diff --git a/.devcontainer.json b/.devcontainer.json index 05cc6697d8..6fda67b28f 100644 --- a/.devcontainer.json +++ b/.devcontainer.json @@ -1,5 +1,5 @@ { - "name": "rain.orderbook dev", + "name": "raindex dev", "image": "ghcr.io/zombiezen/codespaces-nix", "remoteUser": "vscode", "features": { diff --git a/.gas-snapshot b/.gas-snapshot index 9dbd13cfd0..aa021c2444 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,261 +1,359 @@ -GenericPoolOrderBookV6ArbOrderTakerExpressionTest:testGenericPoolTakeOrdersExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256[],uint256[]) (runs: 21, μ: 380135, ~: 377444) -GenericPoolOrderBookV6ArbOrderTakerExpressionTest:testGenericPoolTakeOrdersWrongExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,address,bytes)) (runs: 21, μ: 144678, ~: 139362) -GenericPoolOrderBookV6ArbOrderTakerSenderTest:testGenericPoolTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 21, μ: 293508, ~: 311336) -GenericPoolOrderBookV6FlashBorrowerTest:testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 21, μ: 458264, ~: 489243) -LibOrderTest:testHashEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 111, μ: 170926, ~: 166248) -LibOrderTest:testHashNotEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 111, μ: 231155, ~: 233733) -OrderBookV5FlashBorrowerIERC165Test:testOrderBookV5FlashBorrowerIERC165(bytes4) (runs: 5106, μ: 2289436, ~: 2289436) -OrderBookV6AddOrderEnactTest:testAddLiveOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 938532, ~: 893129) -OrderBookV6AddOrderEnactTest:testAddLiveOrderRevertNoAdd(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 699398, ~: 666288) -OrderBookV6AddOrderEnactTest:testAddOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 1042861, ~: 1006504) -OrderBookV6AddOrderEnactTest:testAddOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 626703, ~: 595830) -OrderBookV6AddOrderEnactTest:testAddOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 685702, ~: 654818) -OrderBookV6AddOrderEnactTest:testAddOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 671083, ~: 640199) -OrderBookV6AddOrderEnactTest:testAddOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 3022963, ~: 2976578) -OrderBookV6AddOrderEnactTest:testAddOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 911048, ~: 880123) -OrderBookV6AddOrderEnactTest:testAddOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 1297701, ~: 1241519) -OrderBookV6AddOrderMockTest:testAddOrderSameAccountWithDifferentConfig(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 111, μ: 2158663, ~: 2100666) -OrderBookV6AddOrderMockTest:testAddOrderTwoAccountsWithDifferentConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 111, μ: 1951982, ~: 1956511) -OrderBookV6AddOrderMockTest:testAddOrderTwoAccountsWithSameConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 1843239, ~: 1886059) -OrderBookV6AddOrderMockTest:testAddOrderWithCalculationsInputsAndOutputsSucceeds(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 110, μ: 964508, ~: 924631) -OrderBookV6AddOrderMockTest:testAddOrderWithNonEmptyMetaEmitsMetaV1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 110, μ: 973045, ~: 933008) -OrderBookV6AddOrderMockTest:testAddOrderWithNonEmptyMetaReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 110, μ: 555088, ~: 533636) -OrderBookV6AddOrderMockTest:testAddOrderWithoutCalculationsDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 541024, ~: 525175) -OrderBookV6AddOrderMockTest:testAddOrderWithoutInputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 131604, ~: 125294) -OrderBookV6AddOrderMockTest:testAddOrderWithoutOutputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 131166, ~: 119362) -OrderBookV6AddOrderNonceTest:testAddOrderNonceDifferentNonceStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes32) (runs: 111, μ: 959655, ~: 919681) -OrderBookV6AddOrderNonceTest:testAddOrderNonceSameNonceDifferentOrderStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1208487, ~: 1205005) -OrderBookV6AddOrderNonceTest:testAddOrderNonceSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 769098, ~: 745872) -OrderBookV6AddOrderOwnerTest:testAddOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 111, μ: 1032070, ~: 1010540) -OrderBookV6AddOrderOwnerTest:testAddOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 769201, ~: 745975) -OrderBookV6AddOrderTest:testAddOrderRealCalculateInputsReverts1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 532777, ~: 517877) -OrderBookV6AddOrderTest:testAddOrderRealCalculateInputsReverts2(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 534556, ~: 519656) -OrderBookV6AddOrderTest:testAddOrderRealCalculateInputsRevertsPreference(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 534141, ~: 519241) -OrderBookV6AddOrderTest:testAddOrderRealNoHandleIODeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 525069, ~: 510169) -OrderBookV6AddOrderTest:testAddOrderRealNoSourcesDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 504519, ~: 489623) -OrderBookV6AddOrderTest:testAddOrderRealOneStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 537135, ~: 522235) -OrderBookV6AddOrderTest:testAddOrderRealThreeStackCalculate(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 549604, ~: 534704) -OrderBookV6AddOrderTest:testAddOrderRealTwoStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 543268, ~: 528368) -OrderBookV6AddOrderTest:testAddOrderRealZeroStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 531499, ~: 516599) -OrderBookV6ArbOrderTakerContextTest:testOrderBookV6ArbOrderTakerContext() (gas: 2046356) -OrderBookV6ArbOrderTakerIERC165Test:testOrderBookV6ArbOrderTakerIERC165(bytes4) (runs: 5107, μ: 1772793, ~: 1772793) -OrderBookV6ClearHandleIORevertTest:testClearOrderAliceNoHandleIORevert() (gas: 622225) -OrderBookV6ClearHandleIORevertTest:testClearOrderBobNoHandleIORevert() (gas: 622160) -OrderBookV6ClearHandleIORevertTest:testClearOrderBothNoHandleIORevert() (gas: 601345) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO0() (gas: 653977) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO1() (gas: 650317) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO2() (gas: 650459) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO3() (gas: 653933) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO4() (gas: 717684) -OrderBookV6ClearHandleIORevertTest:testClearOrderHandleIO5() (gas: 681804) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1882942, ~: 1929303) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1963370, ~: 2003414) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1970194, ~: 2010237) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneOtherOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1902341, ~: 1948708) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1896164, ~: 1942531) -OrderBookV6ClearOrderBadStackTest:testClearOrderBadStackOtherEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1895538, ~: 1941899) -OrderBookV6ClearOrderContextTest:testContextEmptyStack(address,address,bytes32,bytes32,bytes32,bytes32) (runs: 20, μ: 2190636, ~: 2200939) -OrderBookV6ClearSameTokenTest:testClearSameToken(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 1554816, ~: 1599535) -OrderBookV6ClearTest:testClear2ZeroRatioAliceAndBob(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3607727, ~: 3672618) -OrderBookV6ClearTest:testClear2ZeroRatioAliceOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3629011, ~: 3693902) -OrderBookV6ClearTest:testClear2ZeroRatioBobOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3632533, ~: 3697424) -OrderBookV6ClearTest:testClearFuzzIoRatioError(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 110, μ: 3629502, ~: 3646896) -OrderBookV6ClearTest:testClearFuzzIoRatioHappy(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 110, μ: 3669003, ~: 3686586) -OrderBookV6ClearTest:testClearSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 110, μ: 3697336, ~: 3762214) -OrderBookV6ClearZeroAmountTest:testClearZeroAmount(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 2401419, ~: 2465074) -OrderBookV6DepositEnactTest:testDepositRevertInAction(address,bytes32,uint256) (runs: 20, μ: 126750, ~: 126611) -OrderBookV6DepositEnactTest:testOrderBookDepositEnactEmptyNoop(address,bytes32,uint256) (runs: 20, μ: 75554, ~: 75415) -OrderBookV6DepositEnactTest:testOrderBookDepositEnactOneReadState(address,bytes32,uint256) (runs: 20, μ: 135813, ~: 135674) -OrderBookV6DepositEnactTest:testOrderBookDepositEnactOneStateless(address,bytes32,uint256) (runs: 20, μ: 121217, ~: 121078) -OrderBookV6DepositEnactTest:testOrderBookDepositEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256) (runs: 21, μ: 976699, ~: 976643) -OrderBookV6DepositEnactTest:testOrderBookDepositEvalWriteStateSequential(address,bytes32,uint256) (runs: 20, μ: 610978, ~: 610814) -OrderBookV6DepositEnactTest:testOrderBookDepositEvalWriteStateSingle(address,bytes32,uint256) (runs: 20, μ: 243540, ~: 243376) -OrderBookV6DepositEnactTest:testOrderDepositContext(address,bytes32,uint256,uint256) (runs: 20, μ: 704598, ~: 712253) -OrderBookV6DepositTest:testDepositEvent(address,bytes32,uint256) (runs: 110, μ: 71729, ~: 71627) -OrderBookV6DepositTest:testDepositFail(address,bytes32,uint256) (runs: 110, μ: 1040466626, ~: 1040466489) -OrderBookV6DepositTest:testDepositGas00() (gas: 15740) -OrderBookV6DepositTest:testDepositGas01() (gas: 64054) -OrderBookV6DepositTest:testDepositMany((address,address,bytes32,uint256,bytes32)[]) (runs: 105, μ: 8966192, ~: 7864680) -OrderBookV6DepositTest:testDepositReentrancy(address,bytes32,uint256,address,bytes32,uint256) (runs: 110, μ: 544961, ~: 544994) -OrderBookV6DepositTest:testDepositSimple(address,bytes32,uint256) (runs: 110, μ: 71178, ~: 71076) -OrderBookV6DepositTest:testDepositZero(address,bytes32) (runs: 110, μ: 13961, ~: 13961) -OrderBookV6DepositTest:testDepositZeroVaultId(address,address,bytes32) (runs: 5106, μ: 13834, ~: 13834) -OrderBookV6EnactTest:testOrderBookEvalEmptyNoop(address) (runs: 111, μ: 14260, ~: 14260) -OrderBookV6EnactTest:testOrderBookEvalOneReadState(address) (runs: 111, μ: 71892, ~: 71892) -OrderBookV6EnactTest:testOrderBookEvalOneStateless(address) (runs: 111, μ: 57276, ~: 57276) -OrderBookV6EnactTest:testOrderBookEvalWriteStateDifferentOwnersNamespaced(address,address) (runs: 111, μ: 837360, ~: 837360) -OrderBookV6EnactTest:testOrderBookEvalWriteStateSequential() (gas: 523537) -OrderBookV6EnactTest:testOrderBookEvalWriteStateSingle(address) (runs: 111, μ: 166224, ~: 166224) -OrderBookV6FlashLenderFeeTest:testFlashFee(address,uint256) (runs: 5107, μ: 3798, ~: 3798) -OrderBookV6FlashLenderGriefRecipientTest:testFlashLoanToNonReceiver(uint256,bytes,bytes32,bytes) (runs: 5107, μ: 24272, ~: 24264) -OrderBookV6FlashLenderIERC165Test:testOrderBookV6FlashLenderIERC165(bytes4) (runs: 5106, μ: 366649, ~: 366649) -OrderBookV6FlashLenderMaxFlashLoanTest:testFlashMaxLoan(uint256) (runs: 5107, μ: 7448, ~: 7448) -OrderBookV6FlashLenderMockSuccessTest:testFlashLoanToReceiver(uint256,bytes) (runs: 5107, μ: 11830, ~: 11823) -OrderBookV6FlashLenderReentrant:testReenterAddOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 12750576, ~: 12992923) -OrderBookV6FlashLenderReentrant:testReenterCheckOrderExists(bytes32,uint256) (runs: 111, μ: 439689, ~: 439869) -OrderBookV6FlashLenderReentrant:testReenterClear(uint256,address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 26779445, ~: 27488840) -OrderBookV6FlashLenderReentrant:testReenterDeposit(uint256,uint256,uint256) (runs: 110, μ: 569731, ~: 569629) -OrderBookV6FlashLenderReentrant:testReenterReadVaultBalances(uint256,uint256) (runs: 110, μ: 485330, ~: 485330) -OrderBookV6FlashLenderReentrant:testReenterRemoveOrder(uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 111, μ: 11743403, ~: 11288049) -OrderBookV6FlashLenderReentrant:testReenterTakeOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 13310258, ~: 13510950) -OrderBookV6FlashLenderReentrant:testReenterWithdraw(uint256,uint256,uint256) (runs: 110, μ: 551216, ~: 551114) -OrderBookV6FlashLenderTransferTest:testFlashLoanTransferFail(uint256,uint256,bool) (runs: 111, μ: 946830, ~: 947862) -OrderBookV6FlashLenderTransferTest:testFlashLoanTransferSuccess(uint256,bool) (runs: 111, μ: 900641, ~: 909733) -OrderBookV6QuoteSameTokenTest:testQuoteSameToken(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 20, μ: 8048353, ~: 7621050) -OrderBookV6QuoteTest:testQuoteContextSender(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 111, μ: 8960848, ~: 9260272) -OrderBookV6QuoteTest:testQuoteDeadOrder(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 111, μ: 6501720, ~: 5431388) -OrderBookV6QuoteTest:testQuoteMaxOutput(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 111, μ: 1029816, ~: 1064091) -OrderBookV6QuoteTest:testQuoteSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 111, μ: 1023609, ~: 1057753) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 647606, ~: 636057) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderDeadOrder(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 329892, ~: 321107) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 835598, ~: 810182) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 894799, ~: 869378) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 880269, ~: 854848) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderRevertInAction(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 993761, ~: 965665) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 4120695, ~: 4041924) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1120935, ~: 1095486) -OrderBookV6RemoveOrderEnactTest:testRemoveOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 1732289, ~: 1684183) -OrderBookV6RemoveOrderMockTest:testRemoveOrderAddRemoveMulti(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 5275817, ~: 5035488) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDifferent(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 3689120, ~: 3616789) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDifferentOwners(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 3526613, ~: 3602387) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDifferentOwnersDifferent(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 7138579, ~: 7078430) -OrderBookV6RemoveOrderMockTest:testRemoveOrderDoesNotExist(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 361112, ~: 346529) -OrderBookV6RemoveOrderMockTest:testRemoveOrderOnlyOwner(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 111, μ: 1940170, ~: 1983960) -OrderBookV6RemoveOrderOwnerTest:testRemoveOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 111, μ: 4620921, ~: 4480522) -OrderBookV6RemoveOrderOwnerTest:testRemoveOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 2576783, ~: 2491125) -OrderBookV6RemoveOrderOwnerTest:testRemoveOrderWrongOwner(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 111, μ: 667386, ~: 653431) -OrderBookV6SubParserContextCalculatedIORatioTest:testSubParserContextHappy() (gas: 2065358) -OrderBookV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042454) -OrderBookV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028887) -OrderBookV6SubParserContextCalculatedMaxOutputTest:testSubParserContextHappy() (gas: 2065685) -OrderBookV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042777) -OrderBookV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029215) -OrderBookV6SubParserContextInputTokenDecimalsTest:testSubParserContextHappy() (gas: 2065524) -OrderBookV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042616) -OrderBookV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029053) -OrderBookV6SubParserContextInputTokenTest:testSubParserContextHappy() (gas: 2064061) -OrderBookV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041154) -OrderBookV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027591) -OrderBookV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 2065196) -OrderBookV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042292) -OrderBookV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028725) -OrderBookV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextHappy() (gas: 2065524) -OrderBookV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042616) -OrderBookV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029053) -OrderBookV6SubParserContextInputVaultIdTest:testSubParserContextHappy() (gas: 2064548) -OrderBookV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041641) -OrderBookV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028077) -OrderBookV6SubParserContextOrderBookTest:testSubParserContextHappy() (gas: 2063737) -OrderBookV6SubParserContextOrderBookTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2040830) -OrderBookV6SubParserContextOrderBookTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027267) -OrderBookV6SubParserContextOrderClearerTest:testSubParserContextHappy() (gas: 2064385) -OrderBookV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041478) -OrderBookV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027915) -OrderBookV6SubParserContextOrderCounterpartyTest:testSubParserContextHappy() (gas: 2065196) -OrderBookV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042292) -OrderBookV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028725) -OrderBookV6SubParserContextOrderHashTest:testSubParserContextHappy() (gas: 2063899) -OrderBookV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2040992) -OrderBookV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027429) -OrderBookV6SubParserContextOrderOwnerTest:testSubParserContextHappy() (gas: 2064062) -OrderBookV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041155) -OrderBookV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027591) -OrderBookV6SubParserContextOutputTokenDecimalsTest:testSubParserContextHappy() (gas: 2065686) -OrderBookV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042778) -OrderBookV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029215) -OrderBookV6SubParserContextOutputTokenTest:testSubParserContextHappy() (gas: 2064223) -OrderBookV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041316) -OrderBookV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2027753) -OrderBookV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 2065358) -OrderBookV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042454) -OrderBookV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028887) -OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextHappy() (gas: 2065686) -OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2042778) -OrderBookV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2029215) -OrderBookV6SubParserContextOutputVaultIdTest:testSubParserContextHappy() (gas: 2064710) -OrderBookV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 2041803) -OrderBookV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 2028239) -OrderBookV6SubParserDescribedByMetaV1Test:testOrderBookV6SubParserDescribedByMetaV1Happy() (gas: 1978249) -OrderBookV6SubParserIERC165Test:testOrderBookV6SubParserIERC165(bytes4) (runs: 5107, μ: 1984624, ~: 1984624) -OrderBookV6SubParserPointersTest:testSubParserFunctionPointers() (gas: 1990810) -OrderBookV6SubParserPointersTest:testSubParserOperandParsers() (gas: 1990832) -OrderBookV6SubParserPointersTest:testSubParserParseMeta() (gas: 102268) -OrderBookV6SubParserPointersTest:testWordOperandLengthEquivalence() (gas: 880) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy0() (gas: 2070733) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy1() (gas: 2070844) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy2() (gas: 2070845) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextHappy3() (gas: 2071044) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyInput() (gas: 2047674) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyNoOperand() (gas: 2025115) -OrderBookV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyTooManyOperands() (gas: 2033428) -OrderBookV6SubParserSignersTest:testSubParserContextSignerHappy0() (gas: 2066224) -OrderBookV6SubParserSignersTest:testSubParserContextSignerHappy1() (gas: 2066357) -OrderBookV6SubParserSignersTest:testSubParserContextSignerUnhappyInput() (gas: 2043150) -OrderBookV6SubParserSignersTest:testSubParserContextSignerUnhappyNoOperand() (gas: 2023791) -OrderBookV6SubParserSignersTest:testSubParserContextSignerUnhappyTooManyOperands() (gas: 2029364) -OrderBookV6TakeOrderBadStackTest:testTakeOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 837592, ~: 819326) -OrderBookV6TakeOrderBadStackTest:testTakeOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 111, μ: 844134, ~: 825865) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO00() (gas: 300477) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO1() (gas: 476823) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO10(uint256) (runs: 111, μ: 689086, ~: 644493) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO2() (gas: 490964) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO3() (gas: 647361) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO4() (gas: 663992) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO5() (gas: 663977) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO6() (gas: 649805) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO7(uint256) (runs: 111, μ: 917280, ~: 917519) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO8(uint256) (runs: 111, μ: 1088554, ~: 1088759) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO9(uint256) (runs: 111, μ: 761764, ~: 694136) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert0() (gas: 296236) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert1() (gas: 466195) -OrderBookV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert2() (gas: 452034) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersMultipleOwners(uint256,uint256,uint256) (runs: 111, μ: 551087, ~: 561254) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersSingleOwner(uint256,uint256) (runs: 111, μ: 481846, ~: 503807) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleAnyDeposit(uint256,uint256) (runs: 111, μ: 326192, ~: 328902) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumInput(uint256,uint256) (runs: 111, μ: 303853, ~: 304538) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumOutput(uint256) (runs: 111, μ: 305611, ~: 305561) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderUnlimitedMax(uint256) (runs: 111, μ: 298579, ~: 298374) -OrderBookV6TakeOrderMaximumInputTest:testTakeOrderNoopZeroMaxTakerInput((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 110, μ: 167510, ~: 162007) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrders(uint256,uint256) (runs: 111, μ: 495888, ~: 517956) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersDifferentOwners(uint256,uint256,uint256) (runs: 111, μ: 571993, ~: 587785) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDeposit(uint256,uint256) (runs: 111, μ: 334413, ~: 338379) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedByVault(uint256,uint256) (runs: 111, μ: 311018, ~: 311728) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedMax(uint256) (runs: 111, μ: 310092, ~: 310364) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderUnlimitedMax(uint256) (runs: 111, μ: 305934, ~: 305681) -OrderBookV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputZero((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 5106, μ: 162495, ~: 161657) -OrderBookV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderOne((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)) (runs: 110, μ: 428237, ~: 435942) -OrderBookV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderTwo((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256,(address,bytes32[],bytes),(address,bytes32[],bytes)) (runs: 110, μ: 757840, ~: 758206) -OrderBookV6TakeOrderNoopTest:testTakeOrderNoopZeroOrders() (gas: 13193) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad01() (gas: 303557) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad02() (gas: 303535) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad03() (gas: 305274) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad04() (gas: 305252) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad05() (gas: 305231) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad06() (gas: 305296) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad07() (gas: 304209) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad08() (gas: 304186) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad09() (gas: 304232) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad10() (gas: 304187) -OrderBookV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad11() (gas: 304651) -OrderBookV6TakeOrderSameTokenTest:testTakeOrderSameToken(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 21, μ: 756980, ~: 718387) -OrderBookV6TakeOrderTokenMismatchTest:testTokenDecimalMismatchOutputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 20, μ: 555505, ~: 571000) -OrderBookV6TakeOrderTokenMismatchTest:testTokenMismatchInputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 20, μ: 555338, ~: 570833) -OrderBookV6VaultBalanceTest:testVaultBalanceNoDeposits(address,bytes32) (runs: 5106, μ: 9163, ~: 9163) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalEmptyNoop(address,bytes32,uint256,uint256) (runs: 110, μ: 98383, ~: 99323) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalOneReadState(address,bytes32,uint256,uint256) (runs: 110, μ: 158597, ~: 159539) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalOneStateless(address,bytes32,uint256,uint256) (runs: 110, μ: 143960, ~: 144902) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256,uint256) (runs: 111, μ: 1060219, ~: 1063023) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalWriteStateSequential(address,bytes32,uint256,uint256) (runs: 110, μ: 655960, ~: 656978) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawEvalWriteStateSingle(address,bytes32,uint256,uint256) (runs: 110, μ: 287751, ~: 288769) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawalEvalRevertInAction(address,bytes32,uint256,uint256) (runs: 110, μ: 142932, ~: 143874) -OrderBookV6WithdrawEvalTest:testOrderBookWithdrawalEvalZeroAmountEvalNoop(address,bytes32,uint256) (runs: 110, μ: 110929, ~: 110665) -OrderBookV6WithdrawEvalTest:testOrderWithdrawContext(address,bytes32,uint256,uint256) (runs: 110, μ: 774807, ~: 771817) -OrderBookV6WithdrawTest:testWithdrawEmptyVault(address,bytes32,uint256) (runs: 110, μ: 57644, ~: 57548) -OrderBookV6WithdrawTest:testWithdrawFailure(address,bytes32,uint256,uint256) (runs: 110, μ: 1040421911, ~: 1040404236) -OrderBookV6WithdrawTest:testWithdrawFullVault(address,bytes32,uint256,uint256) (runs: 110, μ: 79571, ~: 79798) -OrderBookV6WithdrawTest:testWithdrawMany((bool,address,address,bytes32,uint256,bytes32,uint256,bool)[]) (runs: 111, μ: 7409843, ~: 7190842) -OrderBookV6WithdrawTest:testWithdrawPartialVault(address,bytes32,uint256,uint256) (runs: 110, μ: 95763, ~: 95791) -OrderBookV6WithdrawTest:testWithdrawZero(address,address,bytes32) (runs: 111, μ: 13621, ~: 13621) -RouteProcessorOrderBookV6ArbOrderTakerExpressionTest:testRouteProcessorTakeOrdersExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256[],uint256[]) (runs: 111, μ: 361296, ~: 355146) -RouteProcessorOrderBookV6ArbOrderTakerExpressionTest:testRouteProcessorTakeOrdersWrongExpression((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,address,bytes)) (runs: 111, μ: 139968, ~: 136952) -RouteProcessorOrderBookV6ArbOrderTakerSenderTest:testRouteProcessorTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 111, μ: 272813, ~: 263019) \ No newline at end of file +GenericPoolRaindexV6ArbOrderTakerApprovalRevokedTest:testApprovalRevokedAfterOnTakeOrders2() (gas: 4187360) +GenericPoolRaindexV6ArbOrderTakerExchangeRevertTest:testExchangeRevertPropagates() (gas: 4010015) +GenericPoolRaindexV6ArbOrderTakerSenderTest:testGenericPoolTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 10, μ: 240617, ~: 236170) +GenericPoolRaindexV6FlashBorrowerApprovalRevokedTest:testApprovalRevokedAfterExchange() (gas: 4791226) +GenericPoolRaindexV6FlashBorrowerEthForwardedTest:testEthForwardedToExchangeDuringExchange() (gas: 4831176) +GenericPoolRaindexV6FlashBorrowerExchangeRevertTest:testExchangeRevertPropagates() (gas: 4645831) +GenericPoolRaindexV6FlashBorrowerTest:testGenericPoolRaindexV6FlashBorrowerTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 10, μ: 376819, ~: 368454) +LibOrderTest:testHashEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 100, μ: 162224, ~: 170137) +LibOrderTest:testHashNotEqual((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 100, μ: 326762, ~: 323279) +LibRaindexArbFinalizeArbNativeGasTest:testFinalizeArbSendsNativeGas() (gas: 4122396) +LibRaindexArbFinalizeArbOutputTokenProfitTest:testFinalizeArbTransfersOutputTokenProfit() (gas: 4128389) +LibRaindexArbFinalizeArbTaskContextTest:testFinalizeArbTaskContextValues() (gas: 4295096) +LibRaindexArbFinalizeArbTokenTransfersTest:testFinalizeArbTransfersInputTokenProfit() (gas: 4125310) +LibRaindexDeploySubgraphYamlAddressTest:testSubgraphYamlAddress() (gas: 5161) +LibRaindexDeployTest:testCreationCodeRaindex() (gas: 22417) +LibRaindexDeployTest:testCreationCodeSubParser() (gas: 8512) +LibRaindexDeployTest:testDeployAddressGenericPoolArbOrderTaker() (gas: 1720808) +LibRaindexDeployTest:testDeployAddressGenericPoolFlashBorrower() (gas: 2271572) +LibRaindexDeployTest:testDeployAddressRaindex() (gas: 4768334) +LibRaindexDeployTest:testDeployAddressRouteProcessor() (gas: 3235853) +LibRaindexDeployTest:testDeployAddressRouteProcessorArbOrderTaker() (gas: 1850834) +LibRaindexDeployTest:testDeployAddressSubParser() (gas: 1963503) +LibRaindexDeployTest:testEtchRaindex() (gas: 36203) +LibRaindexDeployTest:testEtchRaindexIdempotent() (gas: 36646) +LibRaindexDeployTest:testExpectedCodeHashGenericPoolArbOrderTaker() (gas: 1713609) +LibRaindexDeployTest:testExpectedCodeHashGenericPoolFlashBorrower() (gas: 2263196) +LibRaindexDeployTest:testExpectedCodeHashRaindex() (gas: 4754446) +LibRaindexDeployTest:testExpectedCodeHashRouteProcessorArbOrderTaker() (gas: 1843310) +LibRaindexDeployTest:testExpectedCodeHashSubParser() (gas: 1955756) +LibRaindexDeployTest:testGeneratedCodehashGenericPoolArbOrderTaker() (gas: 289) +LibRaindexDeployTest:testGeneratedCodehashGenericPoolFlashBorrower() (gas: 311) +LibRaindexDeployTest:testGeneratedCodehashRouteProcessor() (gas: 269) +LibRaindexDeployTest:testGeneratedCodehashRouteProcessorArbOrderTaker() (gas: 267) +LibRaindexDeployTest:testGeneratedDeployedAddressGenericPoolArbOrderTaker() (gas: 306) +LibRaindexDeployTest:testGeneratedDeployedAddressGenericPoolFlashBorrower() (gas: 349) +LibRaindexDeployTest:testGeneratedDeployedAddressRaindex() (gas: 304) +LibRaindexDeployTest:testGeneratedDeployedAddressRouteProcessor() (gas: 326) +LibRaindexDeployTest:testGeneratedDeployedAddressRouteProcessorArbOrderTaker() (gas: 326) +LibRaindexDeployTest:testGeneratedDeployedAddressSubParser() (gas: 325) +LibRaindexDeployTest:testRuntimeCodeGenericPoolArbOrderTaker() (gas: 1719703) +LibRaindexDeployTest:testRuntimeCodeGenericPoolFlashBorrower() (gas: 2271468) +LibRaindexDeployTest:testRuntimeCodeRaindex() (gas: 4773331) +LibRaindexDeployTest:testRuntimeCodeRouteProcessor() (gas: 3241315) +LibRaindexDeployTest:testRuntimeCodeRouteProcessorArbOrderTaker() (gas: 1849931) +LibRaindexDeployTest:testRuntimeCodeSubParser() (gas: 1962851) +LibRouteProcessor4CreationCodeTest:testRouteProcessor4Codehash() (gas: 3225289) +RaindexV6AddOrderEnactTest:testAddLiveOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 839870, ~: 874655) +RaindexV6AddOrderEnactTest:testAddLiveOrderRevertNoAdd(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 630383, ~: 655763) +RaindexV6AddOrderEnactTest:testAddOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 969918, ~: 997197) +RaindexV6AddOrderEnactTest:testAddOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 565679, ~: 589179) +RaindexV6AddOrderEnactTest:testAddOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 625713, ~: 649223) +RaindexV6AddOrderEnactTest:testAddOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 610807, ~: 634317) +RaindexV6AddOrderEnactTest:testAddOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 2968901, ~: 3094080) +RaindexV6AddOrderEnactTest:testAddOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 856258, ~: 879800) +RaindexV6AddOrderEnactTest:testAddOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 1173145, ~: 1216076) +RaindexV6AddOrderMockTest:testAddOrderSameAccountWithDifferentConfig(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 100, μ: 2109643, ~: 2176892) +RaindexV6AddOrderMockTest:testAddOrderTwoAccountsWithDifferentConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,bytes) (runs: 100, μ: 1990458, ~: 2002422) +RaindexV6AddOrderMockTest:testAddOrderTwoAccountsWithSameConfig(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 1813876, ~: 1728783) +RaindexV6AddOrderMockTest:testAddOrderWithCalculationsInputsAndOutputsSucceeds(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 963048, ~: 928089) +RaindexV6AddOrderMockTest:testAddOrderWithNonEmptyMetaEmitsMetaV1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 972560, ~: 926284) +RaindexV6AddOrderMockTest:testAddOrderWithNonEmptyMetaReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 557742, ~: 535883) +RaindexV6AddOrderMockTest:testAddOrderWithoutCalculationsDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 573679, ~: 590764) +RaindexV6AddOrderMockTest:testAddOrderWithoutInputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 150121, ~: 147946) +RaindexV6AddOrderMockTest:testAddOrderWithoutOutputsReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 152178, ~: 151109) +RaindexV6AddOrderNonceTest:testAddOrderNonceDifferentNonceStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes32) (runs: 100, μ: 1015445, ~: 1032856) +RaindexV6AddOrderNonceTest:testAddOrderNonceSameNonceDifferentOrderStateChange(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1235944, ~: 1238440) +RaindexV6AddOrderNonceTest:testAddOrderNonceSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 806423, ~: 831849) +RaindexV6AddOrderOwnerTest:testAddOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 100, μ: 1060302, ~: 1045214) +RaindexV6AddOrderOwnerTest:testAddOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 806526, ~: 831952) +RaindexV6AddOrderTest:testAddOrderRealCalculateInputsReverts1(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 565142, ~: 580853) +RaindexV6AddOrderTest:testAddOrderRealCalculateInputsReverts2(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 567005, ~: 582716) +RaindexV6AddOrderTest:testAddOrderRealCalculateInputsRevertsPreference(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 566593, ~: 582304) +RaindexV6AddOrderTest:testAddOrderRealNoHandleIODeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 557181, ~: 572892) +RaindexV6AddOrderTest:testAddOrderRealNoSourcesDeploys(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 536431, ~: 552138) +RaindexV6AddOrderTest:testAddOrderRealOneStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 569719, ~: 585430) +RaindexV6AddOrderTest:testAddOrderRealThreeStackCalculate(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 582910, ~: 598621) +RaindexV6AddOrderTest:testAddOrderRealTwoStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 576219, ~: 591930) +RaindexV6AddOrderTest:testAddOrderRealZeroStackCalculateReverts(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 563783, ~: 579494) +RaindexV6ArbOrderTakerContextTest:testRaindexV6ArbOrderTakerContext() (gas: 1909351) +RaindexV6ArbOrderTakerFallbackTest:testFallbackAcceptsCalldata() (gas: 3149) +RaindexV6ArbOrderTakerFallbackTest:testFallbackAcceptsETHWithCalldata() (gas: 12730) +RaindexV6ArbOrderTakerFallbackTest:testFallbackAcceptsEmptyCalldata() (gas: 3113) +RaindexV6ArbOrderTakerFallbackTest:testReceiveAcceptsETH() (gas: 12645) +RaindexV6ArbOrderTakerIERC165Test:testRaindexV6ArbOrderTakerIERC165(bytes4) (runs: 5096, μ: 1614805, ~: 1614805) +RaindexV6ArbOrderTakerNoOrdersTest:testArb5NoOrders() (gas: 15971) +RaindexV6ArbOrderTakerOnTakeOrders2DirectTest:testOnTakeOrders2DirectCallSucceeds() (gas: 2894327) +RaindexV6ArbOrderTakerOnTakeOrders2Test:testArb5RealTokenTransfers() (gas: 4097781) +RaindexV6ArbOrderTakerReentrancyTest:testArb5Reentrancy() (gas: 4083416) +RaindexV6ArbTaskGatedCheckTaskHashPassMatchTest:testCheckTaskHashPassesWhenMatch(bytes) (runs: 5096, μ: 351383, ~: 345693) +RaindexV6ArbTaskGatedCheckTaskHashPassZeroTest:testCheckTaskHashPassesWhenZero(bytes) (runs: 5096, μ: 341783, ~: 341410) +RaindexV6ArbTaskGatedCheckTaskHashWrongTaskTest:testCheckTaskHashRevertsWrongTask(bytes,bytes) (runs: 5096, μ: 354707, ~: 349220) +RaindexV6ArbTaskGatedConstructTest:testConstructEmitsEvent(bytes) (runs: 5096, μ: 356294, ~: 346724) +RaindexV6ArbTaskGatedITaskHashNonzeroTest:testITaskHashNonzeroBytecode(bytes) (runs: 5096, μ: 349142, ~: 343723) +RaindexV6ArbTaskGatedITaskHashZeroTest:testITaskHashZeroEmptyBytecode() (gas: 338868) +RaindexV6ClearHandleIORevertTest:testClearOrderAliceNoHandleIORevert() (gas: 640071) +RaindexV6ClearHandleIORevertTest:testClearOrderBobNoHandleIORevert() (gas: 640006) +RaindexV6ClearHandleIORevertTest:testClearOrderBothNoHandleIORevert() (gas: 618788) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO0() (gas: 672615) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO0BothVaultIdZero() (gas: 703035) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO1() (gas: 668742) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO2() (gas: 668884) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO3() (gas: 672571) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO4() (gas: 743080) +RaindexV6ClearHandleIORevertTest:testClearOrderHandleIO5() (gas: 705834) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1954830, ~: 2038606) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 2034775, ~: 2119827) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 2041943, ~: 2127000) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneOtherOne(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1975325, ~: 2059111) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1968745, ~: 2052531) +RaindexV6ClearOrderBadStackTest:testClearOrderBadStackOtherEmpty(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1968176, ~: 2051963) +RaindexV6ClearOrderContextTest:testContextEmptyStack(address,address,bytes32,bytes32,bytes32,bytes32) (runs: 10, μ: 2230716, ~: 2247840) +RaindexV6ClearOrderContextTest:testContextEmptyStackBothVaultIdZero(address,address) (runs: 10, μ: 2044332, ~: 2044852) +RaindexV6ClearSameOwnerTest:testClearSameOwner(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 1180597, ~: 1412796) +RaindexV6ClearSameTokenTest:testClearSameToken(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 1396803, ~: 1440341) +RaindexV6ClearTest:testClear2ZeroRatioAliceAndBob(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1299953, ~: 1291232) +RaindexV6ClearTest:testClear2ZeroRatioAliceOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1321038, ~: 1312522) +RaindexV6ClearTest:testClear2ZeroRatioBobOnly(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1324926, ~: 1316205) +RaindexV6ClearTest:testClearAliceBobOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1332701, ~: 1324295) +RaindexV6ClearTest:testClearAliceBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348404, ~: 1340046) +RaindexV6ClearTest:testClearAliceInputBobBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1335650, ~: 1327016) +RaindexV6ClearTest:testClearAliceInputBobOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348328, ~: 1339809) +RaindexV6ClearTest:testClearAliceInputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1376957, ~: 1368443) +RaindexV6ClearTest:testClearAliceOutputBobBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1320066, ~: 1311384) +RaindexV6ClearTest:testClearAliceOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1361334, ~: 1352984) +RaindexV6ClearTest:testClearAllVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1307093, ~: 1298404) +RaindexV6ClearTest:testClearBobAliceInputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1364313, ~: 1355686) +RaindexV6ClearTest:testClearBobBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348604, ~: 1339979) +RaindexV6ClearTest:testClearBobInputAliceBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1335745, ~: 1327111) +RaindexV6ClearTest:testClearBobInputAliceOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1348698, ~: 1340072) +RaindexV6ClearTest:testClearBobInputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1377296, ~: 1368676) +RaindexV6ClearTest:testClearBobOutputAliceBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1319791, ~: 1311378) +RaindexV6ClearTest:testClearBobOutputVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 100, μ: 1361261, ~: 1352749) +RaindexV6ClearTest:testClearFuzzIoRatioError(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 100, μ: 1312089, ~: 1287974) +RaindexV6ClearTest:testClearFuzzIoRatioHappy(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32,uint256,uint256) (runs: 100, μ: 1370413, ~: 1345387) +RaindexV6ClearTest:testClearSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,address,bytes32,bytes32) (runs: 1000, μ: 1394341, ~: 1374997) +RaindexV6ClearZeroAmountTest:testClearZeroAmount(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 2167411, ~: 2232487) +RaindexV6DepositEnactTest:testDepositRevertInAction(address,bytes32,uint256) (runs: 10, μ: 141395, ~: 141509) +RaindexV6DepositEnactTest:testOrderDepositContext(address,bytes32,uint256,uint256) (runs: 10, μ: 733659, ~: 743522) +RaindexV6DepositEnactTest:testRaindexDepositEnactEmptyNoop(address,bytes32,uint256) (runs: 10, μ: 92085, ~: 92199) +RaindexV6DepositEnactTest:testRaindexDepositEnactOneReadState(address,bytes32,uint256) (runs: 10, μ: 153388, ~: 153502) +RaindexV6DepositEnactTest:testRaindexDepositEnactOneStateless(address,bytes32,uint256) (runs: 10, μ: 138465, ~: 138579) +RaindexV6DepositEnactTest:testRaindexDepositEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256) (runs: 10, μ: 1013146, ~: 1012819) +RaindexV6DepositEnactTest:testRaindexDepositEvalWriteStateSequential(address,bytes32,uint256) (runs: 10, μ: 640232, ~: 640296) +RaindexV6DepositEnactTest:testRaindexDepositEvalWriteStateSingle(address,bytes32,uint256) (runs: 10, μ: 263227, ~: 263291) +RaindexV6DepositTest:testDepositEvent(address,bytes32,uint256) (runs: 100, μ: 88407, ~: 88381) +RaindexV6DepositTest:testDepositFail(address,bytes32,uint256) (runs: 100, μ: 1040483736, ~: 1040483676) +RaindexV6DepositTest:testDepositGas00() (gas: 15751) +RaindexV6DepositTest:testDepositGas01() (gas: 83927) +RaindexV6DepositTest:testDepositMany((address,address,bytes32,uint256,bytes32)[]) (runs: 100, μ: 10354159, ~: 9671538) +RaindexV6DepositTest:testDepositReentrancy(address,bytes32,uint256,address,bytes32,uint256) (runs: 100, μ: 527807, ~: 527879) +RaindexV6DepositTest:testDepositSimple(address,bytes32,uint256) (runs: 100, μ: 87877, ~: 87851) +RaindexV6DepositTest:testDepositZero(address,bytes32) (runs: 100, μ: 31062, ~: 31137) +RaindexV6DepositTest:testDepositZeroVaultId(address,address,bytes32) (runs: 5096, μ: 30908, ~: 31010) +RaindexV6EnactTest:testRaindexEvalEmptyNoop(address) (runs: 100, μ: 34149, ~: 34224) +RaindexV6EnactTest:testRaindexEvalOneReadState(address) (runs: 100, μ: 92873, ~: 92948) +RaindexV6EnactTest:testRaindexEvalOneStateless(address) (runs: 100, μ: 77993, ~: 78068) +RaindexV6EnactTest:testRaindexEvalWriteStateDifferentOwnersNamespaced(address,address) (runs: 100, μ: 878147, ~: 878222) +RaindexV6EnactTest:testRaindexEvalWriteStateSequential() (gas: 556418) +RaindexV6EnactTest:testRaindexEvalWriteStateSingle(address) (runs: 100, μ: 189480, ~: 189555) +RaindexV6FlashBorrowerBadInitiatorTest:testOnFlashLoanBadInitiator(address) (runs: 5096, μ: 11005, ~: 11005) +RaindexV6FlashBorrowerBadLenderApprovalTest:testBadLenderRevertsWithApproval() (gas: 4383922) +RaindexV6FlashBorrowerFallbackTest:testFallbackAcceptsCalldata() (gas: 3149) +RaindexV6FlashBorrowerFallbackTest:testFallbackAcceptsETHWithCalldata() (gas: 12730) +RaindexV6FlashBorrowerFallbackTest:testFallbackAcceptsEmptyCalldata() (gas: 3113) +RaindexV6FlashBorrowerFallbackTest:testReceiveAcceptsETH() (gas: 12645) +RaindexV6FlashBorrowerFlashLoanFailedTest:testFlashLoanFailed() (gas: 4133090) +RaindexV6FlashBorrowerIERC165Test:testRaindexV6FlashBorrowerIERC165(bytes4) (runs: 5096, μ: 2154375, ~: 2154375) +RaindexV6FlashBorrowerLenderValidationTest:testMaliciousLenderCannotExploitOnFlashLoan() (gas: 2954818) +RaindexV6FlashBorrowerMixedDecimalsTest:testArb4MixedDecimals() (gas: 4697995) +RaindexV6FlashBorrowerNoOrdersTest:testArb4NoOrders() (gas: 16224) +RaindexV6FlashBorrowerRealTokenTransfersTest:testArb4RealTokenTransfers() (gas: 4701891) +RaindexV6FlashBorrowerReentrancyTest:testArb4Reentrancy() (gas: 4741194) +RaindexV6FlashLenderFeeTest:testFlashFee(address,uint256) (runs: 5096, μ: 3804, ~: 3804) +RaindexV6FlashLenderGriefRecipientTest:testFlashLoanToNonReceiver(uint256,bytes,bytes32,bytes) (runs: 5096, μ: 25328, ~: 24363) +RaindexV6FlashLenderIERC165Test:testRaindexV6FlashLenderIERC165(bytes4) (runs: 5096, μ: 312268, ~: 312268) +RaindexV6FlashLenderMaxFlashLoanTest:testFlashMaxLoan(uint256) (runs: 5096, μ: 7472, ~: 7472) +RaindexV6FlashLenderMockSuccessTest:testFlashLoanToReceiver(uint256,bytes) (runs: 5096, μ: 12182, ~: 11877) +RaindexV6FlashLenderReentrant:testReenterAddOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 13516112, ~: 14090389) +RaindexV6FlashLenderReentrant:testReenterCheckOrderExists(bytes32,uint256) (runs: 100, μ: 407684, ~: 409475) +RaindexV6FlashLenderReentrant:testReenterClear(uint256,address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 26256780, ~: 27189818) +RaindexV6FlashLenderReentrant:testReenterDeposit(uint256,uint256,uint256) (runs: 100, μ: 555676, ~: 555995) +RaindexV6FlashLenderReentrant:testReenterReadVaultBalances(uint256,uint256) (runs: 100, μ: 454758, ~: 454957) +RaindexV6FlashLenderReentrant:testReenterRemoveOrder(uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32)) (runs: 100, μ: 12516412, ~: 12823819) +RaindexV6FlashLenderReentrant:testReenterTakeOrder(uint256,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 13619158, ~: 13741253) +RaindexV6FlashLenderReentrant:testReenterWithdraw(uint256,uint256,uint256) (runs: 100, μ: 536933, ~: 537451) +RaindexV6FlashLenderTransferTest:testFlashLoanTransferFail(uint256,uint256,bool) (runs: 100, μ: 881755, ~: 883695) +RaindexV6FlashLenderTransferTest:testFlashLoanTransferSuccess(uint256,bool) (runs: 100, μ: 833293, ~: 826424) +RaindexV6QuoteSameTokenTest:testQuoteSameToken(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 10, μ: 9325366, ~: 8700273) +RaindexV6QuoteTest:testQuoteContextSender(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 9063594, ~: 8888604) +RaindexV6QuoteTest:testQuoteDeadOrder(((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)[])) (runs: 100, μ: 8103938, ~: 7514207) +RaindexV6QuoteTest:testQuoteMaxOutput(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 1055942, ~: 1035470) +RaindexV6QuoteTest:testQuoteSimple(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 1049447, ~: 1029711) +RaindexV6QuoteTest:testQuoteSimpleBothVaultIdZero(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),uint256) (runs: 100, μ: 1010867, ~: 991129) +RaindexV6RemoveOrderEnactTest:testRemoveOrderContext(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 676462, ~: 687049) +RaindexV6RemoveOrderEnactTest:testRemoveOrderDeadOrder(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 356482, ~: 364953) +RaindexV6RemoveOrderEnactTest:testRemoveOrderEmptyNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 874495, ~: 903175) +RaindexV6RemoveOrderEnactTest:testRemoveOrderOneReadState(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 934769, ~: 963455) +RaindexV6RemoveOrderEnactTest:testRemoveOrderOneStateless(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 919952, ~: 948638) +RaindexV6RemoveOrderEnactTest:testRemoveOrderRevertInAction(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1032728, ~: 1064218) +RaindexV6RemoveOrderEnactTest:testRemoveOrderWriteStateDifferentOwnersNamespaced(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 4258817, ~: 4113599) +RaindexV6RemoveOrderEnactTest:testRemoveOrderWriteStateSequential(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1166237, ~: 1194937) +RaindexV6RemoveOrderEnactTest:testRemoveOrderWriteStateSingle(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 1791619, ~: 1846282) +RaindexV6RemoveOrderMockTest:testRemoveOrderAddRemoveMulti(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 5232985, ~: 4993442) +RaindexV6RemoveOrderMockTest:testRemoveOrderDifferent(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 3794890, ~: 3971187) +RaindexV6RemoveOrderMockTest:testRemoveOrderDifferentOwners(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 3416772, ~: 3220010) +RaindexV6RemoveOrderMockTest:testRemoveOrderDifferentOwnersDifferent(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 7284202, ~: 7123781) +RaindexV6RemoveOrderMockTest:testRemoveOrderDoesNotExist(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 376436, ~: 362925) +RaindexV6RemoveOrderMockTest:testRemoveOrderOnlyOwner(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),bytes) (runs: 100, μ: 1903567, ~: 1800049) +RaindexV6RemoveOrderOwnerTest:testRemoveOrderOwnerDifferentOwnerStateChange(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 100, μ: 4679006, ~: 4572729) +RaindexV6RemoveOrderOwnerTest:testRemoveOrderOwnerSameOrderNoop(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 2652659, ~: 2741449) +RaindexV6RemoveOrderOwnerTest:testRemoveOrderWrongOwner(((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes),address,address) (runs: 100, μ: 689918, ~: 680133) +RaindexV6SubParserContextCalculatedIORatioTest:testSubParserContextHappy() (gas: 94106) +RaindexV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71681) +RaindexV6SubParserContextCalculatedIORatioTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57743) +RaindexV6SubParserContextCalculatedMaxOutputTest:testSubParserContextHappy() (gas: 94433) +RaindexV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedInputs() (gas: 72004) +RaindexV6SubParserContextCalculatedMaxOutputTest:testSubParserContextUnhappyDisallowedOperand() (gas: 58071) +RaindexV6SubParserContextInputTokenDecimalsTest:testSubParserContextHappy() (gas: 94272) +RaindexV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71843) +RaindexV6SubParserContextInputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57909) +RaindexV6SubParserContextInputTokenTest:testSubParserContextHappy() (gas: 92809) +RaindexV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70381) +RaindexV6SubParserContextInputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56447) +RaindexV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 93944) +RaindexV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71519) +RaindexV6SubParserContextInputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57581) +RaindexV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextHappy() (gas: 94272) +RaindexV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71843) +RaindexV6SubParserContextInputVaultBalanceIncreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57909) +RaindexV6SubParserContextInputVaultIdTest:testSubParserContextHappy() (gas: 94007) +RaindexV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71579) +RaindexV6SubParserContextInputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57644) +RaindexV6SubParserContextOrderClearerTest:testSubParserContextHappy() (gas: 93133) +RaindexV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70705) +RaindexV6SubParserContextOrderClearerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56771) +RaindexV6SubParserContextOrderCounterpartyTest:testSubParserContextHappy() (gas: 93944) +RaindexV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71519) +RaindexV6SubParserContextOrderCounterpartyTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57581) +RaindexV6SubParserContextOrderHashTest:testSubParserContextHappy() (gas: 93358) +RaindexV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70930) +RaindexV6SubParserContextOrderHashTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56996) +RaindexV6SubParserContextOrderOwnerTest:testSubParserContextHappy() (gas: 92810) +RaindexV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70382) +RaindexV6SubParserContextOrderOwnerTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56447) +RaindexV6SubParserContextOutputTokenDecimalsTest:testSubParserContextHappy() (gas: 94434) +RaindexV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedInputs() (gas: 72005) +RaindexV6SubParserContextOutputTokenDecimalsTest:testSubParserContextUnhappyDisallowedOperand() (gas: 58071) +RaindexV6SubParserContextOutputTokenTest:testSubParserContextHappy() (gas: 92971) +RaindexV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedInputs() (gas: 70543) +RaindexV6SubParserContextOutputTokenTest:testSubParserContextUnhappyDisallowedOperand() (gas: 56609) +RaindexV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextHappy() (gas: 94106) +RaindexV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71681) +RaindexV6SubParserContextOutputVaultBalanceBeforeTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57743) +RaindexV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextHappy() (gas: 94434) +RaindexV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedInputs() (gas: 72005) +RaindexV6SubParserContextOutputVaultBalanceDecreaseTest:testSubParserContextUnhappyDisallowedOperand() (gas: 58071) +RaindexV6SubParserContextOutputVaultIdTest:testSubParserContextHappy() (gas: 93458) +RaindexV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedInputs() (gas: 71030) +RaindexV6SubParserContextOutputVaultIdTest:testSubParserContextUnhappyDisallowedOperand() (gas: 57095) +RaindexV6SubParserContextRaindexTest:testSubParserContextHappy() (gas: 92161) +RaindexV6SubParserContextRaindexTest:testSubParserContextUnhappyDisallowedInputs() (gas: 69733) +RaindexV6SubParserContextRaindexTest:testSubParserContextUnhappyDisallowedOperand() (gas: 55799) +RaindexV6SubParserDescribedByMetaV1Test:testRaindexV6SubParserDescribedByMetaV1Happy() (gas: 7351) +RaindexV6SubParserIERC165Test:testRaindexV6SubParserIERC165(bytes4) (runs: 5096, μ: 13077, ~: 13077) +RaindexV6SubParserPointersTest:testSubParserFunctionPointers() (gas: 19234) +RaindexV6SubParserPointersTest:testSubParserOperandParsers() (gas: 19256) +RaindexV6SubParserPointersTest:testSubParserParseMeta() (gas: 104645) +RaindexV6SubParserPointersTest:testWordOperandLengthEquivalence() (gas: 925) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy0() (gas: 99740) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy1() (gas: 99832) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy2() (gas: 99833) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextHappy3() (gas: 100013) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyInput() (gas: 77164) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyNoOperand() (gas: 53858) +RaindexV6SubParserSignedContextTest:testSubParserContextSignedContextUnhappyTooManyOperands() (gas: 62552) +RaindexV6SubParserSignersTest:testSubParserContextSignerHappy0() (gas: 95106) +RaindexV6SubParserSignersTest:testSubParserContextSignerHappy1() (gas: 95220) +RaindexV6SubParserSignersTest:testSubParserContextSignerUnhappyInput() (gas: 72560) +RaindexV6SubParserSignersTest:testSubParserContextSignerUnhappyNoOperand() (gas: 52534) +RaindexV6SubParserSignersTest:testSubParserContextSignerUnhappyTooManyOperands() (gas: 58366) +RaindexV6TakeOrderBadStackTest:testTakeOrderBadStackEmptyStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 882291, ~: 846981) +RaindexV6TakeOrderBadStackTest:testTakeOrderBadStackOneStack(address,address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 100, μ: 889172, ~: 853858) +RaindexV6TakeOrderExceedsMaxRatioTest:testTakeOrderExceedsMaxRatio() (gas: 258233) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO00() (gas: 320920) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO00BothVaultIdZero() (gas: 302984) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO1() (gas: 499705) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO10(uint256) (runs: 100, μ: 710374, ~: 674157) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO2() (gas: 514077) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO3() (gas: 672957) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO4() (gas: 689985) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO5() (gas: 689970) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO6() (gas: 675612) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO7(uint256) (runs: 100, μ: 945377, ~: 945663) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO8(uint256) (runs: 100, μ: 1119342, ~: 1119606) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderHandleIO9(uint256) (runs: 100, μ: 790383, ~: 726129) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert0() (gas: 316087) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert1() (gas: 488717) +RaindexV6TakeOrderHandleIORevertTest:testTakeOrderNoHandleIORevert2() (gas: 474325) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersMultipleOwners(uint256,uint256,uint256) (runs: 100, μ: 554180, ~: 581444) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputMultipleOrdersSingleOwner(uint256,uint256) (runs: 100, μ: 500663, ~: 524679) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleAnyDeposit(uint256,uint256) (runs: 100, μ: 344261, ~: 347866) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleAnyDepositBothVaultIdZero(uint256,uint256) (runs: 100, μ: 302832, ~: 303843) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumInput(uint256,uint256) (runs: 100, μ: 318422, ~: 323492) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderLessThanMaximumOutput(uint256) (runs: 100, μ: 325326, ~: 325230) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderMaximumInputSingleOrderUnlimitedMax(uint256) (runs: 100, μ: 318278, ~: 318237) +RaindexV6TakeOrderMaximumInputTest:testTakeOrderNoopZeroMaxTakerInput((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 100, μ: 172148, ~: 175764) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrders(uint256,uint256) (runs: 100, μ: 516474, ~: 539231) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersBothVaultIdZero(uint256,uint256) (runs: 100, μ: 502885, ~: 520401) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersDifferentOwners(uint256,uint256,uint256) (runs: 100, μ: 579605, ~: 608407) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputMultipleOrdersDifferentOwnersBothVaultIdZero(uint256,uint256,uint256) (runs: 100, μ: 509239, ~: 530794) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDeposit(uint256,uint256) (runs: 100, μ: 354953, ~: 357648) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDepositBothVaultIdZero(uint256,uint256) (runs: 5096, μ: 312790, ~: 313612) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDepositInputVaultIdZero(uint256,uint256) (runs: 5096, μ: 339349, ~: 343084) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleAnyDepositOutputVaultIdZero(uint256,uint256) (runs: 5096, μ: 327105, ~: 328154) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedByVault(uint256,uint256) (runs: 100, μ: 325575, ~: 330816) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderLimitedMax(uint256) (runs: 100, μ: 329932, ~: 330236) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputSingleOrderUnlimitedMax(uint256) (runs: 100, μ: 325868, ~: 325949) +RaindexV6TakeOrderMaximumOutputTest:testTakeOrderMaximumOutputZero((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,bytes32[],bytes)) (runs: 5096, μ: 179347, ~: 178322) +RaindexV6TakeOrderMinimumIOTest:testTakeOrderMinimumIORevert() (gas: 284449) +RaindexV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderOne((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,bytes32[],bytes)) (runs: 100, μ: 449200, ~: 452997) +RaindexV6TakeOrderNoopTest:testTakeOrderNoopNonLiveOrderTwo((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256,(address,bytes32[],bytes),(address,bytes32[],bytes)) (runs: 100, μ: 801426, ~: 788472) +RaindexV6TakeOrderNoopTest:testTakeOrderNoopZeroOrders() (gas: 30529) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad01() (gas: 325437) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad01BothVaultIdZero() (gas: 306756) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad02() (gas: 325438) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad03() (gas: 327154) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad04() (gas: 327132) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad05() (gas: 327089) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad06() (gas: 327110) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad07() (gas: 326067) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad08() (gas: 326044) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad09() (gas: 326024) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad10() (gas: 326067) +RaindexV6TakeOrderPrecisionTest:testTakeOrderPrecisionKnownBad11() (gas: 326509) +RaindexV6TakeOrderSameTokenTest:testTakeOrderSameToken(address,((address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32,bytes32,bytes)) (runs: 10, μ: 672562, ~: 702210) +RaindexV6TakeOrderTokenMismatchTest:testTokenDecimalMismatchOutputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 10, μ: 592418, ~: 592485) +RaindexV6TakeOrderTokenMismatchTest:testTokenMismatchInputs((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,(address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256,uint256,uint256) (runs: 10, μ: 592251, ~: 592318) +RaindexV6VaultBalanceTest:testVaultBalanceNoDeposits(address,address,bytes32) (runs: 5096, μ: 9254, ~: 9254) +RaindexV6WithdrawEvalTest:testOrderWithdrawContext(address,bytes32,uint256,uint256) (runs: 100, μ: 802331, ~: 798475) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalEmptyNoop(address,bytes32,uint256,uint256) (runs: 100, μ: 114405, ~: 115488) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalOneReadState(address,bytes32,uint256,uint256) (runs: 100, μ: 175556, ~: 176639) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalOneStateless(address,bytes32,uint256,uint256) (runs: 100, μ: 160694, ~: 161777) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalWriteStateDifferentOwnersNamespaced(address,address,bytes32,uint256,uint256) (runs: 100, μ: 1096418, ~: 1099893) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalWriteStateSequential(address,bytes32,uint256,uint256) (runs: 100, μ: 684677, ~: 685822) +RaindexV6WithdrawEvalTest:testRaindexWithdrawEvalWriteStateSingle(address,bytes32,uint256,uint256) (runs: 100, μ: 306906, ~: 308051) +RaindexV6WithdrawEvalTest:testRaindexWithdrawalEvalRevertInAction(address,bytes32,uint256,uint256) (runs: 100, μ: 157058, ~: 158141) +RaindexV6WithdrawEvalTest:testRaindexWithdrawalEvalZeroAmountEvalNoop(address,bytes32,uint256) (runs: 100, μ: 125722, ~: 125539) +RaindexV6WithdrawTest:testWithdrawEmptyVault(address,bytes32,uint256) (runs: 100, μ: 74357, ~: 74331) +RaindexV6WithdrawTest:testWithdrawFailure(address,bytes32,uint256,uint256) (runs: 100, μ: 1040425210, ~: 1040443415) +RaindexV6WithdrawTest:testWithdrawFullVault(address,bytes32,uint256,uint256) (runs: 100, μ: 88225, ~: 88257) +RaindexV6WithdrawTest:testWithdrawMany((bool,address,address,bytes32,uint256,bytes32,uint256,bool)[]) (runs: 100, μ: 6625444, ~: 6768896) +RaindexV6WithdrawTest:testWithdrawPartialVault(address,bytes32,uint256,uint256) (runs: 100, μ: 111846, ~: 111815) +RaindexV6WithdrawTest:testWithdrawZero(address,address,bytes32) (runs: 100, μ: 31101, ~: 31151) +RaindexV6WithdrawTest:testWithdrawZeroVaultId(address,address) (runs: 5096, μ: 30266, ~: 30343) +RouteProcessorRaindexV6ArbOrderTakerLossyRoundingTest:testOnTakeOrders2LossyOutputRoundsUp() (gas: 159755) +RouteProcessorRaindexV6ArbOrderTakerNonStandardDecimalsTest:testRouteProcessorArb5SixDecimalTokens() (gas: 4302386) +RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2DirectTest:testOnTakeOrders2DirectCallByAttacker() (gas: 3245122) +RouteProcessorRaindexV6ArbOrderTakerOnTakeOrders2Test:testRouteProcessorArb5() (gas: 4302213) +RouteProcessorRaindexV6ArbOrderTakerSenderTest:testRouteProcessorTakeOrdersSender((address,(address,address,bytes),(address,bytes32)[],(address,bytes32)[],bytes32),uint256,uint256) (runs: 100, μ: 253612, ~: 259029) \ No newline at end of file diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a696e407c1..58d984ee20 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,6 +1,6 @@ > NOTE: Before using this guide, read the repository root `AGENTS.md` for authoritative agent instructions. -# Rain Orderbook – Agent Guide (Concise) +# Raindex – Agent Guide (Concise) Always run commands via Nix: `nix develop -c `. Never cancel long-running tasks (45–90 min builds, 30+ min tests). @@ -8,9 +8,9 @@ Always run commands via Nix: `nix develop -c `. Never cancel long-runni ```bash nix develop -c cargo build nix develop -c cargo build --target wasm32-unknown-unknown --lib -r --workspace \ - --exclude rain_orderbook_cli --exclude rain_orderbook_integration_tests + --exclude raindex_cli --exclude raindex_integration_tests nix develop -c npm install -nix develop -c npm run build:orderbook +nix develop -c npm run build:raindex nix develop -c npm run build:ui ``` @@ -19,7 +19,7 @@ If any step fails due to earlier lint/test issues, use the fallback below. ## 2. Development loop - Edit code - Rebuild dependencies you touched: - - Rust used by `@rainlanguage/orderbook` → `nix develop -c npm run build:orderbook` + - Rust used by `@rainlanguage/raindex` → `nix develop -c npm run build:raindex` - `@rainlanguage/ui-components` → `nix develop -c npm run build -w @rainlanguage/ui-components` - Run targeted tests and lints for changed areas @@ -28,7 +28,7 @@ If any step fails due to earlier lint/test issues, use the fallback below. | Area | Build (if needed) | Lint/Check | Tests | |------|--------------------|------------|-------| | Rust crates (`crates/*`) | `nix develop -c cargo build` | `nix develop -c cargo clippy --workspace --all-targets --all-features -D warnings` | `nix develop -c cargo test --workspace` or `--package ` | -| Orderbook TS (`packages/orderbook`) | `nix develop -c npm run build:orderbook` | `nix develop -c npm run check -w @rainlanguage/orderbook` | `nix develop -c npm run test -w @rainlanguage/orderbook` | +| Raindex TS (`packages/raindex`) | `nix develop -c npm run build:raindex` | `nix develop -c npm run check -w @rainlanguage/raindex` | `nix develop -c npm run test -w @rainlanguage/raindex` | | UI components (`packages/ui-components`) | `nix develop -c npm run build -w @rainlanguage/ui-components` | `nix develop -c npm run svelte-lint-format-check -w @rainlanguage/ui-components` | `nix develop -c npm run test -w @rainlanguage/ui-components` | | Webapp (`packages/webapp`) | `nix develop -c npm run build -w @rainlanguage/webapp` | `nix develop -c npm run svelte-lint-format-check -w @rainlanguage/webapp` | `nix develop -c npm run test -w @rainlanguage/webapp` | | Solidity contracts | `nix develop -c forge build` | — | `nix develop -c forge test` | @@ -48,7 +48,7 @@ Partial commits are OK during the session. Before your final commit of the sessi ```bash ./prep-all.sh nix develop -c npm run lint-format-check:all -nix develop -c npm run build:orderbook # if Rust/orderbook changed +nix develop -c npm run build:raindex # if Rust/raindex changed nix develop -c npm run build:ui nix develop -c cargo test --workspace nix develop -c npm run test @@ -71,8 +71,8 @@ nix develop -c bash -c '(cd lib/rain.interpreter && rainix-sol-prelude && rainix nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.interpreter.interface/lib/rain.math.float && rainix-sol-prelude && rainix-rs-prelude)' nix develop -c bash -c '(cd lib/rain.interpreter/lib/rain.metadata && rainix-sol-prelude && rainix-rs-prelude)' nix develop -c rainix-sol-prelude && nix develop -c rainix-rs-prelude && nix develop -c raindex-prelude -nix develop -c ob-ui-components-prelude -nix develop -c npm run build -w @rainlanguage/orderbook +nix develop -c raindex-ui-components-prelude +nix develop -c npm run build -w @rainlanguage/raindex nix develop -c npm run build -w @rainlanguage/ui-components nix develop -c npm run build -w @rainlanguage/webapp ``` diff --git a/.github/workflows/build-cli-binary.yaml b/.github/workflows/build-cli-binary.yaml index fd33e38a0f..673ab2bc22 100644 --- a/.github/workflows/build-cli-binary.yaml +++ b/.github/workflows/build-cli-binary.yaml @@ -43,7 +43,7 @@ jobs: - run: ./prep-base.sh - name: Build CLI tarball - run: nix develop -c rainix-ob-cli-artifact + run: nix develop -c raindex-cli-artifact - name: Prepare release metadata run: | @@ -51,7 +51,7 @@ jobs: BUILD_TIMESTAMP=$(date -u +"%Y%m%dT%H%M%SZ") echo "TAG_NAME=cli-${SHORT_SHA}-${BUILD_TIMESTAMP}" >> "$GITHUB_ENV" echo "RELEASE_NAME=CLI Binary ${SHORT_SHA} (${BUILD_TIMESTAMP})" >> "$GITHUB_ENV" - echo "ASSET_PATH=crates/cli/bin/rain-orderbook-cli.tar.gz" >> "$GITHUB_ENV" + echo "ASSET_PATH=crates/cli/bin/raindex-cli.tar.gz" >> "$GITHUB_ENV" - name: Publish GitHub release uses: softprops/action-gh-release@v2 diff --git a/.github/workflows/deploy-subgraph.yaml b/.github/workflows/deploy-subgraph.yaml index 972a7633e4..c0e9e51f40 100644 --- a/.github/workflows/deploy-subgraph.yaml +++ b/.github/workflows/deploy-subgraph.yaml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest env: GOLDSKY_TOKEN: ${{ secrets.CI_GOLDSKY_TOKEN }} - GOLDSKY_SUBGRAPH_NAME: ob4 + GOLDSKY_SUBGRAPH_NAME: raindex steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index 68b804ed59..f50e495e56 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -52,7 +52,7 @@ jobs: env: DEPLOYMENT_SUITE: ${{ inputs.suite }} DEPLOY_BROADCAST: "1" - DEPLOYMENT_KEY: ${{ github.ref == 'refs/heads/main' && secrets.PRIVATE_KEY || secrets.PRIVATE_KEY_DEV }} + DEPLOYMENT_KEY: ${{ secrets.PRIVATE_KEY }} ETH_RPC_URL: ${{ secrets.CI_DEPLOY_BASE_RPC_URL || vars.CI_DEPLOY_BASE_RPC_URL || '' }} CI_DEPLOY_ARBITRUM_RPC_URL: ${{ secrets.CI_DEPLOY_ARBITRUM_RPC_URL || vars.CI_DEPLOY_ARBITRUM_RPC_URL || '' }} diff --git a/.github/workflows/npm-package-release.yml b/.github/workflows/npm-package-release.yml index ca17145963..3a676e962d 100644 --- a/.github/workflows/npm-package-release.yml +++ b/.github/workflows/npm-package-release.yml @@ -78,13 +78,13 @@ jobs: run: | echo "Checking repository consistency..." GIT_REPO=$(git remote get-url origin | sed 's/.*github.com[/:]//; s/.git$//') - OB_PKG_REPO=$(node -e "console.log(require('./packages/orderbook/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||') + DEX_PKG_REPO=$(node -e "console.log(require('./packages/raindex/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||') UC_PKG_REPO=$(node -e "console.log(require('./packages/ui-components/package.json').repository?.url || '')" | sed 's|https://github.com/||; s|git+||; s|.git$||') echo "Git remote: $GIT_REPO" - echo "orderbook package.json: $OB_PKG_REPO" + echo "raindex package.json: $DEX_PKG_REPO" echo "ui-components package.json: $UC_PKG_REPO" - if [ "$GIT_REPO" != "$OB_PKG_REPO" ]; then - echo "Repository mismatch for orderbook!" + if [ "$GIT_REPO" != "$DEX_PKG_REPO" ]; then + echo "Repository mismatch for raindex!" echo "This will cause 422 error during publish" exit 1 fi @@ -134,12 +134,12 @@ jobs: - name: Test UI Components run: nix develop -c npm run test -w @rainlanguage/ui-components - # check for npm package blacklists pkgs across all orderbook related packages + # check for npm package blacklists pkgs across all raindex related packages - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: @@ -154,18 +154,18 @@ jobs: # get hash of latest published pkgs from npm and concat them - name: Get Old Hash run: | - OB_PKG_OLD_HASH=$(npm view @rainlanguage/orderbook@latest dist.shasum 2>/dev/null || echo "none") + DEX_PKG_OLD_HASH=$(npm view @rainlanguage/raindex@latest dist.shasum 2>/dev/null || echo "none") UC_PKG_OLD_HASH=$(npm view @rainlanguage/ui-components@latest dist.shasum 2>/dev/null || echo "none") - OLD_HASH=$OB_PKG_OLD_HASH-$UC_PKG_OLD_HASH + OLD_HASH=$DEX_PKG_OLD_HASH-$UC_PKG_OLD_HASH echo "OLD_HASH=$OLD_HASH" >> $GITHUB_ENV echo "old hash: $OLD_HASH" # calc hash of current workspace pkgs by packing them and concat them - name: Get New Hash run: | - OB_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/orderbook | xargs shasum | cut -c1-40) + DEX_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/raindex | xargs shasum | cut -c1-40) UC_PKG_NEW_HASH=$(npm pack --silent -w @rainlanguage/ui-components | xargs shasum | cut -c1-40) - NEW_HASH=$OB_PKG_NEW_HASH-$UC_PKG_NEW_HASH + NEW_HASH=$DEX_PKG_NEW_HASH-$UC_PKG_NEW_HASH echo "NEW_HASH=$NEW_HASH" >> $GITHUB_ENV echo "new hash: $NEW_HASH" rm -f *.tgz @@ -176,27 +176,27 @@ jobs: - name: Set Version if: ${{ env.OLD_HASH != env.NEW_HASH }} run: | - npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/orderbook - NEW_VERSION=$(jq -r '.version' ./packages/orderbook/package.json) + npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/raindex + NEW_VERSION=$(jq -r '.version' ./packages/raindex/package.json) echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV - jq --arg v "$NEW_VERSION" '.dependencies."@rainlanguage/orderbook" = $v' ./packages/ui-components/package.json > tmp.json && mv tmp.json ./packages/ui-components/package.json + jq --arg v "$NEW_VERSION" '.dependencies."@rainlanguage/raindex" = $v' ./packages/ui-components/package.json > tmp.json && mv tmp.json ./packages/ui-components/package.json npx prettier --write ./packages/ui-components/package.json npm version prerelease --preid alpha --no-git-tag-version -w @rainlanguage/ui-components - # Create orderbook npm package tarball - - name: Create orderbook NPM Package Tarball + # Create raindex npm package tarball + - name: Create raindex NPM Package Tarball if: ${{ env.OLD_HASH != env.NEW_HASH }} - run: echo "OB_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/orderbook)" >> $GITHUB_ENV + run: echo "RAINDEX_NPM_PACKAGE=$(npm pack --silent -w @rainlanguage/raindex)" >> $GITHUB_ENV - - name: Rename orderbook NPM Package Tarball + - name: Rename raindex NPM Package Tarball if: ${{ env.OLD_HASH != env.NEW_HASH }} - run: mv ${{ env.OB_NPM_PACKAGE }} orderbook_npm_package_${{ env.NEW_VERSION }}.tgz + run: mv ${{ env.RAINDEX_NPM_PACKAGE }} raindex_npm_package_${{ env.NEW_VERSION }}.tgz - # publish orderbook pkg to npm - - name: Publish orderbook pkg To NPM + # publish raindex pkg to npm + - name: Publish raindex pkg To NPM if: ${{ env.OLD_HASH != env.NEW_HASH }} run: | - npm publish orderbook_npm_package_${{ env.NEW_VERSION }}.tgz \ + npm publish raindex_npm_package_${{ env.NEW_VERSION }}.tgz \ --access public \ --tag latest \ --verbose @@ -223,7 +223,7 @@ jobs: - name: Commit And Tag if: ${{ env.OLD_HASH != env.NEW_HASH }} run: | - git add "packages/orderbook/package.json" + git add "packages/raindex/package.json" git add "packages/ui-components/package.json" git add "package-lock.json" git commit -m "NPM Package Release v${{ env.NEW_VERSION }}" @@ -247,7 +247,7 @@ jobs: tag_name: npm-v${{ env.NEW_VERSION }} name: NPM Package Release v${{ env.NEW_VERSION }} files: | - orderbook_npm_package_${{ env.NEW_VERSION }}.tgz + raindex_npm_package_${{ env.NEW_VERSION }}.tgz ui_components_npm_package_${{ env.NEW_VERSION }}.tgz env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rainix.yaml b/.github/workflows/rainix.yaml index 3139533289..782ffc87e9 100644 --- a/.github/workflows/rainix.yaml +++ b/.github/workflows/rainix.yaml @@ -17,7 +17,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest] - task: [ob-rs-test, rainix-rs-artifacts] + task: [raindex-rs-test, rainix-rs-artifacts] is-not-main: - ${{ github.ref != 'refs/heads/main' }} include: diff --git a/.github/workflows/test-ui-components.yaml b/.github/workflows/test-ui-components.yaml index 11724ca986..be5049c380 100644 --- a/.github/workflows/test-ui-components.yaml +++ b/.github/workflows/test-ui-components.yaml @@ -62,7 +62,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.github/workflows/test-webapp.yaml b/.github/workflows/test-webapp.yaml index e1061e1a16..c1ba4971ad 100644 --- a/.github/workflows/test-webapp.yaml +++ b/.github/workflows/test-webapp.yaml @@ -66,7 +66,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.github/workflows/vercel-docs-preview.yaml b/.github/workflows/vercel-docs-preview.yaml index 406826f2aa..6ff5c97bfc 100644 --- a/.github/workflows/vercel-docs-preview.yaml +++ b/.github/workflows/vercel-docs-preview.yaml @@ -37,13 +37,13 @@ jobs: PUBLIC_WALLETCONNECT_PROJECT_ID: ${{ secrets.WALLETCONNECT_PROJECT_ID }} - run: nix develop .#webapp-shell -c npm run docs - working-directory: packages/orderbook + working-directory: packages/raindex - name: Prepare Vercel build output run: | - OUTPUT_DIR="packages/orderbook/.vercel/output" + OUTPUT_DIR="packages/raindex/.vercel/output" mkdir -p "${OUTPUT_DIR}/static" - cp -r packages/orderbook/docs/* "${OUTPUT_DIR}/static/" + cp -r packages/raindex/docs/* "${OUTPUT_DIR}/static/" echo '{ "version": 3 }' > "${OUTPUT_DIR}/config.json" - name: Install Vercel CLI @@ -51,7 +51,7 @@ jobs: - name: Pull Vercel Environment Information run: vercel pull --yes --environment=preview --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} packages/orderbook + run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }} packages/raindex # forwards status to telegram chat if this ci fails or gets canceled, only runs for default branch - name: Forward CI Status diff --git a/.github/workflows/vercel-docs-prod.yaml b/.github/workflows/vercel-docs-prod.yaml index 4e07d8c0cc..ff1ea4add5 100644 --- a/.github/workflows/vercel-docs-prod.yaml +++ b/.github/workflows/vercel-docs-prod.yaml @@ -30,13 +30,13 @@ jobs: PUBLIC_WALLETCONNECT_PROJECT_ID: ${{ secrets.WALLETCONNECT_PROJECT_ID }} - run: nix develop .#webapp-shell -c npm run docs - working-directory: packages/orderbook + working-directory: packages/raindex - name: Prepare Vercel build output run: | - OUTPUT_DIR="packages/orderbook/.vercel/output" + OUTPUT_DIR="packages/raindex/.vercel/output" mkdir -p "${OUTPUT_DIR}/static" - cp -r packages/orderbook/docs/* "${OUTPUT_DIR}/static/" + cp -r packages/raindex/docs/* "${OUTPUT_DIR}/static/" echo '{ "version": 3 }' > "${OUTPUT_DIR}/config.json" - name: Install Vercel CLI @@ -44,7 +44,7 @@ jobs: - name: Pull Vercel Environment Information run: vercel pull --yes --environment=production --token=${{ secrets.VERCEL_TOKEN }} - name: Deploy Project Artifacts to Vercel - run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} packages/orderbook + run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }} packages/raindex # forwards status to telegram chat if this ci fails or gets canceled, only runs for default branch - name: Forward CI Status diff --git a/.github/workflows/vercel-preview-pr-target.yaml b/.github/workflows/vercel-preview-pr-target.yaml index 6d1e732cb8..f4907004d8 100644 --- a/.github/workflows/vercel-preview-pr-target.yaml +++ b/.github/workflows/vercel-preview-pr-target.yaml @@ -65,7 +65,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.github/workflows/vercel-preview.yaml b/.github/workflows/vercel-preview.yaml index 0346ce3352..eb6bc44d13 100644 --- a/.github/workflows/vercel-preview.yaml +++ b/.github/workflows/vercel-preview.yaml @@ -71,7 +71,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.github/workflows/vercel-prod.yaml b/.github/workflows/vercel-prod.yaml index 554de4e4a3..b278b11e75 100644 --- a/.github/workflows/vercel-prod.yaml +++ b/.github/workflows/vercel-prod.yaml @@ -54,7 +54,7 @@ jobs: - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: - working-directory: packages/orderbook + working-directory: packages/raindex - uses: rainlanguage/github-chore/.github/actions/npm-blacklist@main with: diff --git a/.gitignore b/.gitignore index 0192bcf53d..01a26e9273 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,10 @@ subgraph/tests/.latest.json node_modules temp dist -packages/orderbook/cjs.js -packages/orderbook/cjs.d.ts -packages/orderbook/esm.js -packages/orderbook/esm.d.ts +packages/raindex/cjs.js +packages/raindex/cjs.d.ts +packages/raindex/esm.js +packages/raindex/esm.d.ts .direnv/ # Audit proposed fixes diff --git a/AGENTS.md b/AGENTS.md index 98b5486c95..99c8dffad8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -3,7 +3,7 @@ ## Project Structure & Module Organization - Solidity contracts: `src/`, tests in `test/` with fixtures in `test-resources/`. - Rust workspace: `crates/*` (e.g., `cli`, `common`, `bindings`, `js_api`, `quote`, `subgraph`, `settings`, `math`, `integration_tests`). -- JavaScript/Svelte: `packages/*` — `webapp`, `ui-components`, `orderbook` (wasm wrapper published to npm). +- JavaScript/Svelte: `packages/*` — `webapp`, `ui-components`, `raindex` (wasm wrapper published to npm). - Subgraph and tooling: `subgraph/`, `script/`, helper scripts like `prep-all.sh`. ## Build, Test, and Development Commands @@ -11,7 +11,7 @@ - Rust: `cargo build --workspace`; tests: `cargo test`. - Solidity (Foundry): `forge build`; tests: `forge test`. - Webapp: `cd packages/webapp && npm run dev`. -- JS workspaces (top-level): `npm run test`, `npm run build:ui`, `npm run build:orderbook`. +- JS workspaces (top-level): `npm run test`, `npm run build:ui`, `npm run build:raindex`. - WASM bundle: `rainix-wasm-artifacts`. ## Coding Style & Naming Conventions diff --git a/Cargo.lock b/Cargo.lock index 2629a1b6e7..e2f1a70c0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6865,14 +6865,14 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_app_settings" +name = "raindex_app_settings" version = "0.0.0-alpha.0" dependencies = [ "alloy", "derive_builder 0.20.2", "futures", "httpmock", - "rain_orderbook_bindings", + "raindex_bindings", "reqwest 0.12.20", "serde", "serde_json", @@ -6885,7 +6885,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_bindings" +name = "raindex_bindings" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -6899,7 +6899,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_cli" +name = "raindex_cli" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -6917,12 +6917,12 @@ dependencies = [ "rain-math-float", "rain-metadata 0.0.2-alpha.6", "rain_interpreter_bindings", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_common", - "rain_orderbook_quote", - "rain_orderbook_subgraph_client", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_bindings", + "raindex_common", + "raindex_quote", + "raindex_subgraph_client", + "raindex_test_fixtures", "rusqlite", "rust-bigint", "serde", @@ -6936,7 +6936,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_common" +name = "raindex_common" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -6965,11 +6965,11 @@ dependencies = [ "rain_interpreter_bindings", "rain_interpreter_dispair", "rain_interpreter_parser", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_quote", - "rain_orderbook_subgraph_client", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_bindings", + "raindex_quote", + "raindex_subgraph_client", + "raindex_test_fixtures", "reqwest 0.12.20", "rusqlite", "serde", @@ -6991,20 +6991,20 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_integration_tests" +name = "raindex_integration_tests" version = "0.0.0-alpha.0" dependencies = [ "alloy", "rain-math-float", - "rain_orderbook_app_settings", - "rain_orderbook_common", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_common", + "raindex_test_fixtures", "serde_json", "tokio", ] [[package]] -name = "rain_orderbook_js_api" +name = "raindex_js_api" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7019,11 +7019,11 @@ dependencies = [ "rain-math-float", "rain-metaboard-subgraph", "rain-metadata 0.0.2-alpha.6", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_common", - "rain_orderbook_quote", - "rain_orderbook_subgraph_client", + "raindex_app_settings", + "raindex_bindings", + "raindex_common", + "raindex_quote", + "raindex_subgraph_client", "reqwest 0.12.20", "serde", "serde_json", @@ -7037,7 +7037,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_math" +name = "raindex_math" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7046,7 +7046,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_quote" +name = "raindex_quote" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7062,11 +7062,11 @@ dependencies = [ "rain-interpreter-eval", "rain-math-float", "rain-metadata 0.0.2-alpha.6", - "rain_orderbook_app_settings", - "rain_orderbook_bindings", - "rain_orderbook_common", - "rain_orderbook_subgraph_client", - "rain_orderbook_test_fixtures", + "raindex_app_settings", + "raindex_bindings", + "raindex_common", + "raindex_subgraph_client", + "raindex_test_fixtures", "reqwest 0.12.20", "serde", "serde_json", @@ -7081,11 +7081,11 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_rest_api" +name = "raindex_rest_api" version = "0.0.0-alpha.0" dependencies = [ "alloy", - "rain_orderbook_common", + "raindex_common", "rocket", "rocket_cors", "serde", @@ -7097,7 +7097,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_subgraph_client" +name = "raindex_subgraph_client" version = "0.0.0-alpha.0" dependencies = [ "alloy", @@ -7110,8 +7110,8 @@ dependencies = [ "insta", "once_cell", "rain-math-float", - "rain_orderbook_bindings", - "rain_orderbook_math", + "raindex_bindings", + "raindex_math", "reqwest 0.12.20", "serde", "serde_json", @@ -7122,7 +7122,7 @@ dependencies = [ ] [[package]] -name = "rain_orderbook_test_fixtures" +name = "raindex_test_fixtures" version = "0.0.0-alpha.0" dependencies = [ "alloy", diff --git a/Cargo.toml b/Cargo.toml index 000360d8ee..3e2df4963f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ resolver = "2" edition = "2021" license = "LicenseRef-DCL-1.0" version = "0.0.0-alpha.0" -homepage = "https://github.com/rainprotocol/rain.orderbook" +homepage = "https://github.com/rainprotocol/raindex" [workspace.dependencies] foundry-block-explorers = "0.2.6" @@ -63,34 +63,34 @@ tower = "0.5.2" getrandom = { version = "0.2", features = ["js"] } itertools = "0.14.0" -[workspace.dependencies.rain_orderbook_bindings] +[workspace.dependencies.raindex_bindings] path = "crates/bindings" -[workspace.dependencies.rain_orderbook_common] +[workspace.dependencies.raindex_common] path = "crates/common" -[workspace.dependencies.rain_orderbook_cli] +[workspace.dependencies.raindex_cli] path = "crates/cli" -[workspace.dependencies.rain_orderbook_subgraph_client] +[workspace.dependencies.raindex_subgraph_client] path = "crates/subgraph" -[workspace.dependencies.rain_orderbook_app_settings] +[workspace.dependencies.raindex_app_settings] path = "crates/settings" -[workspace.dependencies.rain_orderbook_quote] +[workspace.dependencies.raindex_quote] path = "crates/quote" -[workspace.dependencies.rain_orderbook_test_fixtures] +[workspace.dependencies.raindex_test_fixtures] path = "crates/test_fixtures" -[workspace.dependencies.rain_orderbook_math] +[workspace.dependencies.raindex_math] path = "crates/math" -[workspace.dependencies.rain_orderbook_js_api] +[workspace.dependencies.raindex_js_api] path = "crates/js_api" -[workspace.dependencies.rain_orderbook_rest_api] +[workspace.dependencies.raindex_rest_api] path = "crates/rest_api" # release profile for wasm build optimized for size reduction diff --git a/README.md b/README.md index 71159711e9..5f650dc2cd 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,25 @@ -# rain.orderbook +# Raindex -Rain Orderbook (also known as Raindex) is an open source, permissionless orderbook system with no fees or admin keys. +Raindex is an open source, permissionless onchain order system with no fees or admin keys. ## Repository Structure This repository contains several components: -- **Solidity Contracts**: The core smart contracts for the Rain Orderbook (`src`) -- **Rust Crates**: Various tooling and libraries for interacting with the Rain Orderbook (`crates/*`) +- **Solidity Contracts**: The core smart contracts for Raindex (`src`) +- **Rust Crates**: Various tooling and libraries for interacting with Raindex (`crates/*`) - **JavaScript Packages (`packages/*`)**: - `webapp`: A SvelteKit site for Raindex - `ui-components`: A shared component library used in the webapp - - `orderbook`: A TypeScript package (published to npm) that provides bindings to the Rust crates + - `raindex`: A TypeScript package (published to npm) that provides bindings to the Rust crates ### Architecture -We use wasm-bindgen to create the `orderbook` package from our Rust crates, which is then used by: +We use wasm-bindgen to create the `raindex` package from our Rust crates, which is then used by: - The UI components library - The webapp -This same package is [published to npm](https://www.npmjs.com/package/@rainlanguage/orderbook), allowing developers to more easily create their own frontends for Raindex. +This same package is [published to npm](https://www.npmjs.com/package/@rainlanguage/raindex), allowing developers to more easily create their own frontends for Raindex. ## Setup for local development @@ -48,8 +48,8 @@ Contracts are deployed via the Foundry script at `script/Deploy.sol`. The script - `DEPLOYMENT_KEY` — the deployer private key - `DEPLOYMENT_SUITE` — which contracts to deploy. One of: - - `raindex` — OrderBookV6 only - - `subparser` — OrderBookV6SubParser only + - `raindex` — RaindexV6 only + - `subparser` — RaindexV6SubParser only - `route-processor` — Sushi RouteProcessor4 only - `arb` — arb contracts only (order takers and flash borrowers) diff --git a/ai_commands/feature-implementation-plan.md b/ai_commands/feature-implementation-plan.md index 47be434ab8..f1111dc218 100644 --- a/ai_commands/feature-implementation-plan.md +++ b/ai_commands/feature-implementation-plan.md @@ -8,7 +8,7 @@ Interactive Start - Ask which areas are likely in scope (check all that apply): - Solidity contracts (`src/`, `test/`, `test-resources/`) - Rust crates (`crates/*` — e.g., `cli`, `common`, `bindings`, `js_api`, `quote`, `subgraph`, `settings`, `math`) - - JS/WASM package (`packages/orderbook`) + - JS/WASM package (`packages/raindex`) - Webapp UI (`packages/webapp`) or UI components (`packages/ui-components`) - Subgraph/indexing (`subgraph/*`) - Tooling/scripts (`script/*`, `.github/*`, `nix.flake`, repo root scripts) @@ -89,7 +89,7 @@ Procedure 4) Detailed implementation plan (by directory) - For each impacted area, list concrete changes with file path anchors where possible. For example: - Rust crates (e.g., `crates/`): modules to add/modify, new types/functions, error handling, feature flags; `Cargo.toml` updates if needed. - - JS/WASM (`packages/orderbook`): new exports, TS types, wasm bindings, build scripts. + - JS/WASM (`packages/raindex`): new exports, TS types, wasm bindings, build scripts. - Webapp (`packages/webapp`): routes/components, stores, API calls, state management, styles. - Contracts (`src/`): new contracts/interfaces/libraries, events, storage layout notes, upgrade path; tests in `test/` with fixtures in `test-resources/`. - Subgraph (`subgraph/`): schema changes, mappings, handlers, data flow and reindex considerations. @@ -164,8 +164,8 @@ Build/Test Commands Reference (use where relevant; reference only — do not exe - Bootstrap: `./prep-all.sh` - Rust: `nix develop -c cargo build --workspace` / `nix develop -c cargo test` - Solidity: `nix develop -c forge build` / `nix develop -c forge test` -- JS workspaces: `npm run test`, `npm run build:ui`, `npm run build:orderbook` -- WASM bundle: `cd packages/orderbook && npm run build-wasm` +- JS workspaces: `npm run test`, `npm run build:ui`, `npm run build:raindex` +- WASM bundle: `cd packages/raindex && npm run build-wasm` - Webapp: `cd packages/webapp && nix develop -c npm run dev` Acceptance Criteria diff --git a/ai_commands/generate-pr-content.md b/ai_commands/generate-pr-content.md index ae7d022151..fff51f6816 100644 --- a/ai_commands/generate-pr-content.md +++ b/ai_commands/generate-pr-content.md @@ -78,7 +78,7 @@ Procedure 3) Draft the title - Format: `: : ` - - Scope: prefer a short identifier like `common`, `js_api`, `orderbook`, `webapp`. + - Scope: prefer a short identifier like `common`, `js_api`, `raindex`, `webapp`. - Summary: 6–12 words, describe outcome, not implementation details. 4) Fill the description template diff --git a/ai_commands/refresh-architecture.md b/ai_commands/refresh-architecture.md index 2d969baedd..d7f1571af9 100644 --- a/ai_commands/refresh-architecture.md +++ b/ai_commands/refresh-architecture.md @@ -3,7 +3,7 @@ Title: Refresh ARCHITECTURE.md for a Given Directory You are an engineering assistant. Your task is to refresh the ARCHITECTURE.md file for a directory specified by the user. The document must accurately describe the current code and behavior in that directory. If the code has changed since the doc was written, identify discrepancies and update the doc to reflect the current state. Inputs -- A path to the target directory inside this repository, provided by the user (e.g., `crates/common`, `packages/orderbook`). +- A path to the target directory inside this repository, provided by the user (e.g., `crates/common`, `packages/raindex`). Constraints and Repo Conventions - Always work inside a Nix shell when running build/test commands (`nix develop -c `). Do not fetch network resources. diff --git a/ai_commands/sdk-documentation-update.md b/ai_commands/sdk-documentation-update.md index f3d2709a72..19dbc6bec6 100644 --- a/ai_commands/sdk-documentation-update.md +++ b/ai_commands/sdk-documentation-update.md @@ -1,16 +1,16 @@ Title: Sync SDK Documentation with Current JS API and Package -You are an engineering assistant. Your task is to verify and update the SDK documentation so it matches the current codebase. The primary source of truth is the Rust JS API in `crates/js_api` (inline docs on items exported via the `wasm_export` macro). You must also validate and update the additional package-level docs in `packages/orderbook` (e.g., README and any in‑package docs) to stay consistent with the built TypeScript surface. +You are an engineering assistant. Your task is to verify and update the SDK documentation so it matches the current codebase. The primary source of truth is the Rust JS API in `crates/js_api` (inline docs on items exported via the `wasm_export` macro). You must also validate and update the additional package-level docs in `packages/raindex` (e.g., README and any in‑package docs) to stay consistent with the built TypeScript surface. Goal - Ensure every JS-facing API exported from `crates/js_api` is documented accurately: names, parameters, parameter descriptions, return types, return descriptions, error semantics, and examples. -- Ensure package documentation in `packages/orderbook` (e.g., README) reflects the current API surface and real usage patterns. +- Ensure package documentation in `packages/raindex` (e.g., README) reflects the current API surface and real usage patterns. - Avoid changing behavior or public API; this task is documentation-only. If you find code/doc conflicts that cannot be resolved with doc edits alone, open/leave a clear TODO note in your summary. Scope - Rust JS API: `crates/js_api/**` — functions, classes, and types reachable from JS via `#[wasm_export]`, `#[wasm_bindgen]`, and `Tsify`. -- Package docs: `packages/orderbook/README.md` and any additional docs in that package. Validate against built declarations `packages/orderbook/{cjs.d.ts,esm.d.ts}` when helpful. -- Cross-check TS usage in `packages/orderbook/test/**/*` to keep examples canonical. +- Package docs: `packages/raindex/README.md` and any additional docs in that package. Validate against built declarations `packages/raindex/{cjs.d.ts,esm.d.ts}` when helpful. +- Cross-check TS usage in `packages/raindex/test/**/*` to keep examples canonical. Constraints and Repo Conventions - Always use a Nix shell for build/test commands: prefix commands with `nix develop -c` (or use appropriate shell attributes). @@ -33,7 +33,7 @@ Procedure - Run the relevant builds and tests to ensure the code is in a good state: - `nix develop -c cargo build --workspace` - `nix develop -c cargo test` - - `cd packages/orderbook && nix develop -c npm run build && nix develop -c npm run test` + - `cd packages/raindex && nix develop -c npm run build && nix develop -c npm run test` 2) Enumerate exported JS API (Rust) - Find all wasm-exported items and their metadata: @@ -49,17 +49,17 @@ Procedure 3) Compare Rust docs to the effective TS surface - Build the package and inspect generated declarations as a quick proxy for the public TS surface: - - `cd packages/orderbook && nix develop -c npm run build` - - Open `packages/orderbook/cjs.d.ts` and `packages/orderbook/esm.d.ts`. + - `cd packages/raindex && nix develop -c npm run build` + - Open `packages/raindex/cjs.d.ts` and `packages/raindex/esm.d.ts`. - Verify that each exported item’s JS name, parameter types/order, and return type match the Rust `wasm_export` metadata. - If you find a mismatch between Rust doc comments/metadata and the generated `.d.ts`, prefer fixing the Rust docs/metadata (not changing code semantics) so docs match actual exports. 4) Reconcile README and examples with canonical usage - Locate examples and usage references in the package README: - - `packages/orderbook/README.md` + - `packages/raindex/README.md` - Cross-check against real usage in tests to keep documentation examples canonical: - - `sg --lang ts -p 'import { $X } from \"@rainlanguage/orderbook\"' packages/orderbook/test` - - Skim `packages/orderbook/test/js_api/*.test.ts` for calls and parameter shapes. + - `sg --lang ts -p 'import { $X } from \"@rainlanguage/raindex\"' packages/raindex/test` + - Skim `packages/raindex/test/js_api/*.test.ts` for calls and parameter shapes. - Ensure examples use correct names, parameter order and types, and demonstrate error handling with `WasmEncodedResult` where relevant. 5) Apply focused edits @@ -68,16 +68,16 @@ Procedure - Ensure each exported function has accurate `param_description` and `return_description` attributes. - Make examples minimal and correct, using the JS-facing `js_name` and showing realistic inputs. - Keep tone consistent with existing docs in this crate. - - In package docs (`packages/orderbook/README.md` and peers): + - In package docs (`packages/raindex/README.md` and peers): - Fix any outdated names, parameters, or return shapes. - Align examples with patterns used in tests (preferred canonical usage). - - Keep imports correct: `import { ... } from '@rainlanguage/orderbook'`. + - Keep imports correct: `import { ... } from '@rainlanguage/raindex'`. 6) Validate - Rust checks: `nix develop -c cargo fmt --all && nix develop -c rainix-rs-static` - - Build artifacts needed for TS surface checks: `cd packages/orderbook && nix develop -c npm run build` - - TS type-check the built output: `cd packages/orderbook && nix develop -c npm run check` - - Run tests to confirm examples mirror real usage: `cd packages/orderbook && nix develop -c npm run test` + - Build artifacts needed for TS surface checks: `cd packages/raindex && nix develop -c npm run build` + - TS type-check the built output: `cd packages/raindex && nix develop -c npm run check` + - Run tests to confirm examples mirror real usage: `cd packages/raindex && nix develop -c npm run test` Practical ast-grep patterns - List wasm exports: `sg --lang rust -p '#[wasm_export]' crates/js_api` @@ -85,7 +85,7 @@ Practical ast-grep patterns - Param descriptions: `sg --lang rust -p 'param_description = $DESC' crates/js_api` - Return descriptions: `sg --lang rust -p 'return_description = $DESC' crates/js_api` - Tsify types: `sg --lang rust -p 'derive(Tsify)' crates/js_api` -- TS API imports in tests: `sg --lang ts -p 'import { $API } from "@rainlanguage/orderbook"' packages/orderbook/test` +- TS API imports in tests: `sg --lang ts -p 'import { $API } from "@rainlanguage/raindex"' packages/raindex/test` Editing Guidelines - Do not change any function signatures or runtime logic for this task. @@ -97,7 +97,7 @@ Editing Guidelines Acceptance Criteria - All `#[wasm_export]` items in `crates/js_api` have accurate, up-to-date docs: names, params (with descriptions), return types/descriptions, and examples. -- `packages/orderbook/README.md` contains examples that compile conceptually against the current `.d.ts` and mirror test usage. +- `packages/raindex/README.md` contains examples that compile conceptually against the current `.d.ts` and mirror test usage. - TypeScript declarations (`cjs.d.ts`/`esm.d.ts`) match the documentation claims for names/types. - Builds, tests, and type checks pass locally using Nix shell commands listed above. - Your summary lists what changed and calls out any unresolved mismatches that require follow-up. @@ -107,4 +107,4 @@ What to return Notes - This repo uses a macro named `wasm_export` in `crates/js_api` to define JS-visible APIs and attach TypeScript-specific metadata (`js_name`, `unchecked_return_type`, `param_description`, `return_description`, `preserve_js_class`). Treat those attributes as the contract for the generated TypeScript surface. -- Some examples in README demonstrate end-to-end flows (e.g., GUI setup via `DotrainOrderGui`, order hash/calldata helpers). Prefer aligning those with current tests under `packages/orderbook/test/js_api` to avoid drift. +- Some examples in README demonstrate end-to-end flows (e.g., GUI setup via `DotrainOrderGui`, order hash/calldata helpers). Prefer aligning those with current tests under `packages/raindex/test/js_api` to avoid drift. diff --git a/audit/2026-03-13-01/pass0/process.md b/audit/2026-03-13-01/pass0/process.md deleted file mode 100644 index a5ee830233..0000000000 --- a/audit/2026-03-13-01/pass0/process.md +++ /dev/null @@ -1,34 +0,0 @@ -# Pass 0: Process Review - -**Date:** 2026-03-13 -**Files reviewed:** CLAUDE.md, AGENTS.md, ~/.claude/CLAUDE.md, ~/.claude/skills/audit/GENERAL_RULES.md - -## A01-1: CLAUDE.md uses `@AGENTS.md` syntax — LOW - -**File:** CLAUDE.md:1 - -The `@` prefix (`@AGENTS.md`) is IDE-specific mention syntax (e.g., Cursor, VS Code). Under context compression or in environments that don't expand `@` references, the instruction could be interpreted as literal text rather than a file reference. Plain markdown link or explicit "read the file `AGENTS.md`" would be more robust. - -## A01-2: No nix shell guidance in AGENTS.md — MEDIUM - -**File:** AGENTS.md - -AGENTS.md lists build commands (`cargo build`, `forge build`, `npm run dev`) but doesn't mention the nix development environment. The codebase relies on nix for tooling (`rainix-sol-prelude`, `rainix-rs-static`, `rainix-sol-artifacts`, etc.), and commands must not be prefixed with `nix develop -c` when already inside a nix shell (`$IN_NIX_SHELL` is set). Without this guidance, agents will either fail to find nix-provided tools or double-wrap commands unnecessarily. - -## A01-3: Preflight check omits `forge fmt` — LOW - -**File:** AGENTS.md:29 - -The "Quick preflight" is `npm run lint-format-check:all && rainix-rs-static`, which covers JS/TS linting and Rust static analysis. However, Solidity formatting (`forge fmt`) is listed under Coding Style (line 20) but not included in the preflight command. An agent following only the preflight instruction would miss Solidity formatting violations. - -## A01-4: Global CLAUDE.md applies audit rules universally — LOW - -**File:** ~/.claude/CLAUDE.md:4 - -The instruction "Follow the coding and testing standards in `~/.claude/skills/audit/GENERAL_RULES.md` at all times" applies audit-specific rules (fuzz run override policies, proposed fix file structure, finding severity classifications) to non-audit contexts where they don't apply. This could cause confusion — e.g., an agent adding a fuzz test might feel obligated to benchmark timing before adding a runs override, even during routine development. - -## A01-5: `ast-grep`/`sg` availability not guaranteed — INFO - -**File:** AGENTS.md:35 - -Agent-Specific Instructions prefer `sg` (ast-grep) for search, but `sg` is a nix-provided tool. If an agent is operating outside nix or `sg` is not installed, there's no fallback instruction. Standard tools (Grep, Glob) are always available. diff --git a/audit/2026-03-13-01/pass1/Deploy.md b/audit/2026-03-13-01/pass1/Deploy.md deleted file mode 100644 index 5d215b0548..0000000000 --- a/audit/2026-03-13-01/pass1/Deploy.md +++ /dev/null @@ -1,65 +0,0 @@ -# Pass 1: Security — Deploy.sol - -**Agent:** A15 -**File:** script/Deploy.sol - -## Evidence of Thorough Reading - -**Contract name:** `Deploy` (inherits `Script` from forge-std) - -**Functions:** -| Function | Line | Visibility | -|---|---|---| -| `deployRouter()` | 52 | internal | -| `run()` | 61 | external | - -**Constants (file-level):** -| Name | Line | Type | -|---|---|---| -| `DEPLOYMENT_SUITE_ALL` | 24 | `bytes32` | -| `DEPLOYMENT_SUITE_RAINDEX` | 25 | `bytes32` | -| `DEPLOYMENT_SUITE_SUBPARSER` | 26 | `bytes32` | -| `DEPLOYMENT_SUITE_ROUTE_PROCESSOR` | 27 | `bytes32` | -| `DEPLOYMENT_SUITE_ARB` | 28 | `bytes32` | -| `ROUTE_PROCESSOR_4_CREATION_CODE` | 38 | `bytes` | -| `ROUTE_PROCESSOR_4_BYTECODE_HASH` | 41 | `bytes32` | - -**Errors (file-level):** -| Name | Line | -|---|---| -| `BadRouteProcessor` | 44 | - -**State variables:** -| Name | Line | Type | -|---|---|---| -| `sDepCodeHashes` | 50 | `mapping(string => mapping(address => bytes32))` | - -## Findings - -### A15-1 [HIGH] Route processor bytecode hash check runs unconditionally, blocking non-route-processor suites - -**Location:** Lines 129–135 - -The `extcodehash` check against `ROUTE_PROCESSOR_4_BYTECODE_HASH` executes unconditionally after all suite-gated blocks. When running the `raindex` or `subparser` suite alone (without setting `DEPLOY_ROUTE_PROCESSOR_4_ADDRESS`), the variable `routeProcessor` remains `address(0)` (its default from line 68). `extcodehash(address(0))` returns the empty account hash, which does not match `ROUTE_PROCESSOR_4_BYTECODE_HASH`, causing the script to revert with `BadRouteProcessor`. - -This means the `raindex` and `subparser` suites cannot be run independently unless the caller also provides a valid `DEPLOY_ROUTE_PROCESSOR_4_ADDRESS` env var pointing to a pre-deployed RouteProcessor4, even though those suites have no functional dependency on the route processor. - -The check (and the route processor logic on lines 122–135 in its entirety) should be gated behind the same condition used by the arb suite or route-processor suite, since only those suites need it. - -### A15-2 [LOW] No explicit revert on failed `create` in `deployRouter()` - -**Location:** Lines 55–58 - -The `create` opcode returns `address(0)` on failure (e.g., out-of-gas during init code execution, or value transfer failure). The function returns this zero address without checking it. While the downstream `extcodehash` check on line 131 would eventually catch this (since `extcodehash(address(0))` won't match the expected hash), the error message would be `BadRouteProcessor` rather than a clear indication that contract creation failed. An explicit `require(routeProcessor4 != address(0))` after the assembly block would provide a more informative failure. - -### A15-3 [INFO] Private key loaded from environment variable - -**Location:** Line 62 - -`DEPLOYMENT_KEY` is read via `vm.envUint`. This is standard practice for Foundry deployment scripts and is the expected mechanism. No issue — noted for completeness of the security surface review. The script correctly does not log or expose the key value. - -### A15-4 [INFO] Unused `DEPLOYMENT_SUITE_ALL` constant if "all" suite is intended to be removed - -**Location:** Lines 24, 70, 94, 123, 137 - -The constant `DEPLOYMENT_SUITE_ALL` is defined and actively used in four conditional branches. If the intent (per the refactor note) is to remove the "all" suite and make each suite fully self-contained, these references are stale. However, since the code currently uses the constant and the logic works for the `all` case, this is informational only — it depends on the project's intended direction. diff --git a/audit/2026-03-13-01/pass1/GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass1/GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 4ba3120ca3..0000000000 --- a/audit/2026-03-13-01/pass1/GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,30 +0,0 @@ -# Pass 1: Security — GenericPoolOrderBookV6ArbOrderTaker.sol - -**Agent:** A05 -**File:** src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol - -## Evidence of Thorough Reading - -- **Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (line 11) -- **Functions:** constructor (line 15), onTakeOrders2 (line 18), fallback (line 38) -- **No types, errors, or constants defined** (all inherited) - -## Findings - -### A05-1 [HIGH] Unlimited approval to arbitrary spender with caller-controlled data - -**Location:** Line 29 - -`onTakeOrders2` is `public` with no access control. The function decodes `takeOrdersData` to get an attacker-chosen `spender`, grants `type(uint256).max` approval on `inputToken`, then makes an arbitrary call to an attacker-chosen `pool`. During that call, the spender can transfer the contract's `inputToken` balance. The approval is revoked at line 34, but only after the external call. Mitigated by the contract typically holding no residual tokens. - -### A05-2 [MEDIUM] Arbitrary external call sends entire ETH balance - -**Location:** Line 30 - -`pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` sends the full ETH balance to a caller-controlled address. Combined with public access to `onTakeOrders2`, any ETH held can be drained. - -### A05-3 [LOW] Non-payable fallback with misleading comment - -**Location:** Line 38 - -`fallback() external {}` is not `payable`. The comment "Allow receiving gas" is misleading — this does not enable ETH receipt. diff --git a/audit/2026-03-13-01/pass1/GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass1/GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index 93af7d0c7d..0000000000 --- a/audit/2026-03-13-01/pass1/GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,80 +0,0 @@ -# Pass 1 Audit: GenericPoolOrderBookV6FlashBorrower.sol - -**Agent:** A06 -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Name -`GenericPoolOrderBookV6FlashBorrower` (inherits `OrderBookV6FlashBorrower`) - -### Functions and Line Numbers -| Function | Line | -|---|---| -| `constructor(OrderBookV6ArbConfig memory config)` | 31 | -| `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData) internal virtual override` | 34 | -| `fallback() external` | 48 | - -### Types, Errors, and Constants -- No types, errors, or constants defined in this file. All are inherited from parent contracts. - -### Imports (lines 5-15) -- `IERC3156FlashLender` (line 5) -- `IERC3156FlashBorrower` (line 6) -- `OrderBookV6FlashBorrower`, `SafeERC20`, `IERC20`, `Address`, `TakeOrdersConfigV5`, `OrderBookV6ArbConfig` (lines 8-15) - -### Parent Contract Context Reviewed -- `OrderBookV6FlashBorrower` (`src/abstract/OrderBookV6FlashBorrower.sol`): provides `arb4`, `onFlashLoan`, `_exchange` (virtual hook), `supportsInterface`. Uses `ReentrancyGuard`. -- `OrderBookV6ArbCommon` (`src/abstract/OrderBookV6ArbCommon.sol`): provides `iTaskHash`, `onlyValidTask` modifier, `Construct` event. -- `LibOrderBookArb` (`src/lib/LibOrderBookArb.sol`): provides `finalizeArb` which sends remaining tokens and gas to `msg.sender`. - ---- - -## Findings - -### A06-1 [MEDIUM] — Unlimited approval to arbitrary spender with no validation - -**Location:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol`, line 40 - -**Description:** -In `_exchange`, the contract approves `type(uint256).max` tokens to an arbitrary `spender` address decoded from `exchangeData`: - -```solidity -IERC20(borrowedToken).forceApprove(spender, type(uint256).max); -``` - -The `spender` is entirely caller-controlled (decoded from `exchangeData` at line 35-36). While the approval is reset to 0 on line 44, if the `pool.functionCallWithValue` call on line 41 reverts, the approval is never cleared. More importantly, if the `pool` call re-enters (the pool is also arbitrary), it could exploit the standing max approval before it is cleared. - -However, mitigating factors exist: -1. The parent `arb4` function has `nonReentrant` guard, but this only blocks re-entry into `arb4` itself, not into `_exchange` via `onFlashLoan` which is already inside the guarded section. -2. The `onFlashLoan` checks `initiator == address(this)`, so the flash loan callback path is protected. -3. After the entire arb completes, `finalizeArb` sweeps all remaining tokens to `msg.sender`, so there shouldn't be residual tokens for a future approval exploit. - -The risk is that during the `pool.functionCallWithValue` call, the arbitrary pool contract has `type(uint256).max` approval and could drain any pre-existing token balance the contract holds from a prior step or concurrent state. Since the contract is designed to hold zero balance between arbs, this is primarily a theoretical risk during the arb execution window. - -**Impact:** An attacker who controls or interacts with a malicious pool address could exploit the max approval window. However, since the `arb` caller chooses the pool and spender, this requires the arb caller to self-attack (or be tricked via a frontrunning attack that substitutes exchangeData, which is not possible since data is already committed in the tx). - -### A06-2 [LOW] — fallback function accepts arbitrary calls without payable - -**Location:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol`, line 48 - -**Description:** -The contract defines a `fallback()` function: - -```solidity -fallback() external {} -``` - -The comment says "Allow receiving gas" but the `fallback` is not `payable`. In Solidity 0.8.25, a non-payable `fallback` will revert when called with `msg.value > 0`. To receive ETH, the contract would need either `fallback() external payable` or a `receive() external payable` function. - -This means the contract cannot actually receive plain ETH transfers via the fallback, contradicting the stated intent. The `arb4` function is `payable` and can receive ETH, and `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` forwards any ETH balance to the pool. If the pool needs to return ETH to this contract (e.g., as change), it cannot do so via a plain transfer. - -However, ETH can still arrive at the contract via `selfdestruct` from another contract, or as block rewards / coinbase. The practical impact is that any pool that tries to send ETH back to this contract via a plain transfer will have that transfer revert. - -### A06-3 [INFO] — Unused import IERC3156FlashLender - -**Location:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol`, line 5 - -**Description:** -`IERC3156FlashLender` is imported but never used in this contract. The contract implements `IERC3156FlashBorrower` (via inheritance), not the lender interface. This is a code hygiene issue with no security impact. diff --git a/audit/2026-03-13-01/pass1/LibOrder.md b/audit/2026-03-13-01/pass1/LibOrder.md deleted file mode 100644 index ef59b9c4d9..0000000000 --- a/audit/2026-03-13-01/pass1/LibOrder.md +++ /dev/null @@ -1,31 +0,0 @@ -# Pass 1 Audit: LibOrder.sol - -**Agent:** A09 -**File:** `/Users/thedavidmeister/Code/rain.orderbook/src/lib/LibOrder.sol` - -## Evidence of Thorough Reading - -### Contract/Module -- `LibOrder` (library, lines 10-18) - -### Functions -| Function | Line | -|----------|------| -| `hash(OrderV4 memory order) internal pure returns (bytes32)` | 16 | - -### Types, Errors, and Constants -- None defined in this file. -- Imports: `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5). - -## Findings - -No findings. - -The library is minimal and correct: - -- **Memory safety:** No assembly blocks. Uses `abi.encode` which is handled by the Solidity compiler with safe memory operations. -- **Reentrancy:** Function is `pure`; no state reads or external calls. -- **Access control:** Library with `internal` visibility; appropriate for a utility function. -- **Arithmetic safety:** No arithmetic operations. -- **Input validation:** `abi.encode` correctly handles dynamic types (`IOV2[]` arrays in `OrderV4`) and produces unambiguous encoding, avoiding hash collision risks that `abi.encodePacked` would introduce with dynamic types. -- **Hash collision resistance:** The choice of `abi.encode` over `abi.encodePacked` is explicitly documented and correct, as `OrderV4` contains dynamic array fields (`validInputs`, `validOutputs`) where packed encoding could produce collisions. diff --git a/audit/2026-03-13-01/pass1/LibOrderBook.md b/audit/2026-03-13-01/pass1/LibOrderBook.md deleted file mode 100644 index 38fd3a2d74..0000000000 --- a/audit/2026-03-13-01/pass1/LibOrderBook.md +++ /dev/null @@ -1,95 +0,0 @@ -# Pass 1: Security -- LibOrderBook.sol - -**Agent:** A11 -**File:** src/lib/LibOrderBook.sol - -## Evidence of Thorough Reading - -**Library name:** `LibOrderBook` (line 96) - -**Functions:** -| Line | Function | -|------|----------| -| 97 | `doPost(bytes32[][] memory context, TaskV2[] memory post) internal` | - -This is the only function in the library. - -**Types/Errors/Constants defined (file-level, outside the library):** - -| Lines | Item | Kind | -|-------|------|------| -| 28 | `CALLING_CONTEXT_COLUMNS = 4` | constant | -| 30 | `CONTEXT_COLUMNS = CALLING_CONTEXT_COLUMNS + 1` | constant | -| 36 | `CONTEXT_CALLING_CONTEXT_COLUMN = 1` | constant | -| 37 | `CONTEXT_CALLING_CONTEXT_ROWS = 3` | constant | -| 39 | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH = 0` | constant | -| 40 | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER = 1` | constant | -| 41 | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY = 2` | constant | -| 43 | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN = 0` | constant | -| 44 | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID = 1` | constant | -| 45 | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE = 2` | constant | -| 46 | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER = 3` | constant | -| 48 | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN = 0` | constant | -| 49 | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID = 1` | constant | -| 50 | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE = 2` | constant | -| 51 | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER = 3` | constant | -| 52 | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT = 4` | constant | -| 56 | `CONTEXT_CALCULATIONS_COLUMN = 2` | constant | -| 57 | `CONTEXT_CALCULATIONS_ROWS = 2` | constant | -| 59 | `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT = 0` | constant | -| 60 | `CONTEXT_CALCULATIONS_ROW_IO_RATIO = 1` | constant | -| 66 | `CONTEXT_VAULT_INPUTS_COLUMN = 3` | constant | -| 69 | `CONTEXT_VAULT_OUTPUTS_COLUMN = 4` | constant | -| 72 | `CONTEXT_VAULT_IO_TOKEN = 0` | constant | -| 74 | `CONTEXT_VAULT_IO_TOKEN_DECIMALS = 1` | constant | -| 76 | `CONTEXT_VAULT_IO_VAULT_ID = 2` | constant | -| 79 | `CONTEXT_VAULT_IO_BALANCE_BEFORE = 3` | constant | -| 84 | `CONTEXT_VAULT_IO_BALANCE_DIFF = 4` | constant | -| 86 | `CONTEXT_VAULT_IO_ROWS = 5` | constant | -| 88 | `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN = 5` | constant | -| 89 | `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS = 1` | constant | -| 90 | `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW = 0` | constant | -| 92 | `CONTEXT_SIGNED_CONTEXT_START_COLUMN = 6` | constant | -| 93 | `CONTEXT_SIGNED_CONTEXT_START_ROWS = 1` | constant | -| 94 | `CONTEXT_SIGNED_CONTEXT_START_ROW = 0` | constant | - -No custom errors or structs are defined in this file. No assembly is used. - -**Imports:** -- `CONTEXT_BASE_ROWS`, `CONTEXT_BASE_ROW_SENDER`, `CONTEXT_BASE_ROW_CALLING_CONTRACT`, `CONTEXT_BASE_COLUMN` from `LibContext.sol` -- `TaskV2` from `IRaindexV6.sol` -- `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4` from `IInterpreterV4.sol` -- `LibNamespace`, `FullyQualifiedNamespace` from `LibNamespace.sol` -- `LibContext` from `LibContext.sol` - -## Findings - -No CRITICAL, HIGH, MEDIUM, or LOW findings were identified. The analysis below documents what was checked and why no issues were found. - -###Checklist of areas reviewed with no issues found: - -**Reentrancy:** `doPost` makes external calls to `task.evaluable.interpreter.eval4(...)` and `task.evaluable.store.set(...)`. Both the interpreter and store addresses come from the user-supplied `TaskV2`. However, all callers of `doPost` in `OrderBookV6.sol` (`entask2`, `deposit4`, `withdraw4`, `addOrder4`, `removeOrder3`) are protected by `nonReentrant`. The `doPost` call is always made after all state changes (vault balance updates, order state changes) are complete, so even though external calls occur, all contract state is already finalized. This is correct. - -**Namespace consistency:** `doPost` creates `namespace = StateNamespace.wrap(uint256(uint160(msg.sender)))` and then `qualifiedNamespace = LibNamespace.qualifyNamespace(namespace, address(this))`. The `qualifiedNamespace` is passed to `eval4` so the interpreter reads from the correct namespace. The unqualified `namespace` is passed to `store.set`, which is correct because `IInterpreterStoreV3.set` takes an unqualified namespace and the store implementation (`RainterpreterStore`) qualifies it internally with `msg.sender` (which is the OrderBook, i.e. `address(this)`). These produce identical fully qualified namespaces, so state reads during eval and state writes via set are consistent. - -**Input validation / empty arrays:** When `post.length == 0`, the loop body never executes, which is correct. When `task.evaluable.bytecode.length == 0`, the eval is skipped entirely, which is correct. When `writes.length == 0`, the `store.set` call is skipped, which is correct and gas-efficient. - -**Arithmetic safety:** The loop counter `++i` uses checked arithmetic (no `unchecked` block), so overflow is impossible. No other arithmetic operations exist. - -**Memory safety:** No assembly is used. All memory operations use standard Solidity patterns. `emptyStack` and `emptyStateOverlay` are allocated once outside the loop and reused, which is safe since they are zero-length immutable arrays. - -**Error handling:** External calls to `eval4` and `store.set` are not wrapped in try/catch. If either reverts, the entire transaction reverts, which is the intended behavior per the IRaindexV6 specification ("If ANY of the expressions revert, the entire transaction MUST revert"). - -**Stack suppression:** Line 118 `(stack);` suppresses the unused variable warning for the stack returned by `eval4`. The stack values from post-tasks are intentionally discarded. This is a standard Solidity pattern and not a bug. - -**User-supplied interpreter/store addresses:** The `task.evaluable.interpreter` and `task.evaluable.store` are user-supplied external contract addresses. A malicious user could supply a malicious interpreter or store. However, this is by design -- users provide their own tasks and bear the risk of their own evaluable configurations. The namespace is derived from `msg.sender`, so one user's tasks cannot affect another user's state. This is documented in the `EvaluableV4` struct's NatSpec: "Callers MUST NOT use an `EvaluableV4` with a zero or untrusted interpreter address." - -### A11-1 [INFO] Unused return value from `eval4` is silently discarded - -**Location:** Line 118 - -Line 118 reads `(stack);` which discards the stack output from `eval4`. This is intentional for post-tasks (the stack output is not meaningful), but there is no comment explaining why the return value is discarded. Adding a brief comment would improve readability for future auditors and developers. - ---- - -No fix files are required as the only finding is INFO-level. diff --git a/audit/2026-03-13-01/pass1/LibOrderBookArb.md b/audit/2026-03-13-01/pass1/LibOrderBookArb.md deleted file mode 100644 index 34a5d83294..0000000000 --- a/audit/2026-03-13-01/pass1/LibOrderBookArb.md +++ /dev/null @@ -1,20 +0,0 @@ -# Pass 1: Security — LibOrderBookArb.sol - -**Agent:** A11 -**File:** src/lib/LibOrderBookArb.sol - -## Evidence of Thorough Reading - -- **Library:** `LibOrderBookArb` (line 20) -- **Functions:** `finalizeArb` (line 23) -- **Errors:** `NonZeroBeforeArbStack` (line 14), `BadLender` (line 17) - -## Findings - -### A11-1 [INFO] Unused Import: IERC20Metadata - -**File:** src/lib/LibOrderBookArb.sol:10 - -`IERC20Metadata` is imported but never referenced in the library. - -No LOW+ findings. No fix files needed. diff --git a/audit/2026-03-13-01/pass1/LibOrderBookDeploy.md b/audit/2026-03-13-01/pass1/LibOrderBookDeploy.md deleted file mode 100644 index d550599185..0000000000 --- a/audit/2026-03-13-01/pass1/LibOrderBookDeploy.md +++ /dev/null @@ -1,45 +0,0 @@ -# Pass 1: Security -- LibOrderBookDeploy.sol - -**Agent:** A14 -**File:** src/lib/deploy/LibOrderBookDeploy.sol - -## Evidence of Thorough Reading - -**Library name:** `LibOrderBookDeploy` - -**Functions:** -- `etchOrderBook(Vm vm)` -- line 45 (internal, takes Forge Vm cheatcode interface) - -**Constants:** -- `ORDERBOOK_DEPLOYED_ADDRESS` (address) -- line 27, aliased from `ORDERBOOK_ADDR` imported from generated pointers -- `ORDERBOOK_DEPLOYED_CODEHASH` (bytes32) -- line 31, aliased from `ORDERBOOK_HASH` imported from generated pointers -- `SUB_PARSER_DEPLOYED_ADDRESS` (address) -- line 35, aliased from `SUB_PARSER_ADDR` imported from generated pointers -- `SUB_PARSER_DEPLOYED_CODEHASH` (bytes32) -- line 39, aliased from `SUB_PARSER_HASH` imported from generated pointers - -**Types, errors, custom types defined:** None. - -**Imports:** -- `Vm` from `forge-std/Vm.sol` (line 5) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6.pointers.sol` (lines 7-11), aliased as `ORDERBOOK_HASH`, `ORDERBOOK_ADDR`, `ORDERBOOK_RUNTIME_CODE` -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6SubParser.pointers.sol` (lines 12-16), aliased as `SUB_PARSER_HASH`, `SUB_PARSER_ADDR`, `SUB_PARSER_RUNTIME_CODE` - -**Functionality summary:** -The library is a test/script utility that stores deterministic deployment addresses and codehashes for OrderBookV6 and its sub-parser. The single function `etchOrderBook` uses Forge's `vm.etch` cheatcode to place runtime bytecode at the expected deterministic addresses, but only if the codehash at those addresses does not already match (idempotent behavior). This library is used in test setup (via `OrderBookV6ExternalMockTest`) and the deploy script (`Deploy.sol`). - -## Findings - -No findings. - -This file is a minimal, well-structured test/script utility library. The security analysis considered: - -1. **Memory safety / Assembly:** No assembly or low-level memory operations are present. -2. **Input validation:** The function accepts a `Vm` reference which is a Forge cheatcode interface -- this is only callable in test/script contexts, not on-chain. No user-supplied data is processed. -3. **Authentication/Authorization:** Not applicable -- this is a `library` with an `internal` function, so it can only be called by contracts that include it. It is not deployed on-chain as a standalone contract. -4. **Reentrancy:** No state mutations, no external calls to untrusted contracts. `vm.etch` is a Forge cheatcode. -5. **Arithmetic safety:** No arithmetic operations are present. -6. **Error handling:** The codehash comparison on lines 46 and 49 serves as a guard to skip unnecessary etching. No error conditions need to be handled since `vm.etch` is a cheatcode that reverts internally on failure. -7. **Solidity-specific (custom errors, string reverts):** No revert paths exist in this library. No string reverts. -8. **Correctness of codehash check:** The check `ORDERBOOK_DEPLOYED_CODEHASH != ORDERBOOK_DEPLOYED_ADDRESS.codehash` correctly uses the Solidity `.codehash` member on an address, which returns the keccak256 of the runtime code at that address (or `bytes32(0)` for accounts without code). This correctly gates the etch operation. -9. **Import integrity:** Constants are imported from autogenerated pointer files whose correctness is verified by comprehensive tests in `test/lib/deploy/LibOrderBookDeploy.t.sol` (tests verify creation code, runtime code, deployed addresses, and codehashes all match between generated constants and actual compiler output). - -The library is correct, minimal, and contains no security issues. diff --git a/audit/2026-03-13-01/pass1/LibOrderBookSubParser.md b/audit/2026-03-13-01/pass1/LibOrderBookSubParser.md deleted file mode 100644 index 3284d1e370..0000000000 --- a/audit/2026-03-13-01/pass1/LibOrderBookSubParser.md +++ /dev/null @@ -1,81 +0,0 @@ -# Pass 1: Security -- LibOrderBookSubParser.sol - -**Agent:** A13 -**File:** src/lib/LibOrderBookSubParser.sol - -## Evidence of Thorough Reading - -**Library name:** `LibOrderBookSubParser` (line 98) - -**Functions (with line numbers):** -1. `subParserSender(uint256, uint256, OperandV2)` -- line 101 -2. `subParserCallingContract(uint256, uint256, OperandV2)` -- line 106 -3. `subParserOrderHash(uint256, uint256, OperandV2)` -- line 115 -4. `subParserOrderOwner(uint256, uint256, OperandV2)` -- line 124 -5. `subParserOrderCounterparty(uint256, uint256, OperandV2)` -- line 133 -6. `subParserMaxOutput(uint256, uint256, OperandV2)` -- line 143 -7. `subParserIORatio(uint256, uint256, OperandV2)` -- line 152 -8. `subParserInputToken(uint256, uint256, OperandV2)` -- line 161 -9. `subParserInputTokenDecimals(uint256, uint256, OperandV2)` -- line 170 -10. `subParserInputVaultId(uint256, uint256, OperandV2)` -- line 179 -11. `subParserInputBalanceBefore(uint256, uint256, OperandV2)` -- line 188 -12. `subParserInputBalanceDiff(uint256, uint256, OperandV2)` -- line 197 -13. `subParserOutputToken(uint256, uint256, OperandV2)` -- line 206 -14. `subParserOutputTokenDecimals(uint256, uint256, OperandV2)` -- line 215 -15. `subParserOutputVaultId(uint256, uint256, OperandV2)` -- line 224 -16. `subParserOutputBalanceBefore(uint256, uint256, OperandV2)` -- line 233 -17. `subParserOutputBalanceDiff(uint256, uint256, OperandV2)` -- line 242 -18. `subParserSigners(uint256, uint256, OperandV2 operand)` -- line 251 -19. `subParserDepositToken(uint256, uint256, OperandV2)` -- line 260 -20. `subParserDepositVaultId(uint256, uint256, OperandV2)` -- line 269 -21. `subParserDepositVaultBalanceBefore(uint256, uint256, OperandV2)` -- line 279 -22. `subParserDepositVaultBalanceAfter(uint256, uint256, OperandV2)` -- line 291 -23. `subParserWithdrawToken(uint256, uint256, OperandV2)` -- line 303 -24. `subParserWithdrawVaultId(uint256, uint256, OperandV2)` -- line 312 -25. `subParserWithdrawVaultBalanceBefore(uint256, uint256, OperandV2)` -- line 322 -26. `subParserWithdrawVaultBalanceAfter(uint256, uint256, OperandV2)` -- line 334 -27. `subParserWithdrawTargetAmount(uint256, uint256, OperandV2)` -- line 346 -28. `subParserSignedContext(uint256, uint256, OperandV2 operand)` -- line 357 -29. `authoringMetaV2()` -- line 369 - -**Constants defined (file-level):** -- `SUB_PARSER_WORD_PARSERS_LENGTH` (line 48) = 2 -- `EXTERN_PARSE_META_BUILD_DEPTH` (line 49) = 1 -- Word constants: `WORD_ORDER_CLEARER`, `WORD_ORDERBOOK`, `WORD_ORDER_HASH`, `WORD_ORDER_OWNER`, `WORD_ORDER_COUNTERPARTY`, `WORD_CALCULATED_MAX_OUTPUT`, `WORD_CALCULATED_IO_RATIO`, `WORD_INPUT_TOKEN`, `WORD_INPUT_TOKEN_DECIMALS`, `WORD_INPUT_VAULT_ID`, `WORD_INPUT_VAULT_BALANCE_BEFORE`, `WORD_INPUT_VAULT_BALANCE_INCREASE`, `WORD_OUTPUT_TOKEN`, `WORD_OUTPUT_TOKEN_DECIMALS`, `WORD_OUTPUT_VAULT_ID`, `WORD_OUTPUT_VAULT_BALANCE_BEFORE`, `WORD_OUTPUT_VAULT_BALANCE_DECREASE` (lines 51-67) -- Deposit word constants: `WORD_DEPOSITOR`, `WORD_DEPOSIT_TOKEN`, `WORD_DEPOSIT_VAULT_ID`, `WORD_DEPOSIT_VAULT_BEFORE`, `WORD_DEPOSIT_VAULT_AFTER` (lines 69-73) -- Withdraw word constants: `WORD_WITHDRAWER`, `WORD_WITHDRAW_TOKEN`, `WORD_WITHDRAW_VAULT_ID`, `WORD_WITHDRAW_VAULT_BEFORE`, `WORD_WITHDRAW_VAULT_AFTER`, `WORD_WITHDRAW_TARGET_AMOUNT` (lines 75-80) -- Deposit word index constants: `DEPOSIT_WORD_DEPOSITOR` through `DEPOSIT_WORDS_LENGTH` (lines 82-87) -- Withdraw word index constants: `WITHDRAW_WORD_WITHDRAWER` through `WITHDRAW_WORDS_LENGTH` (lines 89-95) - -**Types, errors, custom types defined:** None in this file. Types and errors are imported from dependencies. - -**Imports:** -- `AuthoringMetaV2`, `OperandV2` from `rain.interpreter.interface` -- `LibUint256Matrix` from `rain.solmem` -- `LibSubParse` from `rain.interpreter` -- Numerous context constants from `LibOrderBook.sol` - -**Using directives:** -- `LibUint256Matrix for uint256[][]` (line 99) - -## Findings - -No findings. The file is secure. - -**Analysis summary:** - -1. **All sub-parser functions (lines 101-355):** Functions 1-17 and 19-27 are trivial wrappers around `LibSubParse.subParserContext(column, row)` with compile-time constant arguments. The called function validates both column and row fit in uint8 before encoding. All constant pairs were verified against `LibOrderBook.sol` definitions and are within range. - -2. **`subParserSigners` (line 251):** Passes the full `uint256(OperandV2.unwrap(operand))` as the row to `subParserContext`. Since `OperandV2 is bytes32`, this could be a large value, but `subParserContext` validates `row > type(uint8).max` and reverts with `ContextGridOverflow` if violated. Safe. - -3. **`subParserSignedContext` (line 357):** Extracts column from low byte and row from second byte of operand via bitmasking (`& 0xFF`). Both are bounded to 0-255. The column is then offset by `CONTEXT_SIGNED_CONTEXT_START_COLUMN` (6), yielding max 261, which `subParserContext` validates against uint8 max. Operand column values >= 250 will revert. This is correct behavior. - -4. **`authoringMetaV2` (line 369):** The two `assembly` blocks at lines 588-590 and 593-595 perform pointer aliasing (reinterpreting `AuthoringMetaV2[][]` as `uint256[][]` and `uint256[]` as `AuthoringMetaV2[]`). These are read-only pointer casts with no memory writes, consistent with the rain codebase pattern. The `AuthoringMetaV2` struct layout (`bytes32 word; string description;`) maps to two 256-bit slots per element, matching the `uint256[]` element size after flattening. - -5. **Array bounds in `authoringMetaV2`:** The `meta` array is allocated with size `CONTEXT_COLUMNS + 2 + 1 + 1 = 9`. All 9 indices (0 through 8) are populated. Deposit meta uses `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_* + 1` indexing which was verified correct against the constant values (0-3, yielding indices 1-4 in a length-5 array). Withdraw meta uses `WITHDRAW_WORD_*` indices (0-5 in a length-6 array). All within bounds. - -6. **`bytes32` conversions from `bytes` constants:** All `WORD_*` constants are string literals shorter than 32 bytes (longest is 21 characters). The `bytes32(WORD_*)` conversions are safe and annotated with `forge-lint: disable-next-line(unsafe-typecast)` comments. - -7. **No string reverts:** The library does not define or use any `require` with string messages or `revert` with string arguments. All error handling is delegated to `LibSubParse.subParserContext` which uses custom errors (`ContextGridOverflow`). - -8. **No arithmetic operations** beyond array index computation with compile-time constants. No unchecked blocks. No external calls. diff --git a/audit/2026-03-13-01/pass1/OrderBookV6.md b/audit/2026-03-13-01/pass1/OrderBookV6.md deleted file mode 100644 index 62fbf4793c..0000000000 --- a/audit/2026-03-13-01/pass1/OrderBookV6.md +++ /dev/null @@ -1,127 +0,0 @@ -# Pass 1: Security -- OrderBookV6.sol - -**Agent:** A08 -**File:** src/concrete/ob/OrderBookV6.sol - -## Evidence of Thorough Reading - -**Contract name:** `OrderBookV6` - -**Inheritance:** `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender` - -**Functions and line numbers:** - -| Function | Line | Visibility | -|---|---|---| -| `vaultBalance2` | 226 | external view | -| `_vaultBalance` | 231 | internal view | -| `orderExists` | 249 | external view | -| `entask2` | 254 | external | -| `deposit4` | 259 | external | -| `withdraw4` | 294 | external | -| `addOrder4` | 333 | external | -| `removeOrder3` | 383 | external | -| `checkTokenSelfTrade` | 406 | internal pure | -| `quote2` | 413 | external view | -| `takeOrders4` | 436 | external | -| `clear3` | 596 | external | -| `calculateOrderIO` | 701 | internal view | -| `increaseVaultBalance` | 823 | internal | -| `decreaseVaultBalance` | 854 | internal | -| `recordVaultIO` | 892 | internal | -| `handleIO` | 916 | internal | -| `calculateClearStateChange` | 971 | internal pure | -| `calculateClearStateAlice` | 984 | internal pure | -| `pullTokens` | 1003 | internal | -| `pushTokens` | 1025 | internal | -| `_nonZeroVaultId` | 1045 | internal pure | -| `nonZeroVaultId` (modifier) | 1051 | modifier | - -**Inherited from OrderBookV6FlashLender (src/abstract/OrderBookV6FlashLender.sol):** - -| Function | Line | Visibility | -|---|---|---| -| `supportsInterface` | 33 | public view | -| `flashLoan` | 38 | external | -| `flashFee` | 70 | external pure | -| `maxFlashLoan` | 78 | external view | - -**Types defined:** - -- `OrderIOCalculationV4` (struct, line 181): order, outputIOIndex, outputMax, IORatio, context, namespace, kvs -- `Output18Amount` (user-defined value type, line 192): wraps uint256 -- `Input18Amount` (user-defined value type, line 194): wraps uint256 - -**Errors defined (lines 69-125):** - -- `ReentrancyGuardReentrantCall` (line 69) -- `NotOrderOwner` (line 73) -- `TokenMismatch` (line 76) -- `TokenSelfTrade` (line 79) -- `TokenDecimalsMismatch` (line 83) -- `MinimumIO` (line 88) -- `SameOwner` (line 91) -- `UnsupportedCalculateInputs` (line 95) -- `UnsupportedCalculateOutputs` (line 98) -- `NegativeInput` (line 102) -- `NegativeOutput` (line 105) -- `NegativeVaultBalance` (line 109) -- `NegativeVaultBalanceChange` (line 113) -- `NegativePull` (line 116) -- `NegativePush` (line 119) -- `NegativeBounty` (line 122) -- `ClearZeroAmount` (line 125) - -**Constants defined (lines 129-150):** - -- `ORDER_LIVE` = 1 (line 129) -- `ORDER_DEAD` = 0 (line 134) -- `CALCULATE_ORDER_ENTRYPOINT` = SourceIndexV2.wrap(0) (line 137) -- `HANDLE_IO_ENTRYPOINT` = SourceIndexV2.wrap(1) (line 140) -- `CALCULATE_ORDER_MIN_OUTPUTS` = 2 (line 143) -- `CALCULATE_ORDER_MAX_OUTPUTS` = 2 (line 145) -- `HANDLE_IO_MIN_OUTPUTS` = 0 (line 148) -- `HANDLE_IO_MAX_OUTPUTS` = 0 (line 150) - -**Storage variables:** - -- `sOrders` (mapping, line 215): `bytes32 orderHash => uint256 liveness` -- `sVaultBalances` (mapping, line 222): `address owner => address token => bytes32 vaultId => Float balance` - -## Findings - -### A08-1 [LOW] `flashLoan` lacks `nonReentrant` guard allowing reentrant flash loan nesting - -**Location:** `src/abstract/OrderBookV6FlashLender.sol`, lines 38-67 - -The `flashLoan` function inherited from `OrderBookV6FlashLender` does not carry the `nonReentrant` modifier. During the `onFlashLoan` callback (line 45), the borrower contract can call `flashLoan` again, creating nested flash loans against the same token balance. While each nested loan is individually self-balancing (tokens sent = tokens returned), the composition of nested flash loans transiently depletes the contract's token balance by a multiple of the loaned amount. - -This means a flash loan borrower can temporarily move more tokens out of the contract than it actually holds in its real balance (by borrowing, then re-borrowing within the callback before repaying). If the intermediate state is observed by any `calculateOrderIO` calls (which read vault balances and could be called via `takeOrders4` or `clear3` within the callback since they acquire their own `nonReentrant` locks), the observed balances would be artificially deflated. However, since `takeOrders4` and `clear3` are `nonReentrant`, they cannot be called during a flash loan that was itself called during a `nonReentrant`-guarded function. They CAN be called during a standalone flash loan's callback, but at that point the balance has already been sent out, which is expected flash loan behavior. - -The practical impact is limited because: (1) each nested loan must be repaid in LIFO order, (2) the OZ `ReentrancyGuard` protects all state-modifying vault operations, and (3) flash loan interactions with `takeOrders4` inside the callback are an explicitly documented and intended use case. Nevertheless, the lack of a reentrancy guard on `flashLoan` is a deviation from defensive coding practice and could interact unexpectedly with future code changes. - -### A08-2 [INFO] Stale comment in `recordVaultIO` describes opposite operation order - -**Location:** Line 902 - -The comment on line 902 says "Decrease before increasing so that if vault id == 0 then we pull tokens before pushing them." However, the code does the opposite: it calls `increaseVaultBalance` first (line 896, which pushes tokens for vault ID 0), then `decreaseVaultBalance` (line 904, which pulls tokens for vault ID 0). For vault ID 0, this means tokens are pushed to the order owner before being pulled from them, which is the reverse of what the comment claims. The actual execution order (push-then-pull) does not appear to cause a security issue since the entire function executes within a `nonReentrant` context, but the misleading comment could cause confusion during future maintenance. - -### A08-3 [INFO] `addOrder4` does not validate bytecode source count against entrypoint requirements - -**Location:** Lines 333-380 - -The `addOrder4` function validates that `validInputs` and `validOutputs` are non-empty but does not verify that the provided `evaluable.bytecode` contains at least two sources (one for `CALCULATE_ORDER_ENTRYPOINT` at index 0, and one for `HANDLE_IO_ENTRYPOINT` at index 1). The `IRaindexV6` interface specifies that the function "MUST revert with `OrderNoSources` if the order has no associated calculation and `OrderNoHandleIO` if the order has no handle IO entrypoint," but neither `OrderNoSources` nor `OrderNoHandleIO` errors are ever emitted by this implementation. - -An order with insufficient bytecode sources will still be stored as live. When a counterparty or clearer attempts to interact with it, the interpreter's `eval4` call will either revert (causing the take/clear transaction to fail) or return unexpected results. Since the order owner is responsible for their own bytecode and malformed orders primarily harm the order owner (their orders become unclearable), the impact is low. However, it is a deviation from the interface specification. - -### A08-4 [INFO] Unused types `Output18Amount` and `Input18Amount` - -**Location:** Lines 192-194 - -The user-defined value types `Output18Amount` and `Input18Amount` are declared but never used anywhere in the contract. These appear to be remnants from a prior version that used fixed-point 18-decimal amounts before the migration to `Float`. Dead code increases cognitive load and could mislead auditors or developers about the contract's behavior. - -### A08-5 [INFO] Unused errors `TokenDecimalsMismatch`, `UnsupportedCalculateInputs`, `NegativeInput`, and `NegativeOutput` - -**Location:** Lines 83, 95, 102, 105 - -The errors `TokenDecimalsMismatch` (line 83), `UnsupportedCalculateInputs` (line 95), `NegativeInput` (line 102), and `NegativeOutput` (line 105) are declared at file scope but are never used in any revert statement within `OrderBookV6.sol` or its parent contracts. These appear to be vestigial from prior versions. While they do not pose a security risk, they inflate bytecode size and could mislead future maintainers about which error conditions are actually enforced. diff --git a/audit/2026-03-13-01/pass1/OrderBookV6ArbCommon.md b/audit/2026-03-13-01/pass1/OrderBookV6ArbCommon.md deleted file mode 100644 index ca205f7de7..0000000000 --- a/audit/2026-03-13-01/pass1/OrderBookV6ArbCommon.md +++ /dev/null @@ -1,89 +0,0 @@ -# Pass 1 Audit: OrderBookV6ArbCommon.sol - -**Agent:** A01 -**File:** `/Users/thedavidmeister/Code/rain.orderbook/src/abstract/OrderBookV6ArbCommon.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract/Module Name -- `OrderBookV6ArbCommon` (abstract contract, line 34) - -### Struct Definitions -- `OrderBookV6ArbConfig` (lines 21-25): fields `orderBook` (address), `task` (TaskV2), `implementationData` (bytes) - -### Error Definitions -- `WrongTask()` (line 28) - -### Constant Definitions -- `BEFORE_ARB_SOURCE_INDEX` (line 32): `SourceIndexV2.wrap(0)` -- note: defined at file scope but not used within this contract - -### State Variables -- `iTaskHash` (line 39): `bytes32 public immutable`, initialized to `0` - -### Events -- `Construct(address sender, OrderBookV6ArbConfig config)` (line 37) - -### Functions/Modifiers (with line numbers) -- `constructor(OrderBookV6ArbConfig memory config)` (line 41) -- `modifier onlyValidTask(TaskV2 memory task)` (line 50) - -### Imports (lines 5-14) -- `EvaluableV4`, `SignedContextV1` from `IInterpreterCallerV4.sol` -- `IInterpreterV4`, `SourceIndexV2`, `DEFAULT_STATE_NAMESPACE` from `IInterpreterV4.sol` -- `IRaindexV6`, `TaskV2` from `IRaindexV6.sol` -- `LibContext` from `LibContext.sol` -- `LibNamespace` from `LibNamespace.sol` -- `LibEvaluable` from `LibEvaluable.sol` -- `using LibEvaluable for EvaluableV4` (line 35) - -## Security Review - -### Memory Safety -No assembly blocks present. No inline assembly. No raw memory manipulation. - -### Reentrancy -No external calls made in this contract. The constructor only emits an event and computes a keccak256 hash. The modifier `onlyValidTask` only performs comparisons and does not make external calls. Reentrancy is not a direct concern within this contract (inheriting contracts `OrderBookV6FlashBorrower` uses `ReentrancyGuard`). - -### Access Control -The `onlyValidTask` modifier provides task validation. It is correctly applied by inheriting contracts. - -### Arithmetic Safety -Only `keccak256` hashing is performed; no arithmetic operations. No overflow/underflow concerns. - -### Input Validation -Task validation in the modifier checks the hash if `iTaskHash` is nonzero, and passes through if `iTaskHash` is zero (meaning no task was configured at construction time). This is intentional behavior. - -## Findings - -### A01-1: Unused Imports (INFO) - -**Severity:** INFO - -**Location:** Lines 5-14 - -**Description:** Several imports are not used within this contract: -- `IInterpreterV4` (line 7) -- `DEFAULT_STATE_NAMESPACE` (line 9) -- `IRaindexV6` (line 11) -- `LibContext` (line 12) -- `LibNamespace` (line 13) -- `BEFORE_ARB_SOURCE_INDEX` constant (line 32) is defined but not used within this contract - -These are re-exported for use by inheriting contracts (`OrderBookV6ArbOrderTaker`, `OrderBookV6FlashBorrower`). While this is a common Solidity pattern to centralize imports, it can obscure actual dependencies and make auditing harder. - -**Impact:** No security impact. Code clarity concern only. - -### A01-2: `config.orderBook` Address Not Validated or Stored (LOW) - -**Severity:** LOW - -**Location:** Lines 41-48 (constructor) - -**Description:** The `OrderBookV6ArbConfig` struct contains an `orderBook` address field (line 22), but the `OrderBookV6ArbCommon` constructor does not validate this address (e.g., checking for `address(0)`) nor does it store it as a state variable. The address is only emitted in the `Construct` event. - -Inheriting contracts `OrderBookV6FlashBorrower` (line 65) and `OrderBookV6ArbOrderTaker` (line 39) each store `config.orderBook` as `iOrderBook` in their own constructors. However, neither validates it against `address(0)`. - -If `address(0)` is passed as the orderbook address, the contract will deploy successfully and the error will only be discovered when actual arb operations are attempted, wasting gas on deployment. - -**Impact:** Low. A misconfigured deployment would fail at first use rather than at construction. Since deployment is typically done by sophisticated actors (arb bots), the practical risk is minimal, but defense-in-depth suggests validating at construction time. diff --git a/audit/2026-03-13-01/pass1/OrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass1/OrderBookV6ArbOrderTaker.md deleted file mode 100644 index 7e6951b18a..0000000000 --- a/audit/2026-03-13-01/pass1/OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,28 +0,0 @@ -# Pass 1: Security — OrderBookV6ArbOrderTaker.sol - -**Agent:** A02 -**File:** src/abstract/OrderBookV6ArbOrderTaker.sol - -## Evidence of Thorough Reading - -- **Contract:** `OrderBookV6ArbOrderTaker` (abstract, line 31) -- **Inheritance:** IRaindexV6OrderTaker, IRaindexV6ArbOrderTaker, ReentrancyGuard, ERC165, OrderBookV6ArbCommon -- **Functions:** constructor (line 40), supportsInterface (line 43), arb5 (line 49), onTakeOrders2 (line 78) -- **Errors:** NonZeroBeforeArbInputs (line 25) -- **Constants:** BEFORE_ARB_SOURCE_INDEX (line 29) - -## Findings - -### A02-1 [LOW] `onTakeOrders2` callback has no access control - -**Location:** Line 78 - -The `onTakeOrders2` function is `public` with an empty body and no `msg.sender` validation. The interface doc states implementations MUST validate `msg.sender` is the trusted Raindex contract. Concrete overrides perform approvals and external calls without checking the caller. Practical exploitability is limited since the contract holds no balances between arb operations. - -### A02-2 [INFO] Unused error and duplicate constant - -`NonZeroBeforeArbInputs` (line 25) is never used. `BEFORE_ARB_SOURCE_INDEX` (line 29) duplicates the same constant in `OrderBookV6ArbCommon.sol`. - -### A02-3 [INFO] `orderBook` parameter in `arb5` not validated as trusted - -The `arb5` function accepts an arbitrary `IRaindexV6 orderBook` and grants it unlimited approval. This appears to be by design — the caller provides both the orderbook and receives profits. diff --git a/audit/2026-03-13-01/pass1/OrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass1/OrderBookV6FlashBorrower.md deleted file mode 100644 index c238aa0035..0000000000 --- a/audit/2026-03-13-01/pass1/OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,135 +0,0 @@ -# Audit Pass 1: OrderBookV6FlashBorrower.sol - -**Agent:** A03 -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence of Thorough Reading - -### Contract Name -`OrderBookV6FlashBorrower` (abstract contract, line 62) - -### Functions (with line numbers) -| Function | Line | Visibility | -|---|---|---| -| `constructor` | 66 | N/A | -| `supportsInterface` | 69 | public view virtual override | -| `_exchange` | 82 | internal virtual | -| `onFlashLoan` | 85 | external | -| `arb4` | 130 | external payable | - -### Inheritance -- `IERC3156FlashBorrower` -- `ReentrancyGuard` -- `ERC165` -- `OrderBookV6ArbCommon` - -### Types, Errors, and Constants -| Kind | Name | Line | -|---|---|---| -| error | `BadInitiator(address)` | 24 | -| error | `FlashLoanFailed()` | 27 | -| error | `SwapFailed()` | 30 | - -### Imports (unused noted) -- `BadLender` imported at line 18 but never used in this contract. -- `LibBytecode` imported at line 10 but never used in this contract. -- `IInterpreterStoreV3` imported at line 14 but never used in this contract. -- `EvaluableV4`, `SignedContextV1` imported at line 16 but never used directly. -- `LibOrderBook` imported at line 17 but never used directly. -- `SwapFailed` error defined at line 30 but never used in this contract. - ---- - -## Findings - -### A03-1: Missing `msg.sender` (lender) validation in `onFlashLoan` [MEDIUM] - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, line 85-107 - -**Description:** -The `onFlashLoan` function validates that `initiator == address(this)` (line 87) but does NOT validate that `msg.sender` is a trusted lender (orderbook). The `BadLender` error is imported (line 18) but never used, suggesting this check was intended but omitted. - -Any external contract can call `onFlashLoan(address(arbContract), ...)` directly. Because `msg.sender` is not checked: - -1. `_exchange(takeOrders, exchangeData)` executes with attacker-controlled data. In `GenericPoolOrderBookV6FlashBorrower._exchange`, the attacker controls `spender`, `pool`, and `encodedFunctionCall`, allowing arbitrary approvals and external calls. -2. `IRaindexV6(msg.sender).takeOrders4(takeOrders)` is called on the attacker's contract (`msg.sender`), which can return arbitrary data. - -The practical impact is mitigated because the arb contract is designed to hold zero balance between uses (`finalizeArb` drains all tokens). However, if tokens are ever present in the contract (e.g., sent accidentally, or during a multi-step operation), they can be drained. - -**Comparison to sibling contract:** `OrderBookV6ArbOrderTaker` does not have `onFlashLoan` and instead relies on `onTakeOrders2` which is called by the orderbook during `takeOrders4`. - -**Note:** The `nonReentrant` modifier on `arb4` does NOT protect `onFlashLoan` because `onFlashLoan` is a separate external entry point. It can be called independently outside of any `arb4` invocation. - ---- - -### A03-2: Missing ERC20 approval for flash loan repayment token [HIGH] - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, lines 158-162 - -**Description:** -In `arb4`, line 158 approves `ordersInputToken` (the order's input / taker's output) to the orderbook: -```solidity -IERC20(ordersInputToken).forceApprove(address(orderBook), type(uint256).max); -``` - -Line 159 initiates a flash loan for `ordersOutputToken` (the order's output / taker's input): -```solidity -orderBook.flashLoan(this, ordersOutputToken, flashLoanAmount, data) -``` - -The flash lender (`OrderBookV6FlashLender.sol`, line 64) repays by pulling the loaned token from the borrower: -```solidity -IERC20(token).safeTransferFrom(address(receiver), address(this), amount + FLASH_FEE); -``` - -This `safeTransferFrom` pulls `ordersOutputToken` from the arb contract back to the orderbook. However, there is no `forceApprove` for `ordersOutputToken` to the orderbook anywhere in `arb4` or `onFlashLoan`. The only approval is for `ordersInputToken`. - -**Impact:** Every call to `arb4` against the real `OrderBookV6FlashLender` will revert at flash loan repayment because the ERC20 `transferFrom` will fail due to insufficient allowance. The function is non-functional. - -**Why tests don't catch this:** The test suite uses `FlashLendingMockOrderBook` whose `flashLoan` implementation (line 22-28 of `test/util/concrete/FlashLendingMockOrderBook.sol`) does not perform actual token transfers or repayment -- it simply calls `onFlashLoan` and returns `true`. - ---- - -### A03-3: Flash loan amount computed with wrong token decimals [MEDIUM] - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, line 153 - -**Description:** -```solidity -uint256 flashLoanAmount = LibDecimalFloat.toFixedDecimalLossless(takeOrders.minimumIO, inputDecimals); -``` - -`flashLoanAmount` is used as the amount to flash-borrow of `ordersOutputToken` (line 159). However, it is converted from the `Float` `minimumIO` using `inputDecimals` (the decimals of `ordersInputToken`), not `outputDecimals` (the decimals of `ordersOutputToken`). - -When `IOIsInput` is `true`, `minimumIO` represents the minimum taker input, which is denominated in `ordersOutputToken`. Converting with `inputDecimals` instead of `outputDecimals` produces the wrong fixed-point value whenever the two tokens have different decimal precisions (e.g., USDT with 6 decimals vs DAI with 18 decimals). - -When `IOIsInput` is `false`, `minimumIO` represents the minimum taker output, denominated in `ordersInputToken`. Using `inputDecimals` is correct for the Float-to-uint conversion, but the resulting amount is in `ordersInputToken` units being used to borrow `ordersOutputToken`, which is semantically incorrect. - -**Impact:** The flash loan amount will be incorrect for token pairs with different decimal precisions, leading to either borrowing too much (revert if insufficient liquidity) or too little (arb may fail or be suboptimal). - ---- - -### A03-4: Unused imports and dead error definition [INFO] - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, lines 10, 14, 17, 18, 30 - -**Description:** -Several imports are unused in this contract: -- `LibBytecode` (line 10) -- `IInterpreterStoreV3` (line 14) -- `LibOrderBook` (line 17) -- `BadLender` (line 18) -- notably, this is the lender check that should be used in A03-1 -- `EvaluableV4`, `SignedContextV1` (line 16) - -Additionally, the `SwapFailed` error (line 30) is defined but never used in this contract or its concrete implementation `GenericPoolOrderBookV6FlashBorrower`. - -These unused imports increase bytecode size slightly and reduce code clarity. - ---- - -### A03-5: NatDoc title mismatch [INFO] - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, line 32 - -**Description:** -The NatDoc title reads `@title OrderBookV5FlashBorrower` but the actual contract is `OrderBookV6FlashBorrower`. This is a copy-paste artifact from an earlier version. diff --git a/audit/2026-03-13-01/pass1/OrderBookV6FlashLender.md b/audit/2026-03-13-01/pass1/OrderBookV6FlashLender.md deleted file mode 100644 index 7de8f5fed3..0000000000 --- a/audit/2026-03-13-01/pass1/OrderBookV6FlashLender.md +++ /dev/null @@ -1,25 +0,0 @@ -# Pass 1: Security — OrderBookV6FlashLender.sol - -**Agent:** A04 -**File:** src/abstract/OrderBookV6FlashLender.sol - -## Evidence of Thorough Reading - -- **Contract:** `OrderBookV6FlashLender` (abstract, line 29) -- **Functions:** supportsInterface (line 33), flashLoan (line 38), flashFee (line 70), maxFlashLoan (line 78) -- **Errors:** FlashLenderCallbackFailed (line 18) -- **Constants:** FLASH_FEE = 0 (line 23) - -## Findings - -### A04-1 [INFO] Misleading NatSpec on `maxFlashLoan` - -**Location:** Lines 74-76 - -The NatSpec states "If there is an active debt then loans are disabled so the max becomes 0 until after repayment." The implementation simply returns `balanceOf(address(this))` with no active-debt tracking. - -### A04-2 [LOW] `flashLoan` lacks reentrancy guard, allowing nested flash loans - -**Location:** Line 38 - -`flashLoan` makes an external call to `receiver.onFlashLoan()` without `nonReentrant`. The concrete inheritor `OrderBookV6` applies `nonReentrant` to all other state-mutating external functions but not `flashLoan`. Nested flash loans are possible during callbacks. Zero-fee model and `safeTransferFrom` repayment mitigate practical exploitation. diff --git a/audit/2026-03-13-01/pass1/OrderBookV6SubParser.md b/audit/2026-03-13-01/pass1/OrderBookV6SubParser.md deleted file mode 100644 index 841864580a..0000000000 --- a/audit/2026-03-13-01/pass1/OrderBookV6SubParser.md +++ /dev/null @@ -1,74 +0,0 @@ -# Pass 1: Security -- OrderBookV6SubParser.sol - -**Agent:** A09 -**File:** src/concrete/parser/OrderBookV6SubParser.sol - -## Evidence of Thorough Reading - -**Contract name:** `OrderBookV6SubParser` (line 71), inherits `BaseRainterpreterSubParser` - -**Functions and line numbers:** - -| Function | Line | Visibility | Mutability | -|---|---|---|---| -| `describedByMetaV1()` | 75 | external | pure | -| `subParserParseMeta()` | 80 | internal | pure virtual override | -| `subParserWordParsers()` | 85 | internal | pure virtual override | -| `subParserOperandHandlers()` | 90 | internal | pure virtual override | -| `buildLiteralParserFunctionPointers()` | 95 | external | pure | -| `buildOperandHandlerFunctionPointers()` | 100 | external | pure | -| `buildSubParserWordParsers()` | 186 | external | pure | - -**Types, errors, and constants defined in this file:** - -None defined directly in this file. All types (`OperandV2`), errors (`BadDynamicLength`), and constants (`SUB_PARSER_WORD_PARSERS_LENGTH`, `DEPOSIT_WORD_*`, `WITHDRAW_WORD_*`, `CONTEXT_*`, `DESCRIBED_BY_META_HASH`, `SUB_PARSER_PARSE_META`, `SUB_PARSER_WORD_PARSERS`, `SUB_PARSER_OPERAND_HANDLERS`) are imported. - -**Imports:** - -- `LibParseOperand`, `BaseRainterpreterSubParser`, `OperandV2`, `IParserToolingV1` from rain.interpreter -- `LibConvert` from rain.lib.typecast -- `BadDynamicLength` from rain.interpreter (imported but not used directly in this file) -- `LibExternOpContextSender` from rain.interpreter (imported but not used directly in this file) -- `LibUint256Matrix` from rain.solmem -- Constants from `LibOrderBookSubParser` (word indices and lengths) -- Constants from `LibOrderBook` (context column/row indices) -- Generated pointers from `OrderBookV6SubParser.pointers.sol` -- `IDescribedByMetaV1` from rain.metadata - -**Using directives:** - -- `LibUint256Matrix for uint256[][]` (line 72) - -**Assembly blocks:** - -- Lines 179-181: Reference reinterpretation of `handlers` (function pointer 2D array) to `handlersUint256` (uint256 2D array). Annotated `"memory-safe"`. -- Lines 301-303: Same pattern for `parsers` to `parsersUint256`. Annotated `"memory-safe"`. - -**Array sizing verification (buildOperandHandlerFunctionPointers):** - -- Top-level `handlers` array: length `CONTEXT_COLUMNS + 2 + 1 + 1 = 5 + 4 = 9`. Indices 0-8 all assigned. -- `contextBaseHandlers`: length `CONTEXT_BASE_ROWS = 2`. Indices 0,1 assigned. -- `contextCallingContextHandlers`: length `CONTEXT_CALLING_CONTEXT_ROWS = 3`. Indices 0,1,2 assigned. -- `contextCalculationsHandlers`: length `CONTEXT_CALCULATIONS_ROWS = 2`. Indices 0,1 assigned. -- `contextVaultInputsHandlers`: length `CONTEXT_VAULT_IO_ROWS = 5`. Indices 0,1,2,3,4 assigned. -- `contextVaultOutputsHandlers`: length `CONTEXT_VAULT_IO_ROWS = 5`. Indices 0,1,2,3,4 assigned. -- `contextSignersHandlers`: length `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS = 1`. Index 0 assigned. -- `contextSignedContextHandlers`: length `CONTEXT_SIGNED_CONTEXT_START_ROWS = 1`. Index 0 assigned. -- `contextDepositContextHandlers`: length `DEPOSIT_WORDS_LENGTH = 5`. Indices 0,1,2,3,4 assigned. -- `contextWithdrawContextHandlers`: length `WITHDRAW_WORDS_LENGTH = 6`. Indices 0,1,2,3,4,5 assigned. - -**Array sizing verification (buildSubParserWordParsers):** - -- Identical top-level structure and sub-array dimensions, all slots populated with parser functions. - -## Findings - -No security findings. The contract is a pure configuration/tooling contract with no state mutations, no external calls at runtime, no payable functions, and no authorization concerns. Specifically: - -- All functions are `pure` or `view` (inherited), with no state-changing behavior. -- The assembly blocks perform only reference reinterpretation (no memory writes), correctly annotated `"memory-safe"`. -- All dynamic array slots are fully initialized; no uninitialized function pointer slots exist. -- The contract has no `receive()` or `fallback()` functions accepting ETH. -- Error handling is delegated to the base contract (`BaseRainterpreterSubParser`) which uses custom errors (no string reverts). -- The `buildOperandHandlerFunctionPointers` and `buildSubParserWordParsers` functions are `external pure` tooling functions used at build time for code generation, not at runtime. Their output is baked into the generated pointers file. -- Imported but unused symbols (`BadDynamicLength`, `LibExternOpContextSender`) are not a security concern but are noted. diff --git a/audit/2026-03-13-01/pass1/RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass1/RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 3233531151..0000000000 --- a/audit/2026-03-13-01/pass1/RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,28 +0,0 @@ -# Pass 1: Security — RouteProcessorOrderBookV6ArbOrderTaker.sol - -**Agent:** A07 -**File:** src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol - -## Evidence of Thorough Reading - -- **Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (line 14) -- **Functions:** constructor (line 20), onTakeOrders2 (line 26), fallback (line 52) -- **State:** `iRouteProcessor` (line 18, immutable) - -## Findings - -### A07-1 [LOW] `onTakeOrders2` is public with no access control - -**Location:** Line 26 - -Anyone can call `onTakeOrders2` directly, which grants `type(uint256).max` approval to the route processor on an arbitrary token, executes a caller-controlled route, then resets approval. If the contract holds residual tokens, they could be drained via a crafted route. Mitigated by transient approval window and the contract not designed to hold balances. - -### A07-2 [INFO] Lossy input amount conversion silently discarded - -**Location:** Line 38 - -### A07-3 [INFO] Fallback not payable despite comment - -**Location:** Line 52 - -Same issue as A05-3. diff --git a/audit/2026-03-13-01/pass2/Deploy.md b/audit/2026-03-13-01/pass2/Deploy.md deleted file mode 100644 index 40ffb8a311..0000000000 --- a/audit/2026-03-13-01/pass2/Deploy.md +++ /dev/null @@ -1,91 +0,0 @@ -# Pass 2: Test Coverage — Deploy.sol - -**Agent:** A15 -**File:** `script/Deploy.sol` - -## Evidence of Thorough Reading - -**Contract name:** `Deploy` (inherits `Script` from forge-std) - -**Functions:** -| Function | Line | Visibility | -|---|---|---| -| `deployRouter()` | 52 | internal | -| `run()` | 61 | external | - -**Constants (file-level):** -| Name | Line | Type | -|---|---|---| -| `DEPLOYMENT_SUITE_ALL` | 24 | `bytes32` | -| `DEPLOYMENT_SUITE_RAINDEX` | 25 | `bytes32` | -| `DEPLOYMENT_SUITE_SUBPARSER` | 26 | `bytes32` | -| `DEPLOYMENT_SUITE_ROUTE_PROCESSOR` | 27 | `bytes32` | -| `DEPLOYMENT_SUITE_ARB` | 28 | `bytes32` | -| `ROUTE_PROCESSOR_4_CREATION_CODE` | 38 | `bytes` | -| `ROUTE_PROCESSOR_4_BYTECODE_HASH` | 41 | `bytes32` | - -**Errors (file-level):** -| Name | Line | -|---|---| -| `BadRouteProcessor` | 44 | - -**State variables:** -| Name | Line | Type | -|---|---|---| -| `sDepCodeHashes` | 50 | `mapping(string => mapping(address => bytes32))` | - -## Test Coverage Analysis - -### Search methodology - -1. Searched `test/` for `Deploy`, `deployRouter`, `DEPLOYMENT_SUITE`, `ROUTE_PROCESSOR_4_CREATION_CODE`, `ROUTE_PROCESSOR_4_BYTECODE_HASH`, `BadRouteProcessor` -- none of these reference `script/Deploy.sol` or the `Deploy` contract. -2. Searched for `import.*script/Deploy` across the entire repository -- no test file imports the deploy script. -3. Checked `test/lib/deploy/LibOrderBookDeploy.t.sol` -- this tests `LibOrderBookDeploy` (deployed addresses, codehashes, etch utility) but does NOT test `script/Deploy.sol` itself. -4. Checked CI workflows: `manual-sol-artifacts.yaml` runs `rainix-sol-artifacts` which invokes `forge script script/Deploy.sol:Deploy` in a manually-triggered workflow, and `rainix.yaml` runs `rainix-sol-artifacts` as a CI task. These are dry-run exercises of the full script, not unit tests of individual code paths. - -### Coverage summary - -| Element | Has Unit Test | Has CI Exercise | -|---|---|---| -| `deployRouter()` | NO | Partial (only via `all` or `route-processor` suite) | -| `run()` | NO | Yes (dry-run via `rainix-sol-artifacts` in CI) | -| `DEPLOYMENT_SUITE_*` constants | NO | Indirectly | -| `ROUTE_PROCESSOR_4_CREATION_CODE` | NO | Indirectly | -| `ROUTE_PROCESSOR_4_BYTECODE_HASH` | NO | Indirectly | -| `BadRouteProcessor` error | NO | NO | -| Suite branching (`raindex`, `subparser`, `route-processor`, `arb`, `all`) | NO | Only `all` suite exercised by default CI | -| `sDepCodeHashes` mapping | NO | Indirectly | - -## Findings - -### A15-P2-1 [LOW] No unit test for `deployRouter()` return value on `create` failure - -**Location:** Lines 52-59 - -The `deployRouter()` function uses inline assembly `create` to deploy the route processor. If `create` fails (e.g., out-of-gas during init code, or the creation code is corrupted), it returns `address(0)`. There is no test that verifies: -- That `deployRouter()` successfully deploys a contract with the expected `extcodehash`. -- That `deployRouter()` returning `address(0)` is caught by the downstream `BadRouteProcessor` check (or ideally an explicit zero-address check). - -A dedicated test for `deployRouter()` would validate that the `ROUTE_PROCESSOR_4_CREATION_CODE` constant actually produces a contract with the `ROUTE_PROCESSOR_4_BYTECODE_HASH` codehash, which currently has no automated verification anywhere in the test suite. - -### A15-P2-2 [LOW] `ROUTE_PROCESSOR_4_BYTECODE_HASH` constant is never verified against the actual deployed bytecode in tests - -**Location:** Lines 38-42 - -The constant `ROUTE_PROCESSOR_4_BYTECODE_HASH` is hardcoded at line 41. There is no test that deploys `ROUTE_PROCESSOR_4_CREATION_CODE` and asserts the resulting `extcodehash` matches this constant. If the creation code or the hash were to drift (e.g., during a dependency update), the only way to catch it would be a failed manual deployment. This is the same class of verification that `LibOrderBookDeploy.t.sol` provides for OrderBookV6 and SubParser but is missing for the route processor. - -### A15-P2-3 [LOW] No test for `BadRouteProcessor` error path - -**Location:** Lines 129-135 - -The `BadRouteProcessor` error is defined at line 44 and reverted at line 134 when the route processor's `extcodehash` does not match the expected hash. No test exercises this revert path. A test should verify that providing a mismatched route processor address (or a zero address) triggers `BadRouteProcessor` with the correct expected vs actual hash values. - -### A15-P2-4 [LOW] No test coverage for individual suite isolation (the bug from Pass 1 finding A15-1) - -**Location:** Lines 61-175 - -Pass 1 finding A15-1 identified that running the `raindex` or `subparser` suite in isolation causes an unconditional revert at the route processor bytecode hash check (line 133). There is no test that exercises individual suite paths. A test for each suite value (`raindex`, `subparser`, `route-processor`, `arb`) would have caught this bug, since the `raindex` and `subparser` suites would revert unexpectedly. - -### A15-P2-5 [INFO] Deploy script is exercised via CI dry-run but not unit-tested - -The `rainix-sol-artifacts` task in `rainix.yaml` (line 30) runs the deploy script as a CI job, which provides an integration-level exercise. However, this only runs the `all` suite path (the default) and does not test individual suites, error paths, or edge cases. This is a common pattern for Foundry deploy scripts but means coverage of branching logic and error paths depends entirely on manual deployment. diff --git a/audit/2026-03-13-01/pass2/GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass2/GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index b1a873f40f..0000000000 --- a/audit/2026-03-13-01/pass2/GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,74 +0,0 @@ -# Pass 2: Test Coverage -- GenericPoolOrderBookV6ArbOrderTaker.sol - -**Agent:** A05 -**File:** src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol - -## Evidence of Thorough Reading - -- **Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (line 11), inherits `OrderBookV6ArbOrderTaker` -- **Imports:** `IERC20`, `SafeERC20`, `Address`, `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float` (lines 5-9) -- **Using declarations:** `SafeERC20 for IERC20` (line 12), `Address for address` (line 13) -- **Constructor:** (line 15) -- delegates to `OrderBookV6ArbOrderTaker(config)` -- **`onTakeOrders2`:** (lines 18-35) -- `public virtual override`, decodes `takeOrdersData` into `(address spender, address pool, bytes encodedFunctionCall)`, does `forceApprove(spender, max)`, calls `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)`, then `forceApprove(spender, 0)` -- **`fallback()`:** (line 38) -- `external`, not payable, comment says "Allow receiving gas" -- **No custom errors, events, constants, or structs defined** (all inherited from `OrderBookV6ArbCommon` and `OrderBookV6ArbOrderTaker`) - -## Test Files Examined - -1. `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` -- Tests `arb5` with expression validation (`WrongTask` revert) and mock interpreter `eval4` calls. -2. `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` -- Tests `arb5` as a sender with no expression (empty bytecode). -3. `test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol` -- Thin subclass of `ArbTest` that instantiates `GenericPoolOrderBookV6ArbOrderTaker` via `buildArb`. -4. `test/util/abstract/ArbTest.sol` -- Base test harness providing mock infrastructure: `FlashLendingMockOrderBook`, `Refundoor`, `Token`, `iInterpreter`, `iInterpreterStore`. - -## Findings - -### A05-P2-1 [HIGH] `onTakeOrders2` is completely untested - -**Location:** Lines 18-35 of `GenericPoolOrderBookV6ArbOrderTaker.sol` - -**Evidence:** The string `onTakeOrders2` appears zero times in the entire `test/` directory. The `FlashLendingMockOrderBook.takeOrders4` is a no-op stub (`external pure returns (Float, Float) {}`) that returns immediately without calling `onTakeOrders2` on the taker contract. This means the core business logic of this contract -- the approve-call-revoke pattern on an arbitrary pool -- is never exercised in any test. - -**Impact:** The following behaviors are entirely untested: -- ABI decoding of `takeOrdersData` into `(spender, pool, encodedFunctionCall)` -- `forceApprove(spender, type(uint256).max)` granting unlimited approval -- `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` executing an arbitrary external call with ETH -- `forceApprove(spender, 0)` revoking approval after the call -- Interaction between `super.onTakeOrders2(...)` and the override -- Revert propagation when the pool call fails -- Behavior when `takeOrdersData` is malformed (wrong ABI encoding) - -**Severity rationale:** HIGH because this is the only function that contains non-trivial logic unique to this contract, and it has zero coverage. The constructor is a pass-through, and the fallback is trivial. All security properties identified in Pass 1 (A05-1: unlimited approval, A05-2: ETH drain via arbitrary call) are also untested. - -### A05-P2-2 [MEDIUM] No test for `fallback()` behavior - -**Location:** Line 38 - -**Evidence:** No test sends ETH or arbitrary calldata to the deployed `GenericPoolOrderBookV6ArbOrderTaker` instance. The `fallback()` is not `payable`, so it cannot receive ETH (contradicting its comment). There is no test verifying: -- That the fallback accepts calls with arbitrary calldata -- That the fallback correctly rejects ETH transfers (since it is non-payable) -- That `receive()` is absent, meaning plain ETH transfers revert - -### A05-P2-3 [LOW] Constructor event emission tested only indirectly - -**Location:** Line 15 - -**Evidence:** The `ArbTest` constructor (line 81-82) does `vm.expectEmit(); emit Construct(...)` before calling `buildArb`, which exercises the constructor and verifies the `Construct` event. This provides basic constructor coverage. However, there is no test for constructor behavior with edge-case configs (e.g., empty `implementationData`, zero-address `orderBook`). - -### A05-P2-4 [INFO] Existing tests only cover `arb5` entry point at surface level - -**Evidence:** Both `testGenericPoolTakeOrdersSender` and `testGenericPoolTakeOrdersExpression` call `arb5` but the mock `FlashLendingMockOrderBook.takeOrders4` returns immediately with zero values and never calls back into the taker. The tests effectively only verify: -- The `onlyValidTask` modifier (WrongTask revert path) -- The `nonReentrant` guard is compiled in -- The `arb5` function can be called without reverting when given valid task data -- Interpreter `eval4` is called when expression bytecode is non-empty - -They do NOT verify any token movement, approval lifecycle, or pool interaction. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A05-P2-1 | HIGH | `onTakeOrders2` is completely untested | -| A05-P2-2 | MEDIUM | No test for `fallback()` behavior | -| A05-P2-3 | LOW | Constructor event emission tested only indirectly | -| A05-P2-4 | INFO | Existing tests only cover `arb5` entry point at surface level | diff --git a/audit/2026-03-13-01/pass2/GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass2/GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index 2f1644a1eb..0000000000 --- a/audit/2026-03-13-01/pass2/GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,135 +0,0 @@ -# Pass 2: Test Coverage -- GenericPoolOrderBookV6FlashBorrower.sol -**Agent:** A06 -**Date:** 2026-03-13 -**Source file:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` - -## Evidence of Thorough Reading - -### Contract: `GenericPoolOrderBookV6FlashBorrower` (line 27) -Inherits: `OrderBookV6FlashBorrower` (line 27) - -### Functions -| Function | Line | Visibility | Notes | -|---|---|---|---| -| `constructor(OrderBookV6ArbConfig memory config)` | 31 | public | Delegates to `OrderBookV6FlashBorrower(config)` | -| `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData)` | 34 | internal virtual override | Core exchange logic: decodes `(spender, pool, encodedFunctionCall)`, approves spender, calls pool, revokes approval | -| `fallback()` | 48 | external | Empty fallback to allow receiving gas | - -### Inherited Functions (from `OrderBookV6FlashBorrower`, `src/abstract/OrderBookV6FlashBorrower.sol`) -| Function | Line | Visibility | Notes | -|---|---|---|---| -| `supportsInterface(bytes4)` | 69 | public view virtual override | ERC165 support | -| `onFlashLoan(address, address, uint256, uint256, bytes)` | 85 | external | Flash loan callback; checks `initiator == address(this)`, decodes data, calls `_exchange`, calls `takeOrders4` | -| `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` | 130 | external payable | Entry point; validates task, checks non-empty orders, initiates flash loan, finalizes arb | - -### Inherited Functions (from `OrderBookV6ArbCommon`, `src/abstract/OrderBookV6ArbCommon.sol`) -| Function | Line | Visibility | Notes | -|---|---|---|---| -| `constructor(OrderBookV6ArbConfig memory config)` | 41 | public | Emits `Construct` event, sets `iTaskHash` | -| `onlyValidTask(TaskV2)` | 50 | modifier | Validates task hash matches | - -### Types/Structs -| Type | Location | Notes | -|---|---|---| -| `OrderBookV6ArbConfig` | `OrderBookV6ArbCommon.sol:21` | Config struct (orderBook, task, implementationData) | - -### Errors (from parent contracts) -| Error | Location | Notes | -|---|---|---| -| `BadInitiator(address)` | `OrderBookV6FlashBorrower.sol:24` | When `onFlashLoan` initiator is not `address(this)` | -| `FlashLoanFailed()` | `OrderBookV6FlashBorrower.sol:27` | When `flashLoan` returns false | -| `SwapFailed()` | `OrderBookV6FlashBorrower.sol:30` | Declared but never used in the codebase | -| `WrongTask()` | `OrderBookV6ArbCommon.sol:28` | When task hash does not match | -| `NonZeroBeforeArbStack()` | `LibOrderBookArb.sol:14` | Declared, unused in arb path | -| `BadLender(address)` | `LibOrderBookArb.sol:18` | Declared, unused in flash borrower path | -| `NoOrders()` | `IRaindexV6` (interface) | When `takeOrders.orders.length == 0` | - -### Events -| Event | Location | Notes | -|---|---|---| -| `Construct(address, OrderBookV6ArbConfig)` | `OrderBookV6ArbCommon.sol:37` | Emitted on construction | - -### Constants -| Constant | Location | Notes | -|---|---|---| -| `BEFORE_ARB_SOURCE_INDEX` | `OrderBookV6ArbCommon.sol:32` | `SourceIndexV2.wrap(0)` | -| `ON_FLASH_LOAN_CALLBACK_SUCCESS` | imported | Return value for `onFlashLoan` | - -## Test Coverage Inventory - -### Direct Test File -- `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol` -- 1 fuzz test - -### What Is Tested -1. **`testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender`** (line 31): Fuzz test exercising the happy path of `arb4` with fuzzed `OrderV4`, `inputIOIndex`, `outputIOIndex`. Uses `FlashLendingMockOrderBook` which mocks the flash loan and `takeOrders4`. Validates that the `arb4` call succeeds with a mock that passes `exchangeData = abi.encode(iRefundoor, iRefundoor, "")`. - -### Indirect Coverage (Parent Abstract Tests) -- `test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol`: Tests ERC165 `supportsInterface` for the abstract parent using a minimal child contract. -- `test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol`: Tests flash loan success from the lender side. -- `test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol`: Tests flash loan griefing from the lender side. - -### Sibling Coverage (for comparison) -- `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol`: Tests `WrongTask` revert and expression evaluation for the `ArbOrderTaker` sibling. **No equivalent test exists for `GenericPoolOrderBookV6FlashBorrower`.** - -## Coverage Gaps - -### GAP-1: No test for `BadInitiator` error path [LOW] -**ID:** P2-GPOBV6FB-01 -**Severity:** LOW -**Description:** The `onFlashLoan` function in `OrderBookV6FlashBorrower` (line 85-107) checks that `initiator == address(this)` and reverts with `BadInitiator` if not. There is no test that calls `onFlashLoan` directly with a wrong initiator to verify this guard. -**Risk:** If the initiator check were accidentally removed or weakened, no test would catch the regression. An attacker calling `onFlashLoan` directly with arbitrary parameters could manipulate the contract's token approvals and trigger external calls. - -### GAP-2: No test for `FlashLoanFailed` error path [LOW] -**ID:** P2-GPOBV6FB-02 -**Severity:** LOW -**Description:** The `arb4` function (line 159) checks the return value of `orderBook.flashLoan(...)` and reverts with `FlashLoanFailed()` if it returns false. The mock `FlashLendingMockOrderBook` always returns `true`. There is no test where `flashLoan` returns `false`. -**Risk:** If the revert guard were removed, a failed flash loan would silently continue execution, potentially leading to unexpected state changes or loss of funds. - -### GAP-3: No test for `WrongTask` on `GenericPoolOrderBookV6FlashBorrower` [LOW] -**ID:** P2-GPOBV6FB-03 -**Severity:** LOW -**Description:** The sibling `GenericPoolOrderBookV6ArbOrderTaker` has a dedicated `expression.t.sol` test that exercises the `WrongTask` revert and task evaluation path. No equivalent test exists for `GenericPoolOrderBookV6FlashBorrower`. While the `onlyValidTask` modifier is in the shared parent `OrderBookV6ArbCommon`, it should be verified that it is correctly applied in this concrete contract. -**Risk:** If the `onlyValidTask` modifier were accidentally removed from `arb4` in a future refactor, no test specific to the flash borrower would catch it. - -### GAP-4: No test for `NoOrders` revert in `arb4` [LOW] -**ID:** P2-GPOBV6FB-04 -**Severity:** LOW -**Description:** The `arb4` function (line 137-139) checks `takeOrders.orders.length == 0` and reverts with `NoOrders()`. This is tested for the OrderBook directly (`OrderBookV6.takeOrder.noop.t.sol`) but not via the arb contract's `arb4` entry point. -**Risk:** Low, since the check is straightforward and unlikely to regress, but it represents a code path without direct coverage. - -### GAP-5: No test for `_exchange` failure propagation [LOW] -**ID:** P2-GPOBV6FB-05 -**Severity:** LOW -**Description:** The `_exchange` function calls `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` (line 41). If the external call reverts, this should propagate. There are no tests verifying that a reverting pool call correctly propagates the revert through the flash loan flow. -**Risk:** If `Address.functionCallWithValue` error propagation were broken, funds could be locked or lost. - -### GAP-6: No test for `fallback()` gas reception [INFO] -**ID:** P2-GPOBV6FB-06 -**Severity:** INFO -**Description:** The `fallback()` on line 48 allows the contract to receive gas (ETH). There is no test that sends ETH directly to the contract to verify this works. This is implicitly exercised by the `functionCallWithValue` call if the pool refunds gas, but there's no explicit test. - -### GAP-7: `SwapFailed` error is declared but never used [INFO] -**ID:** P2-GPOBV6FB-07 -**Severity:** INFO -**Description:** The error `SwapFailed()` is declared at line 30 of `OrderBookV6FlashBorrower.sol` but is never referenced anywhere in the contract or its children. This is dead code. - -### GAP-8: No test for reentrancy guard on `arb4` [INFO] -**ID:** P2-GPOBV6FB-08 -**Severity:** INFO -**Description:** The `arb4` function uses the `nonReentrant` modifier. There is no test attempting reentrancy to verify the guard works. While OpenZeppelin's `ReentrancyGuard` is well-tested upstream, a regression test for the integration would be valuable. - -### GAP-9: Mock `FlashLendingMockOrderBook` does not validate flash loan repayment [INFO] -**ID:** P2-GPOBV6FB-09 -**Severity:** INFO -**Description:** The mock `FlashLendingMockOrderBook.flashLoan` does not check that the borrower repays the loan. It simply calls `onFlashLoan` and returns true. This means the happy-path test does not verify that approval/repayment mechanics work correctly with real token balances. The `_exchange` function's `forceApprove` calls (lines 40, 44) are never verified to interact correctly with real token transfers. - -## Summary - -| Severity | Count | -|---|---| -| HIGH | 0 | -| MEDIUM | 0 | -| LOW | 5 | -| INFO | 4 | - -The test suite for `GenericPoolOrderBookV6FlashBorrower` consists of a single fuzz test that exercises the happy path. There are no negative tests (error path coverage), no tests for access control (`WrongTask`), no tests for the `BadInitiator` guard, and no tests for `FlashLoanFailed`. The sibling `GenericPoolOrderBookV6ArbOrderTaker` has better coverage with a dedicated expression test file, suggesting the flash borrower variant was overlooked for equivalent coverage. diff --git a/audit/2026-03-13-01/pass2/LibOrder.md b/audit/2026-03-13-01/pass2/LibOrder.md deleted file mode 100644 index b8ffe6eb8e..0000000000 --- a/audit/2026-03-13-01/pass2/LibOrder.md +++ /dev/null @@ -1,77 +0,0 @@ -# Pass 2: Test Coverage -- LibOrder.sol -**Agent:** A10 -**Date:** 2026-03-13 - -## Source File Summary - -**File:** `src/lib/LibOrder.sol` (19 lines) -**Library:** `LibOrder` - -### Imports -- `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5) - -### Functions -| Function | Line | Visibility | Mutability | Description | -|----------|------|-----------|------------|-------------| -| `hash(OrderV4 memory order)` | 16-18 | `internal` | `pure` | Returns `keccak256(abi.encode(order))` | - -### Types/Errors/Constants/Events -None. The library defines no custom types, errors, constants, or events. - -### OrderV4 Struct (external dependency) -```solidity -struct OrderV4 { - address owner; - EvaluableV4 evaluable; - IOV2[] validInputs; - IOV2[] validOutputs; - bytes32 nonce; -} -``` - -## Test File Summary - -**File:** `test/lib/LibOrder.t.sol` (23 lines) -**Contract:** `LibOrderTest is Test` - -### Tests -| Test | Line | Type | Description | -|------|------|------|-------------| -| `testHashEqual(OrderV4 memory a)` | 14-16 | Fuzz (100 runs) | Asserts `hash(a) == hash(a)` | -| `testHashNotEqual(OrderV4 memory a, OrderV4 memory b)` | 20-22 | Fuzz (100 runs) | Asserts `hash(a) != hash(b)` | - -## Coverage Gaps - -### Function Coverage -- `hash`: Covered by both tests. **100% function coverage.** - -### CG-1: `testHashNotEqual` is logically incorrect (LOW) - -**ID:** A10-1 - -The test on lines 20-22 unconditionally asserts `LibOrder.hash(a) != LibOrder.hash(b)` for any fuzz-generated inputs `a` and `b`. If the fuzzer ever generates two identical `OrderV4` values, the assertion fails -- equal inputs must produce equal hashes. The test should include `vm.assume(keccak256(abi.encode(a)) != keccak256(abi.encode(b)))` or an equivalent guard. - -In practice, with a complex struct containing dynamic arrays and 100 fuzz runs, collision probability is negligible, so the test likely never fails. However, the test's logical contract is wrong: it claims "different inputs produce different hashes" but does not actually ensure the inputs are different. - -**Impact:** A fuzzer seed change, increased fuzz runs, or a targeted fuzzer could cause a spurious failure. More importantly, the test gives a false sense of coverage -- it does not actually prove collision resistance for distinct inputs because it never validates distinctness. - -### CG-2: No known-value / reference hash test (INFO) - -There is no test that computes a hash for a specific hardcoded `OrderV4` and compares against a known expected `bytes32` value. Such a test would serve as a regression guard: if the encoding method were accidentally changed (e.g., `abi.encode` to `abi.encodePacked`), it would catch the change. - -### CG-3: No single-field-delta tests (INFO) - -No tests verify that changing exactly one field of an `OrderV4` (e.g., only `nonce`, only `owner`) produces a different hash. While `abi.encode` is well-understood to be injective for distinct struct values, explicit single-field tests would provide targeted regression coverage and document the expected behavior for each field. - -### CG-4: No empty-array edge case test (INFO) - -No test explicitly covers orders with empty `validInputs` and/or `validOutputs` arrays. `abi.encode` handles empty dynamic arrays correctly, but an explicit test would document this assumption. - -## Findings Summary - -| ID | Severity | Title | -|----|----------|-------| -| A10-1 | LOW | `testHashNotEqual` lacks assumption guard -- asserts inequality without ensuring inputs differ | -| A10-2 | INFO | No known-value regression test for hash output | -| A10-3 | INFO | No single-field-delta collision tests | -| A10-4 | INFO | No empty-array edge case test | diff --git a/audit/2026-03-13-01/pass2/LibOrderBook.md b/audit/2026-03-13-01/pass2/LibOrderBook.md deleted file mode 100644 index d8bfcd8108..0000000000 --- a/audit/2026-03-13-01/pass2/LibOrderBook.md +++ /dev/null @@ -1,116 +0,0 @@ -# Pass 2: Test Coverage -- LibOrderBook.sol -**Agent:** A11 -**Date:** 2026-03-13 - -## Source File Summary - -**File:** `src/lib/LibOrderBook.sol` (125 lines) -**Library:** `LibOrderBook` (line 96) - -### Imports -- `CONTEXT_BASE_ROWS`, `CONTEXT_BASE_ROW_SENDER`, `CONTEXT_BASE_ROW_CALLING_CONTRACT`, `CONTEXT_BASE_COLUMN` from `LibContext.sol` -- `TaskV2` from `IRaindexV6.sol` -- `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4` from `IInterpreterV4.sol` -- `LibNamespace`, `FullyQualifiedNamespace` from `LibNamespace.sol` -- `LibContext` from `LibContext.sol` - -### Functions -| Function | Line | Visibility | Mutability | Description | -|----------|------|-----------|------------|-------------| -| `doPost(bytes32[][] memory context, TaskV2[] memory post)` | 97-124 | `internal` | (state-changing) | Iterates over `post` tasks, evals each with non-empty bytecode, writes state if writes are non-empty | - -This is the only function in the library. - -### Types/Errors/Constants -No custom errors, structs, or events are defined in this library. The file defines 30 file-level constants (lines 28-94) describing context layout columns and rows for order evaluation (calling context, calculations, vault I/O, signed context). - -### Code Paths in `doPost` -1. **Empty post array:** Loop never executes (line 103) -2. **Task with empty bytecode:** `bytecode.length == 0` check skips eval (line 105) -3. **Task with bytecode, no writes:** Eval runs, writes are empty, `store.set` is skipped (line 119) -4. **Task with bytecode and writes:** Eval runs, `store.set` is called (lines 119-121) -5. **Signed context integration:** `LibContext.build(context, task.signedContext)` merges signed context into the context array (line 113) - -## Test Coverage Map - -There is no direct unit test file for `LibOrderBook`. The `doPost` function is tested indirectly through the following callers: - -### Call Sites in Production Code -| Call Site | File | Line | Context Passed | -|-----------|------|------|----------------| -| `entask2` | `OrderBookV6.sol` | 255 | `new bytes32[][](0)` (empty) | -| `deposit4` | `OrderBookV6.sol` | 278 | 1-column matrix: token, vaultId, balanceBefore, balanceAfter, decimals | -| `withdraw4` | `OrderBookV6.sol` | 328 | 1-column matrix: token, vaultId, balanceBefore, balanceAfter, targetAmount, decimals | -| `addOrder4` | `OrderBookV6.sol` | 371 | 1-column matrix: orderHash, owner | -| `removeOrder3` | `OrderBookV6.sol` | 397 | 1-column matrix: orderHash, owner | -| `finalizeArb` | `LibOrderBookArb.sol` | 75 | 1-column matrix: inputBalance, outputBalance, gasBalance | - -### Test Files Exercising `doPost` -| Test File | Entry Point | Code Paths Covered | -|-----------|-------------|-------------------| -| `OrderBookV6.entask.t.sol` | `entask2` | Paths 1,2,3,4 | -| `OrderBookV6.deposit.entask.t.sol` | `deposit4` | Paths 1,2,3,4 + context validation | -| `OrderBookV6.withdraw.entask.t.sol` | `withdraw4` | Paths 1,2,3,4 + context validation | -| `OrderBookV6.addOrder.entask.t.sol` | `addOrder4` | Paths 1,2,3,4 + context validation + noop when already live | -| `OrderBookV6.removeOrder.entask.t.sol` | `removeOrder3` | Paths 1,2,3,4 + noop when dead | -| `GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | `arb5` (via `finalizeArb`) | Path 3,4 (mocked interpreter) | - -### Per-Code-Path Coverage Detail - -| Code Path | Covered | Where | -|-----------|---------|-------| -| 1. Empty post array | YES | `testOrderBookEvalEmptyNoop` and equivalent in all entask test files | -| 2. Empty bytecode task | PARTIAL | Implicitly -- no test explicitly creates a `TaskV2` with zero-length bytecode through a real entask call | -| 3. Eval with no writes | YES | `testOrderBookEvalOneStateless` (evals `_:1;` which produces no writes) | -| 4. Eval with writes | YES | `testOrderBookEvalWriteStateSingle`, `testOrderBookEvalWriteStateSequential` and equivalents in all entask files | -| 5. Signed context | NO | All entask tests pass `new SignedContextV1[](0)`. No test passes a non-empty `signedContext` array through a `doPost` path | - -## Coverage Gaps - -### CG-1: No test with non-empty `signedContext` in any `doPost` path (LOW) - -**ID:** A11-P2-1 - -All test files that exercise `doPost` (entask, deposit, withdraw, addOrder, removeOrder) construct `TaskV2` with `new SignedContextV1[](0)`. The `doPost` function passes `task.signedContext` to `LibContext.build(context, task.signedContext)` (line 113), which merges signed context columns into the evaluation context. This code path is never tested through `doPost`. - -While `LibContext.build` itself may be tested upstream in `rain.interpreter.interface`, and the `SignedContextV1` mechanism is tested through `takeOrders`/`clear` paths which use it during order evaluation (not through `doPost`), the specific integration of signed context with post-task evaluation is untested. - -**Impact:** If `LibContext.build` had a bug specifically triggered when called from a post-task evaluation context (e.g., an interaction with the particular shape of the `context` array passed to `doPost`), it would not be caught by existing tests. - -### CG-2: `testRemoveOrderContext` does not actually test context (LOW) - -**ID:** A11-P2-2 - -In `test/concrete/ob/OrderBookV6.removeOrder.entask.t.sol`, the `testRemoveOrderContext` test (line 181) calls `checkRemoveOrder(alice, config, evals, 0, 0, false)` with `addOrder` = `false` (line 208). When `addOrder` is false, the order is never added so it is already dead. `removeOrder3` detects the order is dead (`sOrders[orderHash] != ORDER_LIVE`), returns `stateChanged = false`, and skips the call to `LibOrderBook.doPost` entirely. This means the context assertions in the eval strings (checking `orderbook()`, `order-hash()`, `order-owner()`) are **never actually executed**. - -The test passes because `expectedReads = 0` and `expectedWrites = 0` -- which is correct for a noop where doPost is never called, but the test name and the eval strings suggest the intent was to validate context values during removeOrder post-evaluation. - -**Impact:** The removeOrder context (orderHash, orderOwner) is not validated by any test. A bug in the context construction at `OrderBookV6.sol` lines 397-402 would not be caught. - -### CG-3: No test for task revert atomicity through `entask2` (INFO) - -**ID:** A11-P2-3 - -The `deposit.entask` and `withdraw.entask` test files both have explicit revert-in-action tests (`testDepositRevertInAction`, `testOrderBookWithdrawalEvalRevertInAction`) that verify a revert in a post-task reverts the entire transaction (including the deposit/withdraw). The `addOrder.entask` and `removeOrder.entask` files also have these tests. However, `OrderBookV6.entask.t.sol` (the standalone `entask2` path) has no revert test. Since `entask2` has no other state changes to roll back, a revert test would mainly confirm that the revert propagates out of `entask2`, which is trivially expected, but it would round out the test pattern. - -### CG-4: No test for multiple tasks with different signed contexts (INFO) - -**ID:** A11-P2-4 - -The `doPost` function iterates over an array of `TaskV2`, each potentially with its own `signedContext`. No test verifies that different tasks in the same `doPost` call can have different signed contexts that are independently evaluated. - -### CG-5: Namespace isolation for `doPost` through arb path is not directly tested (INFO) - -**ID:** A11-P2-5 - -When `doPost` is called from `LibOrderBookArb.finalizeArb`, the namespace is derived from `msg.sender` which is the arb bot address (not the order owner). The arb expression test (`GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol`) mocks the interpreter entirely, so it does not test that state written by the arb's post-task is correctly namespaced under the arb bot's address. The `entask2` tests do validate namespace isolation between different `msg.sender` addresses, which covers the mechanism, but the arb-specific integration is untested with real interpreter. - -## Findings Summary - -| ID | Severity | Title | -|----|----------|-------| -| A11-P2-1 | LOW | No test with non-empty `signedContext` in any `doPost` path | -| A11-P2-2 | LOW | `testRemoveOrderContext` never executes its context assertions (dead order noop) | -| A11-P2-3 | INFO | No revert-propagation test for standalone `entask2` | -| A11-P2-4 | INFO | No test for multiple tasks with different signed contexts | -| A11-P2-5 | INFO | Arb-path namespace isolation not tested with real interpreter | diff --git a/audit/2026-03-13-01/pass2/LibOrderBookArb.md b/audit/2026-03-13-01/pass2/LibOrderBookArb.md deleted file mode 100644 index 791d02b990..0000000000 --- a/audit/2026-03-13-01/pass2/LibOrderBookArb.md +++ /dev/null @@ -1,132 +0,0 @@ -# Pass 2: Test Coverage — LibOrderBookArb.sol -**Agent:** A12 -**File:** src/lib/LibOrderBookArb.sol - -## Evidence of Thorough Reading - -**Library:** `LibOrderBookArb` (line 20) - -### Errors / Types / Constants -| Item | Kind | Line | -|------|------|------| -| `NonZeroBeforeArbStack()` | error | 14 | -| `BadLender(address)` | error | 18 | - -### Functions -| Function | Visibility | Line | -|----------|-----------|------| -| `finalizeArb(TaskV2, address, uint8, address, uint8)` | internal | 23 | - -### Imports Used -- `TaskV2` from `rain.raindex.interface` (line 5) -- `IERC20` from OpenZeppelin (line 6) -- `LibOrderBook` (line 7) -- `Address` from OpenZeppelin (line 8) -- `SafeERC20` from OpenZeppelin (line 9) -- `IERC20Metadata` from OpenZeppelin (line 10) -- **imported but unused** -- `LibDecimalFloat`, `Float` from `rain.math.float` (line 11) - -## Function Analysis: `finalizeArb` - -`finalizeArb` performs three sequential operations: - -1. **Input token sweep** (lines 33-42): Reads `balanceOf(address(this))` for `ordersInputToken`, transfers any non-zero balance to `msg.sender` via `safeTransfer`, converts balance to `Float` via `fromFixedDecimalLossyPacked` using `inputDecimals`, stores in `col[0]`. - -2. **Output token sweep** (lines 44-54): Same pattern for `ordersOutputToken` with `outputDecimals`, stores in `col[1]`. - -3. **Native gas sweep** (lines 56-69): Reads `address(this).balance`, sends entire balance to `msg.sender` via `Address.sendValue`, converts to `Float` via `packLossless` with hardcoded `-18` exponent, stores in `col[2]`. - -4. **Post-task dispatch** (lines 71-75): Wraps the 3-element column into a context matrix and calls `LibOrderBook.doPost(context, post)` with the task. - -## Test Inventory - -### Direct Tests -**None.** There is no test file for `LibOrderBookArb` itself. A grep for `LibOrderBookArb`, `finalizeArb`, `NonZeroBeforeArbStack`, and `BadLender` across the entire `test/` directory returns zero results. - -### Indirect Coverage via Consumer Contracts - -| Test File | What it exercises | -|-----------|-------------------| -| `test/abstract/OrderBookV6ArbOrderTaker.context.t.sol` | Calls `arb5` which calls `finalizeArb`. Mocks `balanceOf` to return `3e12` (input) and `4e12` (output), sets `vm.deal` to `5e18`. Validates context column values via a Rain expression in the task. | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` | Fuzz test of `arb5` happy path (mock tokens, zero balances). Exercises `finalizeArb` with default-zero token balances and no gas balance. | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol` | Fuzz test of `arb4` happy path. Exercises `finalizeArb` after flash loan with zero balances. | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol` | Same as GenericPool but for RouteProcessor variant. | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | Tests `arb5` with expression eval, exercises `finalizeArb` indirectly. | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` | Same as above for RouteProcessor variant. | - -### Coverage Assessment for Each Code Path - -| Code Path | Covered? | Notes | -|-----------|----------|-------| -| Input token balance > 0, `safeTransfer` to `msg.sender` | Partial | Context test mocks `balanceOf` to non-zero and mocks `transfer` to true. Transfer destination/amount are NOT asserted. | -| Input token balance == 0, skip transfer | Yes (implicit) | Most fuzz tests use mock tokens with zero balance. | -| Output token balance > 0, `safeTransfer` to `msg.sender` | Partial | Same as input: mocked but transfer args unverified. | -| Output token balance == 0, skip transfer | Yes (implicit) | Same as above. | -| Native gas balance > 0, `Address.sendValue` | Partial | Context test sets `vm.deal(arb, 5e18)`. But no assertion on the actual ETH transfer to `msg.sender`. | -| Native gas balance == 0, `Address.sendValue(0)` | Yes (implicit) | Fuzz tests with no `vm.deal`. | -| `fromFixedDecimalLossyPacked` for various decimals | Minimal | Context test uses 12-decimal tokens. No test with 0, 6, 8, or 18 decimals. | -| `packLossless` for gas balance | Minimal | Only tested with `5e18`. No edge-case values. | -| `doPost` called with correct context shape | Partial | Context test verifies values via expression, but does not verify the context matrix dimensions. | - -## Findings - -### A12-P2-1 [LOW] `NonZeroBeforeArbStack` and `BadLender` errors are dead code with zero test coverage - -**Location:** Lines 14, 18 - -These two errors are defined in `LibOrderBookArb.sol` but are never used anywhere in the library's code. They are imported by `OrderBookV6ArbOrderTaker.sol` (line 20) and `OrderBookV6FlashBorrower.sol` (line 18), but are never referenced in those contracts' code either -- they appear only in `import` statements. No test references either error. - -This is dead code. The errors either belonged to an earlier version of the arb logic that has since been refactored, or they were intended for use that was never implemented. - -**Impact:** Dead error declarations create confusion for auditors and developers who may expect corresponding revert conditions to exist. If these errors were meant to guard against real attack vectors (e.g., an unauthorized flash loan lender calling `onFlashLoan`), the missing guards represent a security gap. However, `onFlashLoan` in `OrderBookV6FlashBorrower` already uses `BadInitiator` (a separate error declared in that file), so `BadLender` appears to be a leftover. - -### A12-P2-2 [LOW] No test verifies that token transfers in `finalizeArb` go to the correct recipient with correct amounts - -**Location:** Lines 36-37, 47-48 - -The context test (`OrderBookV6ArbOrderTaker.context.t.sol`) mocks `IERC20.balanceOf` and `IERC20.transfer` but does not use `vm.expectCall` to verify that `safeTransfer` is called with `msg.sender` as the recipient and the full balance as the amount. The mock accepts any `transfer` call and returns `true`. - -A bug that transferred tokens to `address(0)`, to `address(this)`, or transferred a partial amount would pass all existing tests. - -**Impact:** The core economic purpose of `finalizeArb` -- sweeping profit to the arb caller -- has no assertion on the actual transfer parameters. - -### A12-P2-3 [LOW] No test verifies native gas (ETH) is actually sent to `msg.sender` - -**Location:** Lines 63-64 - -The context test sets `vm.deal(address(arbOrderTaker), 5e18)` and verifies that the gas balance appears in the context column. But there is no assertion that `msg.sender`'s ETH balance increased by `5e18` after the call, or that the arb contract's balance is zero afterward. A bug in the `Address.sendValue` call (e.g., sending to `address(this)` instead of `msg.sender`) would not be caught. - -**Impact:** The ETH sweep is a critical part of arb profit extraction. Without balance assertions, a loss-of-funds bug could go undetected. - -### A12-P2-4 [LOW] No test exercises `finalizeArb` with realistic non-zero balances of both tokens simultaneously - -**Location:** Lines 33-54 - -The context test sets non-zero balances for both input and output tokens, but uses mocked (non-real) ERC20 tokens. The fuzz tests in `GenericPool*` and `RouteProcessor*` use real `Token` contracts but the mock orderbook's `takeOrders4` is a no-op that never produces token balances. No test creates a scenario where `finalizeArb` actually has real ERC20 balances to sweep. - -**Impact:** The interaction between `balanceOf`, `safeTransfer`, and the post-task context values is never tested with real token contracts. Subtle issues like token transfer fees, re-entrancy through ERC777-like tokens, or `safeTransfer` revert behavior on non-standard tokens are completely unexercised. - -### A12-P2-5 [INFO] `fromFixedDecimalLossyPacked` lossy conversion is explicitly silenced - -**Location:** Lines 39-40, 51-52 - -The `lossless` return value from `fromFixedDecimalLossyPacked` is captured but discarded: `(lossless);`. This means the context column values passed to the post-task expression may be imprecise representations of the actual token balances. There is no test that verifies lossless conversion for common decimal values (6, 8, 18) or that documents the expected precision loss for extreme values. - -### A12-P2-6 [INFO] `IERC20Metadata` import is unused - -**Location:** Line 10 - -`IERC20Metadata` is imported but never used in the library. This was also noted in Pass 1 (A11-1). No test impact, but it adds a spurious dependency. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A12-P2-1 | LOW | `NonZeroBeforeArbStack` and `BadLender` are dead code with zero coverage | -| A12-P2-2 | LOW | No test verifies token transfer recipient and amount in `finalizeArb` | -| A12-P2-3 | LOW | No test verifies native gas is sent to `msg.sender` | -| A12-P2-4 | LOW | No test exercises `finalizeArb` with real non-zero token balances | -| A12-P2-5 | INFO | Lossy float conversion is silently discarded, untested for precision | -| A12-P2-6 | INFO | Unused `IERC20Metadata` import (confirms A11-1) | - -The library has zero direct test coverage. All coverage is indirect through consumer contracts (`OrderBookV6ArbOrderTaker` and `OrderBookV6FlashBorrower`), and the existing tests rely heavily on mocked ERC20 behavior. The mocks verify that `finalizeArb` produces correct context column values for the post-task, but do not verify the actual token/ETH transfers that constitute the library's core purpose. diff --git a/audit/2026-03-13-01/pass2/LibOrderBookDeploy.md b/audit/2026-03-13-01/pass2/LibOrderBookDeploy.md deleted file mode 100644 index 0711bfeccc..0000000000 --- a/audit/2026-03-13-01/pass2/LibOrderBookDeploy.md +++ /dev/null @@ -1,95 +0,0 @@ -# Pass 2: Test Coverage -- LibOrderBookDeploy.sol - -**Agent:** A14 -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` -**Test file:** `test/lib/deploy/LibOrderBookDeploy.t.sol` - -## Evidence of Thorough Reading - -**Library name:** `LibOrderBookDeploy` - -**Functions (with line numbers):** -- `etchOrderBook(Vm vm)` -- line 45 (internal). Etches runtime bytecode for both OrderBookV6 and OrderBookV6SubParser at their expected deterministic addresses, skipping any contract whose codehash already matches. - -**Constants (with line numbers):** -- `ORDERBOOK_DEPLOYED_ADDRESS` (address) -- line 27 -- `ORDERBOOK_DEPLOYED_CODEHASH` (bytes32) -- line 31 -- `SUB_PARSER_DEPLOYED_ADDRESS` (address) -- line 35 -- `SUB_PARSER_DEPLOYED_CODEHASH` (bytes32) -- line 39 - -**Types/errors/custom types:** None. - -**Imports:** -- `Vm` from `forge-std/Vm.sol` (line 5) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6.pointers.sol` (lines 7-11) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6SubParser.pointers.sol` (lines 12-16) - -## Test Inventory - -The test file `test/lib/deploy/LibOrderBookDeploy.t.sol` contains 10 tests in `LibOrderBookDeployTest`: - -| # | Test | What it covers | -|---|------|----------------| -| 1 | `testDeployAddressOrderBook` | Zoltu deploy of OrderBookV6 produces expected address and codehash | -| 2 | `testDeployAddressSubParser` | Zoltu deploy of SubParser produces expected address and codehash | -| 3 | `testExpectedCodeHashOrderBook` | Fresh `new OrderBookV6()` codehash matches constant | -| 4 | `testExpectedCodeHashSubParser` | Fresh `new OrderBookV6SubParser()` codehash matches constant | -| 5 | `testCreationCodeOrderBook` | Generated creation code constant matches compiler output | -| 6 | `testCreationCodeSubParser` | Generated creation code constant matches compiler output | -| 7 | `testRuntimeCodeOrderBook` | Generated runtime code constant matches deployed bytecode | -| 8 | `testRuntimeCodeSubParser` | Generated runtime code constant matches deployed bytecode | -| 9 | `testGeneratedDeployedAddressOrderBook` | Generated address constant matches library constant | -| 10 | `testGeneratedDeployedAddressSubParser` | Generated address constant matches library constant | -| 11 | `testEtchOrderBook` | After `etchOrderBook`, both addresses have correct codehash | -| 12 | `testEtchOrderBookIdempotent` | Calling `etchOrderBook` twice is idempotent | - -## Coverage Analysis - -### Constants coverage - -All four constants (`ORDERBOOK_DEPLOYED_ADDRESS`, `ORDERBOOK_DEPLOYED_CODEHASH`, `SUB_PARSER_DEPLOYED_ADDRESS`, `SUB_PARSER_DEPLOYED_CODEHASH`) are thoroughly verified: -- Against Zoltu factory deployments (tests 1-2) -- Against direct `new` deployments (tests 3-4) -- Against generated pointer file values (tests 9-10) -- Creation code and runtime code constants also cross-checked (tests 5-8) - -This is strong multi-angle validation that the generated constants are correct. - -### Function coverage: `etchOrderBook` - -The function has two independent conditional branches (lines 46-48 and lines 49-51), creating four possible execution paths: - -| Path | OB needs etch | SP needs etch | Tested? | -|------|--------------|---------------|---------| -| A | Yes | Yes | Yes -- `testEtchOrderBook` (fresh state, both addresses empty) | -| B | No | No | Yes -- `testEtchOrderBookIdempotent` (second call) | -| C | Yes | No | No | -| D | No | Yes | No | - -Paths C and D (partial etch) are not directly tested. In path C, OrderBook is missing but SubParser is already etched. In path D, the reverse. - -### Integration coverage - -The library is also exercised indirectly in test utilities: -- `OrderBookV6ExternalMockTest` constructor calls `LibOrderBookDeploy.etchOrderBook(vm)` (line 51) -- `OrderBookV6ExternalRealTest` and `OrderBookV6SubParserContextTest` also use it -- `Deploy.sol` script references the constants for production deployments - -## Findings - -### INFO-A14-1: Partial etch paths (C and D) are untested - -**Severity:** INFO -**Location:** `etchOrderBook` lines 46-51 - -The two `if` guards in `etchOrderBook` are independent, but tests only exercise both-need-etch (path A) and neither-needs-etch (path B). Paths where only one contract needs etching are not directly tested. - -**Impact:** Negligible. The two `if` blocks are structurally independent -- they share no state, no variables, and no control flow coupling. Each branch is a simple comparison + `vm.etch` call. The combined paths (A and B) already exercise both the "etch" and "skip" logic for each branch, just not in the mixed combination. There is no realistic scenario where testing paths C or D would reveal a bug that A and B do not. - -**Recommendation:** No action required. Adding explicit tests for partial etch would marginally improve formal branch coverage but provides no practical security benefit given the simplicity of the code. - -## Summary - -Test coverage for `LibOrderBookDeploy.sol` is thorough and well-structured. The tests take a commendable multi-angle verification approach: every constant is validated against Zoltu factory deployment, direct deployment, and generated pointer files. The `etchOrderBook` function is tested for both the initial etch case and idempotency. The only untested paths are partial-etch combinations, which are structurally independent branches with no interaction effects, making this an informational observation only. - -No LOW+ findings. No fix files required. diff --git a/audit/2026-03-13-01/pass2/LibOrderBookSubParser.md b/audit/2026-03-13-01/pass2/LibOrderBookSubParser.md deleted file mode 100644 index 70d07d3a29..0000000000 --- a/audit/2026-03-13-01/pass2/LibOrderBookSubParser.md +++ /dev/null @@ -1,138 +0,0 @@ -# Pass 2: Test Coverage -- LibOrderBookSubParser.sol -**Agent:** A13 -**Date:** 2026-03-13 -**File:** `src/lib/LibOrderBookSubParser.sol` (599 lines) - -## Evidence of Thorough Reading - -### Library -- `LibOrderBookSubParser` (line 98) - -### Constants (lines 48-95) -- `SUB_PARSER_WORD_PARSERS_LENGTH` (line 48) = 2 -- `EXTERN_PARSE_META_BUILD_DEPTH` (line 49) = 1 -- Word constants (lines 51-80): `WORD_ORDER_CLEARER`, `WORD_ORDERBOOK`, `WORD_ORDER_HASH`, `WORD_ORDER_OWNER`, `WORD_ORDER_COUNTERPARTY`, `WORD_CALCULATED_MAX_OUTPUT`, `WORD_CALCULATED_IO_RATIO`, `WORD_INPUT_TOKEN`, `WORD_INPUT_TOKEN_DECIMALS`, `WORD_INPUT_VAULT_ID`, `WORD_INPUT_VAULT_BALANCE_BEFORE`, `WORD_INPUT_VAULT_BALANCE_INCREASE`, `WORD_OUTPUT_TOKEN`, `WORD_OUTPUT_TOKEN_DECIMALS`, `WORD_OUTPUT_VAULT_ID`, `WORD_OUTPUT_VAULT_BALANCE_BEFORE`, `WORD_OUTPUT_VAULT_BALANCE_DECREASE`, `WORD_DEPOSITOR`, `WORD_DEPOSIT_TOKEN`, `WORD_DEPOSIT_VAULT_ID`, `WORD_DEPOSIT_VAULT_BEFORE`, `WORD_DEPOSIT_VAULT_AFTER`, `WORD_WITHDRAWER`, `WORD_WITHDRAW_TOKEN`, `WORD_WITHDRAW_VAULT_ID`, `WORD_WITHDRAW_VAULT_BEFORE`, `WORD_WITHDRAW_VAULT_AFTER`, `WORD_WITHDRAW_TARGET_AMOUNT` -- Deposit index constants (lines 82-87): `DEPOSIT_WORD_DEPOSITOR` through `DEPOSIT_WORDS_LENGTH` -- Withdraw index constants (lines 89-95): `WITHDRAW_WORD_WITHDRAWER` through `WITHDRAW_WORDS_LENGTH` - -### Functions (all `internal pure`) -| # | Function | Line | Purpose | -|---|----------|------|---------| -| 1 | `subParserSender` | 101 | Context: base column, sender row | -| 2 | `subParserCallingContract` | 106 | Context: base column, calling contract row | -| 3 | `subParserOrderHash` | 115 | Context: calling context column, order hash row | -| 4 | `subParserOrderOwner` | 124 | Context: calling context column, order owner row | -| 5 | `subParserOrderCounterparty` | 133 | Context: calling context column, order counterparty row | -| 6 | `subParserMaxOutput` | 143 | Context: calculations column, max output row | -| 7 | `subParserIORatio` | 152 | Context: calculations column, IO ratio row | -| 8 | `subParserInputToken` | 161 | Context: vault inputs column, token row | -| 9 | `subParserInputTokenDecimals` | 170 | Context: vault inputs column, token decimals row | -| 10 | `subParserInputVaultId` | 179 | Context: vault inputs column, vault ID row | -| 11 | `subParserInputBalanceBefore` | 188 | Context: vault inputs column, balance before row | -| 12 | `subParserInputBalanceDiff` | 197 | Context: vault inputs column, balance diff row | -| 13 | `subParserOutputToken` | 206 | Context: vault outputs column, token row | -| 14 | `subParserOutputTokenDecimals` | 215 | Context: vault outputs column, token decimals row | -| 15 | `subParserOutputVaultId` | 224 | Context: vault outputs column, vault ID row | -| 16 | `subParserOutputBalanceBefore` | 233 | Context: vault outputs column, balance before row | -| 17 | `subParserOutputBalanceDiff` | 242 | Context: vault outputs column, balance diff row | -| 18 | `subParserSigners` | 251 | Context: signers column, operand-as-row (dynamic) | -| 19 | `subParserDepositToken` | 260 | Context: calling context column, deposit token row | -| 20 | `subParserDepositVaultId` | 269 | Context: calling context column, deposit vault ID row | -| 21 | `subParserDepositVaultBalanceBefore` | 279 | Context: calling context column, deposit vault before row | -| 22 | `subParserDepositVaultBalanceAfter` | 291 | Context: calling context column, deposit vault after row | -| 23 | `subParserWithdrawToken` | 303 | Context: calling context column, withdraw token row | -| 24 | `subParserWithdrawVaultId` | 312 | Context: calling context column, withdraw vault ID row | -| 25 | `subParserWithdrawVaultBalanceBefore` | 322 | Context: calling context column, withdraw vault before row | -| 26 | `subParserWithdrawVaultBalanceAfter` | 334 | Context: calling context column, withdraw vault after row | -| 27 | `subParserWithdrawTargetAmount` | 346 | Context: calling context column, withdraw target amount row | -| 28 | `subParserSignedContext` | 357 | Context: signed context start column + operand-low-byte, operand-high-byte-as-row | -| 29 | `authoringMetaV2` | 369 | Builds authoring metadata for all context words | - -### Types/Errors -No custom errors or types are defined in this library. All types (`AuthoringMetaV2`, `OperandV2`) are imported. - -## Existing Test Coverage - -### Unit-level context word tests (via `OrderBookV6SubParserContextTest` abstract base) -Each test file extends `OrderBookV6SubParserContextTest` and overrides `word()`. The base provides three tests per word: -1. `testSubParserContextHappy` -- parses word, evaluates against fixture context, checks stack matches `keccak256(word)`. -2. `testSubParserContextUnhappyDisallowedOperand` -- verifies operand `<1>` is rejected. -3. `testSubParserContextUnhappyDisallowedInputs` -- verifies input `(1)` causes `StackAllocationMismatch`. - -**Covered words (17 test files):** -- `order-clearer` (subParserSender) -- `orderbook` (subParserCallingContract) -- `order-hash` (subParserOrderHash) -- `order-owner` (subParserOrderOwner) -- `order-counterparty` (subParserOrderCounterparty) -- `calculated-max-output` (subParserMaxOutput) -- `calculated-io-ratio` (subParserIORatio) -- `input-token` (subParserInputToken) -- `input-token-decimals` (subParserInputTokenDecimals) -- `input-vault-id` (subParserInputVaultId) -- `input-vault-before` (subParserInputBalanceBefore) -- `input-vault-increase` (subParserInputBalanceDiff) -- `output-token` (subParserOutputToken) -- `output-token-decimals` (subParserOutputTokenDecimals) -- `output-vault-id` (subParserOutputVaultId) -- `output-vault-before` (subParserOutputBalanceBefore) -- `output-vault-decrease` (subParserOutputBalanceDiff) - -### Signer tests (`OrderBookV6SubParser.signers.t.sol`) -- Happy path for `signer<0>()` and `signer<1>()`. -- Unhappy: no operand, too many operands, disallowed input. - -### Signed context tests (`OrderBookV6SubParser.signedContext.t.sol`) -- Happy path for `signed-context<0 0>()`, `<0 1>`, `<1 0>`, `<1 1>`. -- Unhappy: no operand, too many operands, disallowed input. - -### Pointer / meta tests (`OrderBookV6SubParser.pointers.t.sol`) -- `testSubParserParseMeta` -- verifies `authoringMetaV2()` output matches generated parse meta. -- `testSubParserFunctionPointers` -- verifies word parser function pointers match. -- `testSubParserOperandParsers` -- verifies operand handler pointers match. -- `testWordOperandLengthEquivalence` -- checks length consistency. - -### Integration tests for deposit/withdraw context words -- `OrderBookV6.deposit.entask.t.sol` (`testOrderDepositContext`): Tests `depositor()`, `deposit-token()`, `deposit-vault-id()`, `deposit-vault-before()`, `deposit-vault-after()` via actual `deposit4()` call with fuzzed values. -- `OrderBookV6.withdraw.entask.t.sol` (`testOrderWithdrawContext`): Tests `withdrawer()`, `withdraw-token()`, `withdraw-vault-id()`, `withdraw-vault-before()`, `withdraw-vault-after()`, `withdraw-target-amount()` via actual `withdraw4()` call with fuzzed values. - -### Other -- `OrderBookV6SubParser.ierc165.t.sol` -- ERC165 interface support tests. -- `OrderBookV6SubParser.describedByMeta.t.sol` -- verifies described-by meta hash matches on-disk meta file. - -## Coverage Gap Analysis - -### GAP-1: No isolated unit tests for deposit/withdraw sub-parser functions -**Severity:** INFO -**Details:** The 11 deposit/withdraw-related sub-parser functions (`subParserDepositToken`, `subParserDepositVaultId`, `subParserDepositVaultBalanceBefore`, `subParserDepositVaultBalanceAfter`, `subParserWithdrawToken`, `subParserWithdrawVaultId`, `subParserWithdrawVaultBalanceBefore`, `subParserWithdrawVaultBalanceAfter`, `subParserWithdrawTargetAmount`) lack the same isolated `OrderBookV6SubParserContextTest`-style unit tests that the other 17 context words have. However, these functions ARE tested end-to-end through `OrderBookV6.deposit.entask.t.sol` and `OrderBookV6.withdraw.entask.t.sol`, which verify the words produce correct values in real deposit/withdraw flows with fuzzed inputs. - -The difference in test approach is structurally justified: the deposit/withdraw words are served to a different context (the entask/post-action context) which is populated differently from the order-clearing context. The abstract `OrderBookV6SubParserContextTest` base builds a fixture context from `LibOrderBookSubParserContextFixture.hashedNamesContext()` that only covers the order-clearing columns, not the deposit/withdraw columns. The integration tests provide stronger coverage because they verify correctness of both the sub-parser routing AND the actual context population by the orderbook. - -No fix required. The integration tests provide adequate coverage. - -### GAP-2: No test for `authoringMetaV2()` internal consistency of deposit/withdraw metadata -**Severity:** INFO -**Details:** The `testSubParserParseMeta` test in `OrderBookV6SubParser.pointers.t.sol` indirectly validates that `authoringMetaV2()` produces valid metadata (by verifying the parse meta built from it matches the pre-generated constant). This covers the deposit and withdraw metadata entries since they are part of the same `authoringMetaV2()` output. The test also serves as a regression check: if any word is added/removed without updating the generated pointers, this test fails. - -No fix required. - -### GAP-3: `subParserSignedContext` operand encoding boundary values not fuzz-tested -**Severity:** INFO -**Details:** `subParserSignedContext` (line 357-366) extracts column from the low byte (`& 0xFF`) and row from the next byte (`>> 8 & 0xFF`) of the operand. While the happy-path tests cover four concrete combinations (0,0), (0,1), (1,0), (1,1), there is no fuzz test exercising boundary values of the operand encoding (e.g., column=255, row=255, or operands where higher bits beyond byte 0 and byte 1 are set). - -However, the operand values are controlled by the parser's `handleOperandDoublePerByteNoDefault` handler, which restricts input to two single-byte values. Arbitrary operand values cannot reach `subParserSignedContext` through the normal parsing flow. The risk is near-zero in practice. - -No fix required. - -## Summary - -| Category | Count | -|----------|-------| -| Functions in library | 29 | -| Functions with direct unit tests | 19 (17 context words + signers + signed-context) | -| Functions with integration test coverage | 9 (deposit/withdraw words via entask tests) | -| Functions with indirect test coverage | 1 (`authoringMetaV2` via pointer test) | -| Untested functions | 0 | -| Coverage gaps requiring fixes | 0 | - -**Overall Assessment:** Test coverage for `LibOrderBookSubParser.sol` is comprehensive. All 29 functions have at least one form of test coverage. The 17 order-clearing context words have thorough isolated unit tests (happy + unhappy paths). The deposit/withdraw context words have fuzzed integration tests. The `authoringMetaV2` function is indirectly validated through the parse meta consistency test. No LOW+ findings. diff --git a/audit/2026-03-13-01/pass2/OrderBookV6.md b/audit/2026-03-13-01/pass2/OrderBookV6.md deleted file mode 100644 index ee4cbe321b..0000000000 --- a/audit/2026-03-13-01/pass2/OrderBookV6.md +++ /dev/null @@ -1,293 +0,0 @@ -# Pass 2: Test Coverage -- OrderBookV6.sol -**Agent:** A08 -**File:** src/concrete/ob/OrderBookV6.sol - -## Evidence of Thorough Reading - -### Contract -- **Name:** `OrderBookV6` (line 198) -- **Inherits:** `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender` -- **Pragma:** `solidity =0.8.25` (line 3) - -### State Variables -| Name | Type | Line | -|------|------|------| -| `sOrders` | `mapping(bytes32 => uint256)` | 215 | -| `sVaultBalances` | `mapping(address => mapping(address => mapping(bytes32 => Float)))` | 222 | - -### Constants -| Name | Value | Line | -|------|-------|------| -| `ORDER_LIVE` | `1` | 129 | -| `ORDER_DEAD` | `0` | 134 | -| `CALCULATE_ORDER_ENTRYPOINT` | `SourceIndexV2.wrap(0)` | 137 | -| `HANDLE_IO_ENTRYPOINT` | `SourceIndexV2.wrap(1)` | 140 | -| `CALCULATE_ORDER_MIN_OUTPUTS` | `2` | 143 | -| `CALCULATE_ORDER_MAX_OUTPUTS` | `2` | 145 | -| `HANDLE_IO_MIN_OUTPUTS` | `0` | 148 | -| `HANDLE_IO_MAX_OUTPUTS` | `0` | 150 | - -### Errors (all defined at file scope, lines 69-125) -| Error | Line | -|-------|------| -| `ReentrancyGuardReentrantCall()` | 69 | -| `NotOrderOwner(address)` | 73 | -| `TokenMismatch()` | 76 | -| `TokenSelfTrade()` | 79 | -| `TokenDecimalsMismatch()` | 83 | -| `MinimumIO(Float, Float)` | 88 | -| `SameOwner()` | 91 | -| `UnsupportedCalculateInputs(uint256)` | 95 | -| `UnsupportedCalculateOutputs(uint256)` | 99 | -| `NegativeInput()` | 102 | -| `NegativeOutput()` | 105 | -| `NegativeVaultBalance(Float)` | 109 | -| `NegativeVaultBalanceChange(Float)` | 113 | -| `NegativePull()` | 116 | -| `NegativePush()` | 119 | -| `NegativeBounty()` | 122 | -| `ClearZeroAmount()` | 125 | - -### Types -| Name | Line | -|------|------| -| `OrderIOCalculationV4` (struct) | 181 | -| `Output18Amount` (type alias) | 192 | -| `Input18Amount` (type alias) | 194 | - -### Public/External Functions -| Function | Visibility | Line | Modifier(s) | -|----------|------------|------|-------------| -| `vaultBalance2` | external view | 226 | -- | -| `orderExists` | external view | 249 | -- | -| `entask2` | external | 254 | nonReentrant | -| `deposit4` | external | 259 | nonReentrant, nonZeroVaultId | -| `withdraw4` | external | 294 | nonReentrant, nonZeroVaultId | -| `addOrder4` | external | 333 | nonReentrant | -| `removeOrder3` | external | 383 | nonReentrant | -| `quote2` | external view | 413 | -- | -| `takeOrders4` | external | 436 | nonReentrant | -| `clear3` | external | 596 | nonReentrant | - -### Internal Functions -| Function | Visibility | Line | -|----------|------------|------| -| `_vaultBalance` | internal view | 231 | -| `checkTokenSelfTrade` | internal pure | 406 | -| `calculateOrderIO` | internal view | 701 | -| `increaseVaultBalance` | internal | 823 | -| `decreaseVaultBalance` | internal | 854 | -| `recordVaultIO` | internal | 892 | -| `handleIO` | internal | 916 | -| `calculateClearStateChange` | internal pure | 971 | -| `calculateClearStateAlice` | internal pure | 984 | -| `pullTokens` | internal | 1003 | -| `pushTokens` | internal | 1025 | -| `_nonZeroVaultId` | internal pure | 1045 | - -### Modifier -| Modifier | Line | -|----------|------| -| `nonZeroVaultId` | 1051 | - -### Test Files Reviewed (30 files) -- `OrderBookV6.deposit.t.sol` -- 7 tests -- `OrderBookV6.deposit.entask.t.sol` -- 8 tests -- `OrderBookV6.withdraw.t.sol` -- 6 tests -- `OrderBookV6.withdraw.entask.t.sol` -- 9 tests -- `OrderBookV6.addOrder.t.sol` -- 9 tests -- `OrderBookV6.addOrder.mock.t.sol` -- 8 tests -- `OrderBookV6.addOrder.nonce.t.sol` -- 3 tests -- `OrderBookV6.addOrder.owner.t.sol` -- 2 tests -- `OrderBookV6.addOrder.entask.t.sol` -- 9 tests -- `OrderBookV6.removeOrder.mock.t.sol` -- 5 tests -- `OrderBookV6.removeOrder.owner.t.sol` -- 3 tests -- `OrderBookV6.removeOrder.entask.t.sol` -- 8 tests -- `OrderBookV6.takeOrder.badStack.t.sol` -- 2 tests -- `OrderBookV6.takeOrder.handleIO.revert.t.sol` -- 14 tests -- `OrderBookV6.takeOrder.maximumInput.t.sol` -- 6 tests -- `OrderBookV6.takeOrder.maximumOutput.t.sol` -- 11 tests -- `OrderBookV6.takeOrder.noop.t.sol` -- 3 tests -- `OrderBookV6.takeOrder.precision.t.sol` -- 12 tests -- `OrderBookV6.takeOrder.sameToken.t.sol` -- 1 test -- `OrderBookV6.takeOrder.tokenMismatch.t.sol` -- 2 tests -- `OrderBookV6.clear.badStack.t.sol` -- 6 tests -- `OrderBookV6.clear.context.t.sol` -- 2 tests -- `OrderBookV6.clear.handleIO.revert.t.sol` -- 10 tests -- `OrderBookV6.clear.mock.t.sol` -- ~20 tests -- `OrderBookV6.clear.sameToken.t.sol` -- 1 test -- `OrderBookV6.clear.zeroAmount.t.sol` -- 1 test -- `OrderBookV6.quote.t.sol` -- 4 tests -- `OrderBookV6.quote.sameToken.t.sol` -- 1 test -- `OrderBookV6.vaultBalance.t.sol` -- 1 test -- `OrderBookV6.entask.t.sol` -- 5 tests - ---- - -## Findings - -### A08-1 [INFO] No direct test for `SameOwner` error in `clear3` - -**Description:** The `clear3` function reverts with `SameOwner()` at line 605 when `aliceOrder.owner == bobOrder.owner`. No test file directly exercises this error path. The `clear.mock.t.sol` imports `SameOwner` but every test uses `vm.assume(alice != bob)` to avoid it. A test confirming the revert would strengthen coverage. - -**Impact:** Informational. The check is simple and correct by inspection; this is purely a test gap. - -**Test files searched:** All `OrderBookV6.clear.*.t.sol` - ---- - -### A08-2 [INFO] No direct test for `TokenMismatch` error in `clear3` - -**Description:** The `clear3` function at lines 607-614 checks that Alice's output token equals Bob's input token and vice-versa, reverting with `TokenMismatch()`. No clear test file exercises this path. The `TokenMismatch` error is tested only in `takeOrder.tokenMismatch.t.sol` for `takeOrders4`. The `clear3` code path is separate and could have a regression independently. - -**Impact:** Informational. The logic is straightforward, but a regression test would be useful since `clear3` has its own token matching code. - -**Test files searched:** All `OrderBookV6.clear.*.t.sol` - ---- - -### A08-3 [INFO] No test for `MinimumIO` revert path in `takeOrders4` - -**Description:** The `takeOrders4` function at lines 562-566 checks that the actual relevant IO meets the caller-specified `minimumIO`, reverting with `MinimumIO(minimumIO, actualRelevantTakerIO)`. No test exercises this error. Every test sets `minimumIO` to 0, meaning this revert path is never triggered. - -**Impact:** Informational. The `minimumIO` check is the taker's primary protection against slippage. Without testing, a regression (e.g., comparing wrong values or wrong direction) could go undetected. - -**Test files searched:** All `OrderBookV6.takeOrder.*.t.sol` and grep across all test files for `MinimumIO`. - ---- - -### A08-4 [INFO] No test for `OrderExceedsMaxRatio` event emission in `takeOrders4` - -**Description:** At line 503-504, when an order's IO ratio exceeds `config.maximumIORatio`, the order is skipped and the event `OrderExceedsMaxRatio` is emitted. No test exercises this path. All tests set `maximumIORatio` to `type(int224).max`, so this branch is never taken. - -**Impact:** Informational. This is the taker's protection against overpaying for an order. An untested path could silently break. - -**Test files searched:** All `OrderBookV6.takeOrder.*.t.sol` -- grep for `OrderExceedsMaxRatio` returned no matches. - ---- - -### A08-5 [INFO] No test for `OrderZeroAmount` event emission in `takeOrders4` - -**Description:** At lines 505-506, when `orderIOCalculation.outputMax.isZero()`, the order is skipped and `OrderZeroAmount` is emitted. No test directly triggers this event in the `takeOrders4` context. While `clear.zeroAmount.t.sol` tests zero output in `clear3`, the `takeOrders4` path is separate. - -**Impact:** Informational. This path represents skipping zero-output orders; a test would confirm that correctly-evaluated zero-output orders are indeed skipped without reverting. - ---- - -### A08-6 [INFO] No test for `onTakeOrders2` callback path in `takeOrders4` - -**Description:** At lines 581-584, `takeOrders4` calls `IRaindexV6OrderTaker(msg.sender).onTakeOrders2(...)` when `config.data.length > 0`. All tests pass an empty `data` field, so this callback is never tested in the `OrderBookV6.takeOrder.*.t.sol` files. (There are separate arb-related test files that exercise similar callbacks but from the arb contract's perspective, not from `OrderBookV6.takeOrders4` directly.) - -**Impact:** Informational. The callback is the mechanism for flash-swap-style integrations. Untested paths could mask bugs in parameter ordering or token direction. - ---- - -### A08-7 [INFO] Unused error: `TokenDecimalsMismatch` - -**Description:** The error `TokenDecimalsMismatch()` is declared at line 83 but is never used in `OrderBookV6.sol`. It is not thrown anywhere in the contract. This is dead code. - -**Impact:** Informational. Dead error declarations create confusion about contract behavior. - ---- - -### A08-8 [INFO] Unused errors: `NegativeInput`, `NegativeOutput` - -**Description:** The errors `NegativeInput()` (line 102) and `NegativeOutput()` (line 105) are declared but never thrown in `OrderBookV6.sol`. The functions `increaseVaultBalance` and `decreaseVaultBalance` use `NegativeVaultBalanceChange` instead. These appear to be vestigial from an earlier design. - -**Impact:** Informational. Dead error declarations; no test coverage needed but they should be cleaned up. - ---- - -### A08-9 [INFO] Unused error: `UnsupportedCalculateInputs` - -**Description:** The error `UnsupportedCalculateInputs(uint256)` is declared at line 95 but is never thrown in `OrderBookV6.sol`. In `calculateOrderIO` (line 788), only `UnsupportedCalculateOutputs` is checked. The `addOrder.t.sol` imports `UnsupportedCalculateInputs` but no test actually triggers it because the contract never throws it. - -**Impact:** Informational. Dead code that creates false expectations about runtime behavior. - ---- - -### A08-10 [INFO] No test for `NegativeVaultBalanceChange` revert in `increaseVaultBalance`/`decreaseVaultBalance` - -**Description:** Both `increaseVaultBalance` (line 827) and `decreaseVaultBalance` (line 858) check for negative amounts and revert with `NegativeVaultBalanceChange`. No test exercises these paths. While negative Float values reaching these functions would be an unusual condition, the guard is important for correctness. - -**Impact:** Informational. These are safety guards on internal functions. Testing would confirm they work as expected if an expression evaluates to a negative output or ratio. - ---- - -### A08-11 [INFO] No test for `NegativePull`/`NegativePush` revert paths - -**Description:** `pullTokens` (line 1008) reverts with `NegativePull()` and `pushTokens` (line 1031) reverts with `NegativePush()` when the Float amount is negative. No test triggers these paths. - -**Impact:** Informational. These are safety guards. In normal operation, negative amounts should not reach these functions, but a crafted expression could potentially return negative values. Testing confirms the guard works. - ---- - -### A08-12 [INFO] No test for `NegativeVaultBalance` revert in `increaseVaultBalance` - -**Description:** At line 845, `increaseVaultBalance` checks that `newBalance` is not negative after adding a positive amount. The comment states "This should never be possible" but the check is there for safety. No test exercises this path. - -**Impact:** Informational. While this condition is theoretically unreachable (adding a positive amount to any Float should not produce a negative result), the guard exists and should ideally have a test demonstrating it cannot be reached or demonstrating the revert if it could. - ---- - -### A08-13 [INFO] No test for `NegativeVaultBalance` revert in `decreaseVaultBalance` - -**Description:** At line 877, `decreaseVaultBalance` checks that `newBalance` is not negative after subtracting. No test exercises this path for the case where a withdrawal exceeds the vault balance through an internal path (not via `withdraw4`, which caps the amount). This could be triggered through `recordVaultIO` if an order expression returns values that cause the output to exceed the vault balance. - -**Impact:** Informational. This is a critical safety check -- it prevents a vault from going negative. The `withdraw4` function caps withdrawal at the balance, but `clear3` and `takeOrders4` paths through `recordVaultIO` do not explicitly cap at the vault balance before calling `decreaseVaultBalance`. The cap is instead via `orderOutputMax` being min'd with `ownerVaultBalance` in `calculateOrderIO` (line 804). A test confirming the revert behavior would be valuable. - ---- - -### A08-14 [INFO] No test for `NegativeBounty` revert in `clear3` - -**Description:** At line 658, `clear3` checks if either the Alice or Bob bounty is negative and reverts with `NegativeBounty()`. While `clear.mock.t.sol` imports `NegativeBounty` and tests it in `testClearFuzzIoRatioError` (line 839 of the mock test), this test uses a mock interpreter. No real-interpreter test exercises this path. - -**Impact:** Informational. The mock test provides adequate coverage for the revert logic. A real-interpreter test would add confidence. - ---- - -### A08-15 [INFO] No test for dead order early-return paths in `clear3` - -**Description:** At lines 626-633, `clear3` returns early (emitting `OrderNotFound`) if either Alice's or Bob's order is dead. No test exercises these specific paths. `takeOrders4` dead-order handling IS tested in `takeOrder.noop.t.sol`, but the `clear3` early-return paths are separate. - -**Impact:** Informational. The early-return design (instead of reverting) is intentional for Multicall compatibility. Testing would confirm the `OrderNotFound` event is correctly emitted and no state changes occur. - ---- - -### A08-16 [INFO] Unused type aliases `Output18Amount` and `Input18Amount` - -**Description:** The type aliases `Output18Amount` (line 192) and `Input18Amount` (line 194) are declared but never used anywhere in the contract. - -**Impact:** Informational. Dead code that should be cleaned up. - ---- - -## Summary - -The test suite is extensive and covers the major functional paths well: - -**Well-tested areas:** -- Deposit (happy path, zero deposit, zero vault ID, reentrancy, many deposits, events, entask context) -- Withdraw (happy path, zero target, empty vault, full/partial, failure, many withdrawals, entask context) -- Add order (no inputs/outputs reverts, valid order emission, meta validation, nonce behavior, owner isolation, entask, idempotency) -- Remove order (owner check, add/remove cycles, dead order noop, different owners, entask, revert-in-action) -- Take orders (zero orders, dead orders, token mismatch, same-token, bad stack, handle IO revert, maximum input/output, precision, vault ID 0) -- Clear (bad stack, context, handle IO revert, same token, zero amount, vault ID 0 combinations, mock matching with various ratios) -- Quote (dead order, simple, vault-capped output, context access, same-token) -- Vault balance (empty read) -- Entask (stateless, stateful, namespaced) -- Flash lending (separate test directory) - -**Coverage gaps (all INFO severity):** -- `SameOwner` error in `clear3` -- no test -- `TokenMismatch` error in `clear3` -- no test (only tested for `takeOrders4`) -- `MinimumIO` revert in `takeOrders4` -- no test (all tests use minimumIO=0) -- `OrderExceedsMaxRatio` skip in `takeOrders4` -- no test -- `OrderZeroAmount` skip in `takeOrders4` -- no test -- `onTakeOrders2` callback path -- no test in OB test files -- `NegativeVaultBalanceChange`, `NegativePull`, `NegativePush` reverts -- no tests -- `NegativeVaultBalance` reverts in increase/decrease -- no tests -- Dead order early-return in `clear3` -- no test -- Several unused/dead error declarations and type aliases - -No MEDIUM or higher findings. The existing tests provide strong coverage of the core economic logic, and the gaps are limited to secondary error paths and guard rails. diff --git a/audit/2026-03-13-01/pass2/OrderBookV6ArbCommon.md b/audit/2026-03-13-01/pass2/OrderBookV6ArbCommon.md deleted file mode 100644 index dc37b9bc80..0000000000 --- a/audit/2026-03-13-01/pass2/OrderBookV6ArbCommon.md +++ /dev/null @@ -1,111 +0,0 @@ -# Pass 2: Test Coverage -- OrderBookV6ArbCommon.sol - -**Agent:** A01 -**File:** `src/abstract/OrderBookV6ArbCommon.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Struct (file scope) -- `OrderBookV6ArbConfig` (lines 21-25): fields `orderBook` (address), `task` (TaskV2), `implementationData` (bytes) - -### Error (file scope) -- `WrongTask()` (line 28) - -### Constant (file scope) -- `BEFORE_ARB_SOURCE_INDEX` (line 32): `SourceIndexV2.wrap(0)` - -### Contract: `OrderBookV6ArbCommon` (abstract, line 34) - -| Item | Kind | Line | -|------|------|------| -| `using LibEvaluable for EvaluableV4` | using directive | 35 | -| `event Construct(address sender, OrderBookV6ArbConfig config)` | event | 37 | -| `iTaskHash` | `bytes32 public immutable` | 39 | -| `constructor(OrderBookV6ArbConfig memory config)` | constructor | 41 | -| `modifier onlyValidTask(TaskV2 memory task)` | modifier | 50 | - -### Constructor Logic (lines 41-48) -1. Emits `Construct(msg.sender, config)` (line 43) -2. If `config.task.evaluable.bytecode.length != 0`, sets `iTaskHash = keccak256(abi.encode(config.task))` (lines 45-47) -3. Otherwise `iTaskHash` remains `bytes32(0)` (the initializer on line 39) - -### Modifier Logic (lines 50-55) -1. If `iTaskHash != bytes32(0)` AND `iTaskHash != keccak256(abi.encode(task))`, reverts with `WrongTask()` (lines 51-53) -2. Otherwise execution continues - -## Existing Test Files - -| Test File | What It Tests | -|-----------|---------------| -| `test/util/abstract/ArbTest.sol` | Base test harness: constructs arb with non-empty expression `""`, verifies `Construct` event emission | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | `WrongTask` revert on mismatched evaluable; successful eval with matching task | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` | Same as above for RouteProcessor variant | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` | Happy path with empty bytecode (no task hash) | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol` | Same for RouteProcessor | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol` | Happy path flash borrower with empty bytecode | -| `test/util/concrete/ChildOrderBookV6ArbOrderTaker.sol` | Deployable child with all-zero config | -| `test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol` | ERC165 interface checks | -| `test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol` | ERC165 interface checks | -| `test/abstract/OrderBookV6ArbOrderTaker.context.t.sol` | Context columns passed to task evaluable | - -## Coverage Analysis - -### What IS Tested - -1. **`WrongTask` revert path (modifier `onlyValidTask`)**: Tested in both `GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` and `RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol`. These fuzz the evaluable to ensure any mismatched task triggers revert. - -2. **Happy path with non-empty bytecode**: `testGenericPoolTakeOrdersExpression` and `testRouteProcessorTakeOrdersExpression` test that a matching task passes the modifier and the evaluable is called. - -3. **Happy path with empty bytecode (iTaskHash == 0)**: The `*.sender.t.sol` tests and `GenericPoolOrderBookV6FlashBorrower.sender.t.sol` all construct with empty expression (via default `ArbTest` which uses `expression()` returning `""`), then call arb with an empty-bytecode task -- the modifier passes because `iTaskHash` is `bytes32(0)`. - -4. **`Construct` event emission**: `ArbTest.sol` line 81-82 uses `vm.expectEmit()` to verify the event. - -### What is NOT Tested - -See findings below. - -## Findings - -### A01-P2-1 [LOW] No Test for `WrongTask` Revert Through FlashBorrower Path - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:50-55` (modifier), tested only via `OrderBookV6ArbOrderTaker.arb5` - -The `onlyValidTask` modifier is tested for `WrongTask` revert only through the `ArbOrderTaker.arb5` code path (in `GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` and `RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol`). - -There is no test that verifies `WrongTask` is correctly triggered through the `OrderBookV6FlashBorrower.arb4` code path. While the modifier is inherited identically by both abstract contracts, changes to either subclass could break the modifier application without test detection. - -The `GenericPoolOrderBookV6FlashBorrower.sender.t.sol` only tests the happy path (empty bytecode, `iTaskHash == 0`). - -### A01-P2-2 [LOW] No Direct Unit Test for Constructor `iTaskHash` Assignment - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:41-48` (constructor) - -There is no test that directly asserts the value of `iTaskHash` after construction. The existing tests verify behavior (the modifier reverts or passes), but never read `iTaskHash` (which is a public immutable, so it has a getter) to confirm: -- That `iTaskHash == bytes32(0)` when constructed with empty bytecode -- That `iTaskHash == keccak256(abi.encode(task))` when constructed with non-empty bytecode - -This is a defense-in-depth concern: if the constructor logic were accidentally changed (e.g., always setting the hash, or never setting it), the modifier tests might still pass depending on how the change manifests. A direct assertion on the stored value provides independent verification. - -### A01-P2-3 [LOW] No Test for `onlyValidTask` Bypass When `iTaskHash == 0` With Arbitrary Non-Empty Task - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:50-55` (modifier) - -When the contract is constructed with empty bytecode (`iTaskHash == 0`), the modifier should allow ANY task through -- including tasks with non-empty, arbitrary bytecode. The existing `*.sender.t.sol` tests only pass an empty-bytecode task when `iTaskHash == 0`. There is no fuzz test confirming that arbitrary non-empty tasks also pass when `iTaskHash == 0`. - -This matters because the modifier condition is `iTaskHash != bytes32(0) && ...` -- if someone refactored this to `||` or removed the first condition, it would not be caught by existing tests. - -### A01-P2-4 [INFO] No Dedicated Test File for `OrderBookV6ArbCommon` - -**Location:** N/A (test organization) - -`OrderBookV6ArbCommon` has no dedicated test file. All testing of its behavior is done indirectly through tests of its concrete subclasses. While this provides functional coverage, it means: -- There is no single place to look for the contract's test coverage -- Adding new functionality to `OrderBookV6ArbCommon` requires remembering to test through multiple subclass paths -- The contract's invariants are not documented in test form - -### A01-P2-5 [INFO] `BEFORE_ARB_SOURCE_INDEX` Constant Not Tested - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:32` - -The constant `BEFORE_ARB_SOURCE_INDEX = SourceIndexV2.wrap(0)` is defined at file scope but is not directly tested for its value. The constant is consumed by `OrderBookV6ArbOrderTaker` and `OrderBookV6FlashBorrower` in the `_beforeArb` logic (via `LibOrderBookArb`). While `OrderBookV6ArbOrderTaker.context.t.sol` exercises the before-arb path, there is no assertion that specifically validates the source index value. diff --git a/audit/2026-03-13-01/pass2/OrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass2/OrderBookV6ArbOrderTaker.md deleted file mode 100644 index b6ccfc61b6..0000000000 --- a/audit/2026-03-13-01/pass2/OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,67 +0,0 @@ -# Pass 2: Test Coverage — OrderBookV6ArbOrderTaker.sol - -**Agent:** A02 -**File:** src/abstract/OrderBookV6ArbOrderTaker.sol - -## Evidence of Thorough Reading - -| Element | Kind | Line | -|---|---|---| -| `NonZeroBeforeArbInputs(uint256)` | error | 25 | -| `BEFORE_ARB_SOURCE_INDEX` | constant (`SourceIndexV2`) | 29 | -| `OrderBookV6ArbOrderTaker` | abstract contract | 31 | -| `constructor(OrderBookV6ArbConfig)` | constructor | 40 | -| `supportsInterface(bytes4)` | function (public view override) | 43 | -| `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` | function (external payable nonReentrant onlyValidTask) | 49 | -| `onTakeOrders2(address, address, Float, Float, bytes)` | function (public virtual override, no-op) | 78 | - -Inheritance chain: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon`. - -## Existing Test Inventory - -| Test File | What it covers | -|---|---| -| `test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol` | `supportsInterface` for IERC165, IRaindexV6ArbOrderTaker, IRaindexV6OrderTaker, and rejects unknown IDs (fuzz) | -| `test/abstract/OrderBookV6ArbOrderTaker.context.t.sol` | Happy-path `arb5` via `ChildOrderBookV6ArbOrderTaker`, validates context columns (input token balance, output token balance, gas balance) passed into the post-task | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` | `arb5` on concrete GenericPool child (fuzz, happy path) | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | `arb5` with expression eval (fuzz), and `WrongTask` revert on mismatched evaluable | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol` | `arb5` on concrete RouteProcessor child (fuzz, happy path) | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` | `arb5` with expression eval (fuzz), and `WrongTask` revert on mismatched evaluable | - -## Findings - -### A02-P2-1 [LOW] No test for `arb5` reverting on zero orders - -**Location:** Line 56-58 - -`arb5` explicitly checks `takeOrders.orders.length == 0` and reverts with `IRaindexV6.NoOrders()`. There is no test anywhere in the `test/` tree that validates this revert path on the arb order taker contracts. The only `NoOrders` test (`test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol`) targets the order book itself, not the arb taker's own guard. - -### A02-P2-2 [LOW] No test for reentrancy guard on `arb5` - -**Location:** Line 52 - -`arb5` uses the `nonReentrant` modifier. There is no test verifying that a reentrant call (e.g., via a malicious `orderBook` or token callback during `takeOrders4`) is rejected. This is an important security property that should be explicitly validated. - -### A02-P2-3 [LOW] `onTakeOrders2` has no direct test - -**Location:** Line 78 - -The base `onTakeOrders2` is a public no-op. There is no test that calls it directly to confirm it succeeds and does nothing, and no test that confirms it can be called by arbitrary addresses (documenting the lack of access control identified in pass 1, finding A02-1). The concrete overrides in `GenericPool` and `RouteProcessor` are exercised indirectly through mock `orderBook.takeOrders4` calls, but the base abstract implementation is never directly tested. - -### A02-P2-4 [INFO] Approval grant/revoke cycle around `takeOrders4` is untested in isolation - -**Location:** Lines 63, 66 - -`arb5` calls `forceApprove(address(orderBook), type(uint256).max)` before `takeOrders4` and `forceApprove(address(orderBook), 0)` after. There is no test that asserts the approval is set to `type(uint256).max` before the external call and reset to 0 after it. The context test mocks `approve`, but does not assert the approval values or ordering. - -### A02-P2-5 [INFO] Unused error `NonZeroBeforeArbInputs` has no test (expected) - -**Location:** Line 25 - -`NonZeroBeforeArbInputs` is declared but never used in any code path. Consequently there are no tests for it. This is consistent with pass 1 finding A02-2. No test is needed unless the error is actually wired into a revert condition. - -### A02-P2-6 [INFO] No test for `arb5` with `msg.value > 0` - -**Location:** Line 51 - -`arb5` is `payable`, meaning callers can send ETH. The context test sets ETH balance via `vm.deal` but does not send ETH through `arb5{value: ...}()`. There is no test validating behavior when ETH is sent along with the call (it should be swept to the caller by `finalizeArb`). diff --git a/audit/2026-03-13-01/pass2/OrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass2/OrderBookV6FlashBorrower.md deleted file mode 100644 index 9e23bc919d..0000000000 --- a/audit/2026-03-13-01/pass2/OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,117 +0,0 @@ -# Pass 2: Test Coverage -- OrderBookV6FlashBorrower.sol -**Agent:** A03 -**File:** src/abstract/OrderBookV6FlashBorrower.sol - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashBorrower` (abstract, line 62) -**Inheritance:** IERC3156FlashBorrower, ReentrancyGuard, ERC165, OrderBookV6ArbCommon - -### Types / Errors / Constants -| Item | Kind | Line | -|------|------|------| -| `BadInitiator(address)` | error | 24 | -| `FlashLoanFailed()` | error | 27 | -| `SwapFailed()` | error | 30 | - -### Functions -| Function | Visibility | Line | -|----------|-----------|------| -| `constructor(OrderBookV6ArbConfig)` | internal (constructor) | 66 | -| `supportsInterface(bytes4)` | public view virtual | 69 | -| `_exchange(TakeOrdersConfigV5, bytes)` | internal virtual | 82 | -| `onFlashLoan(address, address, uint256, uint256, bytes)` | external | 85 | -| `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` | external payable | 130 | - -### Key Imports Used -- `ON_FLASH_LOAN_CALLBACK_SUCCESS` (line 11) -- `LibTOFUTokenDecimals` (line 19) -- `LibDecimalFloat` (line 20) -- `LibOrderBookArb.finalizeArb` (line 18) - -## Test Inventory - -### Existing Test Files -1. **`test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol`** -- Tests only `supportsInterface`. Fuzz tests that IERC165 and IERC3156FlashBorrower interface IDs return true, and random IDs return false. -2. **`test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol`** -- Single fuzz test calling `arb4` through the concrete `GenericPoolOrderBookV6FlashBorrower`. Uses `FlashLendingMockOrderBook` which skips real token transfers and returns true from `flashLoan`. - -### Mocks -- **`FlashLendingMockOrderBook`** (`test/util/concrete/FlashLendingMockOrderBook.sol`): Passes `msg.sender` (not `address(this)`) as the `initiator` argument to `onFlashLoan` (line 26). The mock's `flashLoan` does NOT transfer any ERC20 tokens, does NOT call `safeTransferFrom` to reclaim repayment, and always returns `true`. The mock's `takeOrders4` is a no-op returning default (zero) values. -- **`Refundoor`** (`test/util/concrete/Refundoor.sol`): Reflexively sends ETH back to caller. - -## Findings - -### A03-P2-1 [MEDIUM] `onFlashLoan` has zero direct test coverage for error paths - -**Description:** The `onFlashLoan` function has two meaningful behaviors beyond the happy path: -1. Revert with `BadInitiator` when `initiator != address(this)` (line 87-89). -2. Decode calldata and call `_exchange`, then call `takeOrders4` on `msg.sender` (lines 91-103). - -Neither error path for `BadInitiator` is tested anywhere in the test suite. A `grep` for `BadInitiator` across all test files returns zero results. There is no test where `onFlashLoan` is called with a wrong initiator to verify the revert. - -Additionally, the mock `FlashLendingMockOrderBook.flashLoan` passes `msg.sender` as initiator (line 26 of the mock), NOT `address(receiver)`. In the test context, `msg.sender` is the arb contract itself (because arb4 calls `orderBook.flashLoan(this, ...)`), so the initiator check happens to pass. But this is fragile: the mock does not faithfully represent a real ERC3156 flash lender, which would pass the borrower's own address as the initiator. - -**Impact:** Bugs in the initiator check or its interaction with real flash lenders would go undetected. - -### A03-P2-2 [MEDIUM] `FlashLoanFailed` error path is never tested - -**Description:** The `arb4` function checks the return value of `orderBook.flashLoan(...)` and reverts with `FlashLoanFailed()` if it returns `false` (line 159-161). The mock `FlashLendingMockOrderBook` always returns `true` (line 27 of mock). There are zero tests verifying the `FlashLoanFailed` revert path. - -**Impact:** If the revert condition were accidentally removed or the logic inverted, no test would catch it. - -### A03-P2-3 [HIGH] Mock skips token transfers, hiding the missing repayment approval bug (A03-2) - -**Description:** Pass 1 finding A03-2 identified that `arb4` approves only `ordersInputToken` to the orderbook (line 158) but never approves `ordersOutputToken`. In a real flash lender, after `onFlashLoan` returns, the lender calls `IERC20(token).safeTransferFrom(borrower, lender, repayAmount)` to reclaim the loan. This requires the borrower to have approved the lender for `ordersOutputToken`. - -The mock `FlashLendingMockOrderBook.flashLoan`: -- Does NOT transfer any tokens to the borrower. -- Does NOT call `safeTransferFrom` to reclaim repayment. -- Does NOT check any approvals. - -Because the mock completely bypasses ERC20 interactions, the test suite cannot detect: -1. The missing `ordersOutputToken` approval (A03-2). -2. Any failure in the token flow (borrow -> exchange -> takeOrders -> repay). -3. Whether `forceApprove` calls are on the correct tokens. -4. Whether `forceApprove(..., 0)` cleanup happens for all approved tokens. - -The existing test `testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender` passes entirely because no real tokens move. - -**Impact:** The contract's core economic flow (flash loan -> exchange -> take orders -> repay loan -> profit) has zero end-to-end coverage. The A03-2 bug (missing repayment approval) would cause every real arb transaction to revert, but no test detects this. - -### A03-P2-4 [LOW] `SwapFailed` error is declared but never used and never tested - -**Description:** The error `SwapFailed()` is declared at line 30 but never referenced in `OrderBookV6FlashBorrower.sol` or its concrete implementations (`GenericPoolOrderBookV6FlashBorrower.sol`). It is dead code. No test references it either. - -**Impact:** Dead code that may mislead auditors into thinking there is a swap failure check. Low severity since it has no runtime effect. - -### A03-P2-5 [LOW] `NoOrders` revert path (line 137-139) has no test through the flash borrower - -**Description:** `arb4` explicitly checks `takeOrders.orders.length == 0` and reverts with `IRaindexV6.NoOrders()`. This path is tested for the orderbook's `takeOrders` directly (`test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol`) but never through any arb contract's `arb4`. While the behavior is simple, testing it through `arb4` would confirm the early-return optimization works correctly in the arb context. - -**Impact:** Low -- the logic is trivial, but the gap means the early revert (which saves gas by avoiding flash loan setup) is not validated in the arb path. - -### A03-P2-6 [MEDIUM] `WrongTask` revert path has no test for flash borrower arb contracts - -**Description:** The `onlyValidTask` modifier from `OrderBookV6ArbCommon` (line 50-55) is applied to `arb4`. When a non-empty task bytecode is configured at construction and a mismatched task is passed to `arb4`, it should revert with `WrongTask`. This is tested for `GenericPoolOrderBookV6ArbOrderTaker` (the order-taker variant) but NOT for `GenericPoolOrderBookV6FlashBorrower` or any flash-borrower path. The flash borrower's `ArbTest` base always constructs with empty bytecode (`expression()` returns `""`), so `iTaskHash` is always `bytes32(0)` and the modifier is never exercised. - -**Impact:** A bug in task validation specific to the flash borrower inheritance chain would go undetected. - -### A03-P2-7 [LOW] Flash loan amount calculation with wrong decimals (A03-3) not caught by tests - -**Description:** Pass 1 finding A03-3 identified that `flashLoanAmount` is computed using `inputDecimals` when it should use `outputDecimals` (line 153). The mock's `flashLoan` ignores the amount entirely (it does not transfer tokens), so the incorrect decimal conversion has no observable effect in tests. Even the `toFixedDecimalLossless` call could revert for certain float values that don't fit in the wrong decimal precision, but the fuzz test uses `minimumIO` of `packLossless(0, 0)` (zero), which converts losslessly regardless of decimals. - -**Impact:** The decimal bug is masked by both the mock's no-op behavior and the test's use of zero amounts. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A03-P2-1 | MEDIUM | `onFlashLoan` error paths have zero test coverage | -| A03-P2-2 | MEDIUM | `FlashLoanFailed` revert path never tested | -| A03-P2-3 | HIGH | Mock skips token transfers, hiding A03-2 missing repayment approval | -| A03-P2-4 | LOW | `SwapFailed` error declared but unused and untested | -| A03-P2-5 | LOW | `NoOrders` revert not tested through flash borrower arb path | -| A03-P2-6 | MEDIUM | `WrongTask` revert not tested for flash borrower contracts | -| A03-P2-7 | LOW | Wrong-decimal flash loan amount (A03-3) masked by mock and zero values | - -The fundamental issue is that `FlashLendingMockOrderBook` is a no-op mock that bypasses all ERC20 token mechanics. This means the entire economic flow of the flash borrower -- which is its core purpose -- has no meaningful test coverage. The mock would need to be replaced with a realistic flash lender that actually transfers tokens, checks approvals, and reclaims repayment to catch the bugs identified in Pass 1. diff --git a/audit/2026-03-13-01/pass2/OrderBookV6FlashLender.md b/audit/2026-03-13-01/pass2/OrderBookV6FlashLender.md deleted file mode 100644 index 12e0d63858..0000000000 --- a/audit/2026-03-13-01/pass2/OrderBookV6FlashLender.md +++ /dev/null @@ -1,74 +0,0 @@ -# Pass 2: Test Coverage — OrderBookV6FlashLender.sol - -**Agent:** A04 -**File:** src/abstract/OrderBookV6FlashLender.sol - -## Evidence of Thorough Reading - -- **Contract:** `OrderBookV6FlashLender` (abstract, line 29), inherits `IERC3156FlashLender` and `ERC165` -- **Imports:** `ERC165`, `IERC165` (line 5); `IERC20` (line 6); `SafeERC20` (line 7); `IERC3156FlashBorrower`, `ON_FLASH_LOAN_CALLBACK_SUCCESS` (lines 10-11); `IERC3156FlashLender` (line 13) -- **Error:** `FlashLenderCallbackFailed(bytes32 result)` (line 18) — thrown when `onFlashLoan` callback does not return the success magic value -- **Constant:** `FLASH_FEE = 0` (line 23) -- **Functions:** - - `supportsInterface(bytes4)` (line 33) — returns true for `IERC3156FlashLender` interfaceId or delegates to `super` - - `flashLoan(IERC3156FlashBorrower, address, uint256, bytes)` (line 38) — transfers tokens to receiver, calls `onFlashLoan`, checks return value, transfers tokens back with fee - - `flashFee(address, uint256)` (line 70) — returns `FLASH_FEE` (always 0) - - `maxFlashLoan(address)` (line 78) — returns `balanceOf(address(this))` for the given token - -## Existing Test Files (7) - -1. `test/abstract/OrderBookV6FlashLender.fee.t.sol` — fuzz tests `flashFee` returns 0 for any token/amount -2. `test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol` — tests callback failure: EOA receiver, wrong return value, non-bytes32 return -3. `test/abstract/OrderBookV6FlashLender.ierc165.t.sol` — tests ERC165 support for `IERC165` and `IERC3156FlashLender` -4. `test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol` — fuzz tests `maxFlashLoan` returns mocked `balanceOf` -5. `test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol` — tests successful flash loan with mocked transfers and correct callback -6. `test/abstract/OrderBookV6FlashLender.reentrant.t.sol` — tests reentrancy from within flash loan callback for deposit, withdraw, addOrder, removeOrder, takeOrders, clear, vaultBalance, orderExists -7. `test/abstract/OrderBookV6FlashLender.transfers.t.sol` — tests with real ERC20: successful round-trip (Bob), and partial return causing revert (Carol), plus callback failure path - -## Coverage Assessment - -### Well Covered - -- **`flashFee`**: Fuzz tested across arbitrary token addresses and amounts. Complete. -- **`maxFlashLoan`**: Fuzz tested with mocked `balanceOf`. Complete. -- **`supportsInterface`**: Positive tests for both `IERC165` and `IERC3156FlashLender`, negative test for arbitrary bad interfaceId. Complete. -- **`FlashLenderCallbackFailed` error path**: Tested via griefRecipient (wrong bytes32 return) and transfers (callback returning `bytes32(0)` when `iSuccess` is false). Adequate. -- **Successful flash loan path**: Tested with both mocked and real ERC20 tokens. Adequate. -- **Repayment failure**: Carol withholds tokens causing `ERC20InsufficientBalance` revert on `safeTransferFrom`. Adequate. -- **Reentrancy from callback**: Comprehensive coverage of reentry into deposit, withdraw, addOrder, removeOrder, takeOrders, clear, vaultBalance, orderExists. Excellent. - -### Coverage Gaps - -None of the gaps below represent exploitable vulnerabilities given the contract's simple design, but they represent missing coverage from a test-completeness perspective. - -## Findings - -### A04-3 [INFO] No test for flash loan when orderbook has insufficient token balance - -**Location:** Line 43 (`IERC20(token).safeTransfer(address(receiver), amount)`) - -All existing tests either mint tokens to the orderbook first (`transfers.t.sol`) or mock the `transfer` call to return true (`mockSuccess`, `griefRecipient`, `reentrant`). There is no test that exercises the path where the orderbook genuinely lacks sufficient token balance to fund the loan, causing `safeTransfer` to revert at line 43 before the callback is ever invoked. This is the natural guard ensuring loans cannot exceed available liquidity. While `maxFlashLoan` reports the available balance, nothing enforces that callers check it, so the `safeTransfer` revert is the actual enforcement mechanism. - -### A04-4 [INFO] No test verifying `msg.sender` (initiator) is correctly forwarded to `onFlashLoan` - -**Location:** Line 45 (`receiver.onFlashLoan(msg.sender, token, amount, FLASH_FEE, data)`) - -The ERC-3156 spec requires that the `initiator` parameter passed to `onFlashLoan` equals `msg.sender` of the `flashLoan` call. No test verifies this. The mock-based tests (`mockSuccess`, `griefRecipient`) use `vm.mockCall` to match any arguments to `onFlashLoan`, so they would pass even if a wrong initiator were forwarded. The `transfers.t.sol` tests use a real borrower (`Alice`) but her `onFlashLoan` ignores the initiator parameter entirely (first parameter is unnamed and unused). A test asserting the initiator is correct would guard against regressions if the function signature or call site changes. - -### A04-5 [INFO] No test for zero-amount flash loan - -**Location:** Line 38 - -No test explicitly exercises `amount = 0`. While fuzz tests *can* generate `amount = 0`, the transfers test bounds `amount >= 1` for the Carol failure case, and the mock-based tests don't assert specific transfer behavior for zero. A zero-amount flash loan is a valid edge case per ERC-3156 (the spec does not forbid it) and should be shown to succeed without side effects. - -### A04-6 [INFO] No test for `data` passthrough to `onFlashLoan` - -**Location:** Line 45 - -The `data` parameter is forwarded verbatim to `receiver.onFlashLoan`. No test verifies that the receiver actually receives the exact `data` bytes. The mock-based tests mock the entire `onFlashLoan` response regardless of arguments, and the real-token tests pass empty `data` (`""`). A test confirming that non-trivial `data` arrives intact at the borrower would guard the passthrough behavior. - -### A04-7 [INFO] Nested flash loan test coverage is missing - -**Location:** Line 38 (no reentrancy guard on `flashLoan`) - -Pass 1 finding A04-2 identified that `flashLoan` lacks a reentrancy guard, allowing nested flash loans. The reentrancy test suite (`reentrant.t.sol`) tests reentry into `deposit4`, `withdraw4`, `addOrder4`, `removeOrder3`, `takeOrders4`, `clear3`, `vaultBalance2`, and `orderExists` — but does not test reentry into `flashLoan` itself (nested flash loans). There is no test demonstrating that a borrower can take a second flash loan from within `onFlashLoan`. This would document the actual behavior and serve as a regression test. diff --git a/audit/2026-03-13-01/pass2/OrderBookV6SubParser.md b/audit/2026-03-13-01/pass2/OrderBookV6SubParser.md deleted file mode 100644 index 23f6821b02..0000000000 --- a/audit/2026-03-13-01/pass2/OrderBookV6SubParser.md +++ /dev/null @@ -1,124 +0,0 @@ -# Pass 2: Test Coverage -- OrderBookV6SubParser.sol -**Agent:** A09 -**Date:** 2026-03-13 -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` (lines 1-307) - -## 1. Evidence of Thorough Reading - -### Contract -- `OrderBookV6SubParser` (line 71), inherits `BaseRainterpreterSubParser` - -### Functions (with line numbers) -| # | Function | Line | Visibility | -|---|----------|------|------------| -| 1 | `describedByMetaV1()` | 75 | external pure | -| 2 | `subParserParseMeta()` | 80 | internal pure virtual override | -| 3 | `subParserWordParsers()` | 85 | internal pure virtual override | -| 4 | `subParserOperandHandlers()` | 90 | internal pure virtual override | -| 5 | `buildLiteralParserFunctionPointers()` | 95 | external pure | -| 6 | `buildOperandHandlerFunctionPointers()` | 100 | external pure | -| 7 | `buildSubParserWordParsers()` | 186 | external pure | - -### Types / Errors / Constants (imported, not locally defined) -- `OperandV2` (from rain.interpreter) -- `BadDynamicLength` (imported but not directly used in this contract -- used in BaseRainterpreterSubParser) -- All `CONTEXT_*` constants from `LibOrderBook.sol` -- All `DEPOSIT_WORD_*` and `WITHDRAW_WORD_*` constants from `LibOrderBookSubParser.sol` -- `DESCRIBED_BY_META_HASH`, `SUB_PARSER_PARSE_META`, `SUB_PARSER_WORD_PARSERS`, `SUB_PARSER_OPERAND_HANDLERS` from generated pointers - -### Key Operand Handler Configuration -- **Context base** (2 words): sender, calling-contract -- `handleOperandDisallowed` -- **Calling context** (3 words): order-hash, order-owner, order-counterparty -- `handleOperandDisallowed` -- **Calculations** (2 words): max-output, io-ratio -- `handleOperandDisallowed` -- **Vault inputs** (5 words): token, decimals, vault-id, balance-before, balance-diff -- `handleOperandDisallowed` -- **Vault outputs** (5 words): same as inputs -- `handleOperandDisallowed` -- **Signers** (1 word): `handleOperandSingleFullNoDefault` -- **Signed context** (1 word): `handleOperandDoublePerByteNoDefault` -- **Deposit** (5 words): depositor, token, vault-id, vault-before, vault-after -- `handleOperandDisallowed` -- **Withdraw** (6 words): withdrawer, token, vault-id, vault-before, vault-after, target-amount -- `handleOperandDisallowed` - -## 2. Test Files Reviewed - -| Test File | What It Tests | -|-----------|---------------| -| `OrderBookV6SubParser.ierc165.t.sol` | ERC165 interface detection for IERC165, ISubParserV4, IDescribedByMetaV1, IParserToolingV1, ISubParserToolingV1 | -| `OrderBookV6SubParser.describedByMeta.t.sol` | `describedByMetaV1()` returns correct hash | -| `OrderBookV6SubParser.pointers.t.sol` | Parse meta matches authoring meta; word parsers match `buildSubParserWordParsers()`; operand handlers match `buildOperandHandlerFunctionPointers()`; length equivalence | -| `OrderBookV6SubParser.signedContext.t.sol` | 4 happy-path tests (0-0, 0-1, 1-0, 1-1), no-operand error, too-many-operands error, disallowed-input error | -| `OrderBookV6SubParser.signers.t.sol` | 2 happy-path tests (signer-0, signer-1), no-operand error, too-many-operands error, disallowed-input error | -| `OrderBookV6SubParser.contextCalculatedIORatio.t.sol` | happy path, disallowed operand, disallowed inputs (via abstract base) | -| `OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol` | same pattern | -| `OrderBookV6SubParser.contextInputToken.t.sol` | same pattern | -| `OrderBookV6SubParser.contextInputTokenDecimals.t.sol` | same pattern | -| `OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol` | same pattern | -| `OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol` | same pattern | -| `OrderBookV6SubParser.contextInputVaultId.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOrderBook.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOrderClearer.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOrderCounterparty.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOrderHash.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOrderOwner.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOutputToken.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOutputTokenDecimals.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol` | same pattern | -| `OrderBookV6SubParser.contextOutputVaultId.t.sol` | same pattern | - -### Abstract Base Test -`test/util/abstract/OrderBookV6SubParserContextTest.sol` provides three tests for each word: -1. `testSubParserContextHappy` -- parses the word, checks it reads the correct context value -2. `testSubParserContextUnhappyDisallowedOperand` -- ensures operand `<1>` is rejected -3. `testSubParserContextUnhappyDisallowedInputs` -- ensures input `(1)` is rejected - -### Fixture -`test/util/fixture/LibOrderBookSubParserContextFixture.sol` provides `hashedNamesContext()` which builds a context array of `CONTEXT_COLUMNS + 3 = 8` columns (indices 0-7). It populates the base, calling-context, calculations, vault-inputs, vault-outputs, signers, and two signed-context columns. It does NOT include deposit context (column 7 per sub-parser, but fixture uses 7 for signed-context-1) or withdraw context (column 8). - -## 3. Coverage Gaps - -### GAP-1: No tests for deposit word parsing (11 words, 0 tests) [LOW] -**Finding ID:** P2-A09-01 - -The sub-parser registers 5 deposit words (`depositor`, `deposit-token`, `deposit-vault-id`, `deposit-vault-before`, `deposit-vault-after`) and 6 withdraw words (`withdrawer`, `withdraw-token`, `withdraw-vault-id`, `withdraw-vault-before`, `withdraw-vault-after`, `withdraw-target-amount`) in both `buildSubParserWordParsers()` (lines 157-176 / 267-298) and `buildOperandHandlerFunctionPointers()` (lines 157-176 in operand section). - -No test files exist for any of these 11 words. There are: -- No happy-path tests verifying they parse and resolve to the correct context column/row -- No operand-disallowed tests -- No input-disallowed tests - -These words use `LibOrderBookSubParser.subParserSender`, `subParserDepositToken`, `subParserDepositVaultId`, `subParserDepositVaultBalanceBefore`, `subParserDepositVaultBalanceAfter`, `subParserWithdrawToken`, `subParserWithdrawVaultId`, `subParserWithdrawVaultBalanceBefore`, `subParserWithdrawVaultBalanceAfter`, `subParserWithdrawTargetAmount` -- all untested at the sub-parser level. - -**Risk:** If any deposit/withdraw word-to-context mapping is wrong (wrong column or row index), a rainlang expression referencing e.g. `deposit-token()` in a deposit entask would silently read the wrong context value. The pointer tests confirm the generated pointers match the builder output, but they do NOT verify that the builder output is semantically correct. - -**Severity:** LOW -- the mapping logic in `LibOrderBookSubParser` is straightforward (each function calls `LibSubParse.subParserContext` with constant column/row), and the pointer test verifies structural correctness. However, a semantic error (wrong constant used) would be invisible without word-level tests. - -### GAP-2: `buildLiteralParserFunctionPointers()` has no direct test [INFO] -**Finding ID:** P2-A09-02 - -`buildLiteralParserFunctionPointers()` (line 95) returns empty bytes `""`. No test verifies this. The risk is negligible since the function body is a single return statement, but completeness would benefit from a one-line assertion. - -### GAP-3: Test fixture does not cover deposit/withdraw context columns [INFO] -**Finding ID:** P2-A09-03 - -`LibOrderBookSubParserContextFixture.hashedNamesContext()` allocates `CONTEXT_COLUMNS + 3 = 8` entries. The sub-parser's `buildSubParserWordParsers()` and `buildOperandHandlerFunctionPointers()` allocate `CONTEXT_COLUMNS + 2 + 1 + 1 = 9` entries. The fixture is structurally smaller than the sub-parser's expected context grid. If deposit/withdraw tests were added, the fixture would need to be extended to 9+ columns. - -### GAP-4: No fuzz tests on signed-context operand encoding [INFO] -**Finding ID:** P2-A09-04 - -The `subParserSignedContext` function (LibOrderBookSubParser.sol line 357-366) extracts column and row from the operand via bitmasking (`operand & 0xFF` for column, `(operand >> 8) & 0xFF` for row). Tests only cover 4 specific (column, row) pairs: (0,0), (0,1), (1,0), (1,1). A fuzz test with arbitrary column/row values would verify the operand encoding is correct across the full range. - -### GAP-5: No fuzz tests on signer operand encoding [INFO] -**Finding ID:** P2-A09-05 - -Similar to GAP-4, `subParserSigners` (line 251-258) uses the full operand as a row index. Only two specific values (0, 1) are tested. - -## 4. Summary - -| Category | Count | -|----------|-------| -| Functions in contract | 7 | -| Words registered | 28 (17 context + 1 signer + 1 signed-context + 5 deposit + 6 withdraw = 30 word slots, but 28 unique words counting signer/signed-context parameterized) | -| Test files | 22 | -| Words with happy-path tests | 19 out of 30 word slots (17 disallowed-operand words + signer + signed-context) | -| Words with NO tests | 11 (all deposit + withdraw words) | -| Functions with no direct test | 1 (`buildLiteralParserFunctionPointers`) | -| Findings | 1 LOW, 4 INFO | diff --git a/audit/2026-03-13-01/pass2/RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass2/RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 64db580af9..0000000000 --- a/audit/2026-03-13-01/pass2/RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,91 +0,0 @@ -# Pass 2: Test Coverage — RouteProcessorOrderBookV6ArbOrderTaker.sol - -**Agent:** A07 -**File:** src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol - -## Evidence of Thorough Reading - -| Element | Kind | Line | -|---|---|---| -| `RouteProcessorOrderBookV6ArbOrderTaker` | concrete contract | 14 | -| `iRouteProcessor` | state variable (public immutable `IRouteProcessor`) | 18 | -| `constructor(OrderBookV6ArbConfig)` | constructor | 20 | -| `onTakeOrders2(address,address,Float,Float,bytes)` | function (public virtual override) | 26 | -| `fallback()` | fallback (external, non-payable) | 52 | - -Inheritance chain: `OrderBookV6ArbOrderTaker` -> `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon`. - -Imports: `IRouteProcessor`, `IERC20`, `SafeERC20`, `Address`, `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float`, `LibDecimalFloat`, `IERC20Metadata`. - -## Existing Test Inventory - -| Test File | What it covers | -|---|---| -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol` | Fuzz: `arb5` happy path via mock order book, validates sender can call arb5 with no expression (empty bytecode). | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` | Fuzz: `arb5` with expression eval (mocked interpreter), validates `WrongTask` revert on mismatched evaluable, validates interpreter is called and store set is invoked when KVs are non-empty. | -| `test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol` | Test harness: constructs `RouteProcessorOrderBookV6ArbOrderTaker` via `buildArb`, sets `implementationData` to `abi.encode(iRefundoor)` (a `Refundoor` contract stands in as the route processor). | - -## Coverage Analysis - -### What is tested - -1. **Constructor deployment** -- implicitly tested: every test constructs the contract via `ArbTest.constructor()`, which decodes `implementationData` and sets `iRouteProcessor`. The `Construct` event emission is also asserted. -2. **`arb5` happy path** -- tested via `testRouteProcessorTakeOrdersSender`: calls `arb5` with a fuzzed order, no expression, mock order book that returns immediately. -3. **Task validation (`WrongTask`)** -- tested via `testRouteProcessorTakeOrdersWrongExpression`: asserts revert when evaluable does not match the stored task hash. -4. **Expression evaluation** -- tested via `testRouteProcessorTakeOrdersExpression`: mocks interpreter and store, validates both are called. - -### What is NOT tested - -The `onTakeOrders2` override (lines 26-49) is the primary logic unique to this contract. It is **never directly exercised** by any test. The mock order book's `takeOrders4` is a no-op that returns immediately without calling back into the taker's `onTakeOrders2`. This means the following code paths have zero coverage: - -- `forceApprove(address(iRouteProcessor), type(uint256).max)` (line 34) -- `abi.decode(takeOrdersData, (bytes))` -- route decoding (line 35) -- `LibDecimalFloat.toFixedDecimalLossy` on `inputAmountSent` (line 36-37) -- The silently discarded `losslessInputAmount` flag (line 38) -- `LibDecimalFloat.toFixedDecimalLossy` on `totalOutputAmount` (line 39-40) -- The `outputTokenAmount++` increment when output conversion is lossy (lines 41-43) -- `iRouteProcessor.processRoute(...)` call (lines 44-46) -- `forceApprove(address(iRouteProcessor), 0)` -- approval reset (line 47) -- The silently discarded `amountOut` (line 48) - -Additionally, the `fallback()` function (line 52) is never tested directly. - -## Findings - -### A07-P2-1 [MEDIUM] `onTakeOrders2` override has zero test coverage - -**Location:** Lines 26-49 - -The entire `onTakeOrders2` function, which is the only meaningful logic unique to this contract, is never executed in any test. The mock `FlashLendingMockOrderBook.takeOrders4` returns immediately without invoking the `onTakeOrders2` callback on the taker. This means: - -- The `forceApprove` / `processRoute` / `forceApprove(0)` sequence is untested. -- The Float-to-fixed-decimal conversion for both input and output amounts is untested. -- The lossy output amount rounding-up logic (`outputTokenAmount++` when `!lossless`) is untested. -- The route decoding from `takeOrdersData` is untested. -- The approval grant/revoke cycle around `processRoute` is untested. - -This is the core differentiating logic of the contract vs. its parent. Any regression in Float conversion, route decoding, or approval handling would go undetected. - -### A07-P2-2 [LOW] No test for `onTakeOrders2` called directly by an external attacker - -**Location:** Line 26 - -Per pass 1 finding A07-1, `onTakeOrders2` is public with no access control. There is no test demonstrating that an arbitrary caller can invoke it to grant `type(uint256).max` approval to `iRouteProcessor` and execute a route. While the `iRouteProcessor` is immutable and trusted, a test documenting this attack surface (or proving the mitigation once A07-1 is fixed) is valuable for regression safety. - -### A07-P2-3 [LOW] No test for constructor with invalid `implementationData` - -**Location:** Line 21 - -The constructor does `abi.decode(config.implementationData, (address))`. There is no test verifying that construction reverts when `implementationData` is empty, too short, or otherwise malformed. If a deployer provides incorrect data, it could silently set `iRouteProcessor` to `address(0)`. - -### A07-P2-4 [INFO] No test that `iRouteProcessor` is correctly set - -**Location:** Line 18 - -While the constructor is implicitly exercised, no test reads `iRouteProcessor` after construction to verify it equals the expected address. This is a basic deployment sanity check. - -### A07-P2-5 [INFO] `fallback()` function is not tested - -**Location:** Line 52 - -The non-payable fallback is never exercised. There is no test confirming it accepts calls without data and no test confirming it rejects calls with ETH value (since it is not payable). diff --git a/audit/2026-03-13-01/pass3/Deploy.md b/audit/2026-03-13-01/pass3/Deploy.md deleted file mode 100644 index 2c846477b2..0000000000 --- a/audit/2026-03-13-01/pass3/Deploy.md +++ /dev/null @@ -1,125 +0,0 @@ -# Pass 3: Documentation — Deploy.sol - -**Agent:** A15 -**File:** `script/Deploy.sol` - -## Evidence of Thorough Reading - -**Contract name:** `Deploy` (inherits `Script` from forge-std), lines 46-176. - -**Functions:** -| Function | Line | Visibility | Has Doc Comment | -|---|---|---|---| -| `deployRouter()` | 52 | internal | NO | -| `run()` | 61 | external | NO | - -**File-level constants:** -| Name | Line | Type | Has Doc Comment | -|---|---|---|---| -| `DEPLOYMENT_SUITE_ALL` | 24 | `bytes32` | NO | -| `DEPLOYMENT_SUITE_RAINDEX` | 25 | `bytes32` | NO | -| `DEPLOYMENT_SUITE_SUBPARSER` | 26 | `bytes32` | NO | -| `DEPLOYMENT_SUITE_ROUTE_PROCESSOR` | 27 | `bytes32` | NO | -| `DEPLOYMENT_SUITE_ARB` | 28 | `bytes32` | NO | -| `ROUTE_PROCESSOR_4_CREATION_CODE` | 38 | `bytes` | YES (`@dev`, lines 30-37) | -| `ROUTE_PROCESSOR_4_BYTECODE_HASH` | 41 | `bytes32` | NO | - -**Errors (file-level):** -| Name | Line | Has Doc Comment | -|---|---|---| -| `BadRouteProcessor(bytes32 expected, bytes32 actual)` | 44 | NO | - -**State variables:** -| Name | Line | Type | Has Doc Comment | -|---|---|---|---| -| `sDepCodeHashes` | 50 | `mapping(string => mapping(address => bytes32))` | NO | - -**Imports:** 20 import statements (lines 5-22), covering forge-std, OrderBookV6, SubParser, arb contracts, metadata libraries, interpreter interfaces, deployment libraries, and generated pointer files. - -## Documentation Audit - -### Existing documentation - -1. **`ROUTE_PROCESSOR_4_CREATION_CODE`** (lines 30-37): Has a `@dev` comment explaining the source of the bytecode (SushiSwap GitHub, etherscan cross-reference) and the constructor args. This comment is accurate and helpful. - -2. **Contract-level `@title` and `@notice`** (lines 46-48): Present but contain inaccuracies (see findings below). - -### Missing documentation - -The following elements have no NatSpec or doc comments at all: -- All five `DEPLOYMENT_SUITE_*` constants (lines 24-28) -- `ROUTE_PROCESSOR_4_BYTECODE_HASH` (line 41) -- `BadRouteProcessor` error (line 44) -- `sDepCodeHashes` state variable (line 50) -- `deployRouter()` function (line 52) -- `run()` function (line 61) - -## Findings - -### A15-P3-1 [LOW] Contract `@notice` references deprecated "mumbai" testnet - -**Location:** Lines 47-48 - -The contract-level NatSpec says: - -``` -/// @notice A script that deploys all contracts. This is intended to be run on -/// every commit by CI to a testnet such as mumbai. -``` - -Polygon Mumbai testnet was deprecated in April 2024. This reference is stale and misleading. Additionally, the description "deploys all contracts" is imprecise since the script supports selective deployment via the `DEPLOYMENT_SUITE` env var and may deploy only a subset of contracts. - -### A15-P3-2 [LOW] `deployRouter()` has no documentation - -**Location:** Line 52 - -The `deployRouter()` function has no NatSpec at all. It uses inline assembly to deploy a contract from `ROUTE_PROCESSOR_4_CREATION_CODE` via `create`. A developer reading this function needs to understand: -- What contract it deploys (SushiSwap RouteProcessor4) -- That it uses `create` (not `create2`), so the address is nondeterministic -- What happens on failure (returns `address(0)` -- as noted in Pass 1 finding A15-2) -- What the return value represents - -### A15-P3-3 [LOW] `run()` function has no documentation describing env var interface - -**Location:** Line 61 - -The `run()` function is the main entry point for the deployment script. It reads three environment variables (`DEPLOYMENT_KEY`, `DEPLOYMENT_SUITE`, `DEPLOY_ROUTE_PROCESSOR_4_ADDRESS` and conditionally `DEPLOY_RAINDEX_ADDRESS`) but none of these are documented. There is no `@notice` or `@dev` explaining: -- The purpose and expected values for each env var -- The valid suite values (`all`, `raindex`, `subparser`, `route-processor`, `arb`) -- The deployment flow and what each suite deploys -- The dependency between suites (e.g., `arb` requires `raindex` address) - -This is the primary user-facing function of the script, and its lack of documentation forces operators to read the full implementation to understand how to use it. - -### A15-P3-4 [LOW] Five `DEPLOYMENT_SUITE_*` constants have no documentation - -**Location:** Lines 24-28 - -The five suite selector constants are undocumented. While the naming convention is somewhat self-explanatory, there is no doc comment explaining: -- What each suite deploys -- How they relate to each other (e.g., `all` is a superset) -- That the values are `keccak256` hashes of the corresponding string identifiers - -### A15-P3-5 [INFO] `ROUTE_PROCESSOR_4_BYTECODE_HASH` lacks provenance documentation - -**Location:** Line 41-42 - -The `ROUTE_PROCESSOR_4_CREATION_CODE` constant has thorough provenance documentation (lines 30-37) citing the SushiSwap GitHub and etherscan. The corresponding `ROUTE_PROCESSOR_4_BYTECODE_HASH` has no such documentation. It would be helpful to note that this is the `extcodehash` of the runtime bytecode produced by deploying `ROUTE_PROCESSOR_4_CREATION_CODE`, and ideally how it was derived or verified. - -### A15-P3-6 [INFO] `BadRouteProcessor` error has no NatSpec - -**Location:** Line 44 - -The error `BadRouteProcessor(bytes32 expected, bytes32 actual)` has no documentation. The parameter names are reasonably self-descriptive, but a brief `@dev` or inline comment explaining when this error is triggered would be helpful. - -### A15-P3-7 [INFO] `sDepCodeHashes` state variable has no documentation - -**Location:** Line 50 - -The `sDepCodeHashes` mapping has no doc comment. Its purpose (tracking dependency code hashes for `LibRainDeploy.deployAndBroadcast`) is not explained. - -### A15-P3-8 [INFO] README.md does not mention deployment - -**Location:** `/README.md` - -The top-level README describes the repository structure, local development setup, and legal information, but contains no section on deployment. There is no mention of `script/Deploy.sol`, the `DEPLOYMENT_SUITE` env var, or how to run the deploy script. While deployment instructions may be considered internal/CI-only knowledge, the README's "Setup for local development" section would be a natural place to at least reference the deploy script's existence and point to further documentation. diff --git a/audit/2026-03-13-01/pass3/GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass3/GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 6f02fb6a33..0000000000 --- a/audit/2026-03-13-01/pass3/GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,85 +0,0 @@ -# Pass 3: Documentation -- GenericPoolOrderBookV6ArbOrderTaker.sol - -**Agent:** A05 -**File:** `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Name -`GenericPoolOrderBookV6ArbOrderTaker` (line 11), inherits `OrderBookV6ArbOrderTaker`. - -### Functions (with line numbers) -| Function | Visibility | Line | -|---|---|---| -| `constructor(OrderBookV6ArbConfig memory config)` | public | 15 | -| `onTakeOrders2(address, address, Float, Float, bytes calldata)` | public virtual override | 18 | -| `fallback()` | external | 38 | - -### Types, Errors, Constants -None defined locally. All inherited from parent contracts. - -### Imports (lines 5-9) -- `IERC20` (line 5) -- `SafeERC20` (line 6) -- `Address` (line 7) -- `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float` (line 9) - ---- - -## Documentation Inventory - -### Contract-Level Documentation -**Missing.** No `@title` or `@notice` NatSpec on the contract declaration at line 11. The sibling `GenericPoolOrderBookV6FlashBorrower` has a `@title` and descriptive block. This contract lacks equivalent documentation explaining its purpose, how `takeOrdersData` is decoded, or the approve-call-revoke pattern. - -### Function Documentation - -#### `constructor` (line 15) -No NatSpec. Passthrough to parent. Acceptable for trivial constructors, but no doc on what `config` should contain for this implementation (unlike `RouteProcessorOrderBookV6ArbOrderTaker`, this contract has no `implementationData` needs, but that fact is not documented). - -#### `onTakeOrders2` (line 18) -Has `/// @inheritdoc OrderBookV6ArbOrderTaker` which chains to `/// @inheritdoc IRaindexV6OrderTaker` in the parent. The interface `IRaindexV6OrderTaker` provides full parameter docs (`@param inputToken`, `@param outputToken`, `@param inputAmountSent`, `@param totalOutputAmount`, `@param takeOrdersData`). - -**Issue:** The `@inheritdoc` chain documents the general callback semantics but does NOT describe this concrete implementation's specific behavior: that `takeOrdersData` is decoded as `(address spender, address pool, bytes encodedFunctionCall)`, that `spender` gets a max approval on `inputToken`, or that the entire ETH balance is forwarded to `pool`. A reader relying on generated docs will not understand how to call this contract. - -#### `fallback` (line 38) -Has `/// Allow receiving gas.` -- a plain comment, not NatSpec (no `@notice` or `@dev` tag). As identified in Pass 1 (A05-3), this comment is **misleading**: the fallback is not `payable`, so it cannot receive ETH/gas. The fallback's actual purpose appears to be accepting arbitrary calldata without reverting (e.g., for return-data callbacks from pools), not receiving ETH. - ---- - -## Findings - -### A05-P3-1 [LOW] Missing contract-level NatSpec documentation - -**Location:** Line 11 - -**Description:** -`GenericPoolOrderBookV6ArbOrderTaker` has no `@title`, `@notice`, or `@dev` NatSpec documentation. Compare with `GenericPoolOrderBookV6FlashBorrower` (lines 17-26 of that file) which has a thorough contract-level docblock explaining: -- What the contract does -- How `exchangeData` is decoded (spender, pool, callData) -- What the `spender` parameter is for -- Guidance on setting `spender` to the pool address if unsure - -This contract has identical decode semantics (`takeOrdersData` -> spender, pool, encodedFunctionCall) but none of this is documented anywhere in the file. Users and integrators must read the source to understand usage. - -**Recommendation:** Add a `@title` and `@notice` block mirroring the pattern from `GenericPoolOrderBookV6FlashBorrower`, adapted for the `ArbOrderTaker` context. - -### A05-P3-2 [INFO] Misleading fallback comment (confirmed from Pass 1) - -**Location:** Line 37-38 - -**Description:** -The comment `/// Allow receiving gas.` on the non-payable `fallback()` is inaccurate. This was identified as A05-3 in Pass 1. In the documentation pass context: the comment is not NatSpec (lacks `@notice`/`@dev`) and its content is factually wrong. A non-payable fallback reverts on `msg.value > 0`. The actual purpose of this fallback (accepting non-matching calldata silently) should be documented if it is intentional. If the fallback is vestigial, it should be removed. - -### A05-P3-3 [INFO] No implementation-specific parameter documentation on `onTakeOrders2` - -**Location:** Lines 17-25 - -**Description:** -While `@inheritdoc` correctly chains to the interface docs, the concrete implementation adds significant behavior undocumented by the interface: -- `takeOrdersData` is ABI-decoded as `(address spender, address pool, bytes encodedFunctionCall)` -- `spender` receives `type(uint256).max` approval on `inputToken` -- `pool` is called with `encodedFunctionCall` and the contract's full ETH balance -- Approval is reset to 0 after the call - -None of these implementation details are documented. A `@dev` comment describing the decode format and the approve-call-revoke flow would significantly improve usability. diff --git a/audit/2026-03-13-01/pass3/GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass3/GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index 8954f2bc2a..0000000000 --- a/audit/2026-03-13-01/pass3/GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,95 +0,0 @@ -# Pass 3: Documentation -- GenericPoolOrderBookV6FlashBorrower.sol - -**Agent:** A06 -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Name -`GenericPoolOrderBookV6FlashBorrower` (line 27), inherits `OrderBookV6FlashBorrower`. - -### Functions (with line numbers) -| Function | Visibility | Line | -|---|---|---| -| `constructor(OrderBookV6ArbConfig memory config)` | public | 31 | -| `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData)` | internal virtual override | 34 | -| `fallback()` | external | 48 | - -### Types, Errors, Constants -None defined locally. All inherited from parent contracts. - -### Imports (lines 5-15) -- `IERC3156FlashLender` (line 5) -- `IERC3156FlashBorrower` (line 6) -- `OrderBookV6FlashBorrower`, `SafeERC20`, `IERC20`, `Address`, `TakeOrdersConfigV5`, `OrderBookV6ArbConfig` (lines 8-15) - ---- - -## Documentation Inventory - -### Contract-Level Documentation -**Present and thorough.** Lines 17-26 provide: -- `@title GenericPoolOrderBookV6FlashBorrower` (line 17) -- Description of the contract's purpose (lines 18-19) -- Explanation of `exchangeData` decode format: spender, pool, callData (lines 20-21) -- Explanation that `callData` is the literal encoded function call to the pool (lines 21-22) -- Note that `spender` is the address approved to spend the input token (lines 24-25) -- Guidance that if unsure, set `spender` to the pool address (lines 25-26) - -This is well-written and sufficient for integrators. - -### Function Documentation - -#### `constructor` (line 31) -No NatSpec. Trivial passthrough to parent. Acceptable. - -#### `_exchange` (line 34) -Has `/// @inheritdoc OrderBookV6FlashBorrower` which points to the parent's documentation at `src/abstract/OrderBookV6FlashBorrower.sol` lines 73-80. The parent docs include: -- Description of the hook's purpose -- `@param takeOrders As per arb.` -- `@param exchangeData As per arb.` - -**Issue:** The parent's `@param` descriptions say "As per `arb`" which requires cross-referencing the `arb4` function docs. The `arb4` docs (lines 124-129 of parent) describe `exchangeData` with a reference to `GenericPoolOrderBookV5FlashBorrower` -- a **stale V5 name** that no longer exists (the contract is now V6). This stale reference lives in the parent, not in this file directly, but affects this contract's inherited documentation. - -#### `fallback` (line 48) -Has `/// Allow receiving gas.` -- a plain comment, not proper NatSpec. As identified in Pass 1 (A06-2), this is **misleading**: the fallback is not `payable` and cannot receive ETH. Same issue as in the two sibling contracts. - ---- - -## Findings - -### A06-P3-1 [LOW] Misleading fallback comment (confirmed from Pass 1) - -**Location:** Lines 47-48 - -**Description:** -The comment `/// Allow receiving gas.` on the non-payable `fallback()` is factually incorrect. A non-payable fallback in Solidity 0.8.25 will revert when called with `msg.value > 0`. This fallback cannot receive ETH/gas. - -This was previously identified as A06-2 in Pass 1. From a documentation perspective, the comment actively misleads readers about the contract's capabilities. If the fallback serves a purpose (e.g., accepting arbitrary calldata from pool callbacks without reverting), the comment should describe that actual purpose. If it has no purpose, it should be removed. - -**Recommendation:** Either: -1. Make the fallback `payable` and update the comment to `/// @notice Allows receiving ETH from pools during exchanges.` -2. Remove the fallback entirely if it is not needed. -3. Update the comment to describe the actual purpose, e.g., `/// @dev Accept arbitrary calldata without reverting for pool callback compatibility.` - -### A06-P3-2 [INFO] Unused import IERC3156FlashLender - -**Location:** Line 5 - -**Description:** -`IERC3156FlashLender` is imported but never referenced in this contract. This was noted as A06-3 (INFO) in Pass 1. From a documentation perspective, the unused import could mislead readers into thinking this contract implements or interacts with the lender interface, when it only implements the borrower side. - -### A06-P3-3 [INFO] Inherited docs reference stale V5 contract name - -**Location:** Inherited from `src/abstract/OrderBookV6FlashBorrower.sol` line 128 - -**Description:** -The `arb4` function documentation in the parent contract references `GenericPoolOrderBookV5FlashBorrower` as an example of how `exchangeData` is used. This V5 name is stale; the actual contract is `GenericPoolOrderBookV6FlashBorrower`. While this is a parent-contract issue (and would be filed against that parent in a separate agent's pass), it affects the documentation chain for this concrete contract since `_exchange`'s `@param exchangeData` says "As per `arb`", which leads readers to the stale reference. - -### A06-P3-4 [INFO] Parent contract @title says OrderBookV5FlashBorrower - -**Location:** Inherited from `src/abstract/OrderBookV6FlashBorrower.sol` line 32 - -**Description:** -The parent abstract contract's `@title` says `OrderBookV5FlashBorrower` when the contract is actually `OrderBookV6FlashBorrower`. This version mismatch in the `@title` NatSpec propagates confusion into the documentation chain of this concrete contract. Again, this is a parent issue but is noted here because it affects the documentation quality visible to readers of this contract's inheritance tree. diff --git a/audit/2026-03-13-01/pass3/LibOrder.md b/audit/2026-03-13-01/pass3/LibOrder.md deleted file mode 100644 index fe9eae7b95..0000000000 --- a/audit/2026-03-13-01/pass3/LibOrder.md +++ /dev/null @@ -1,44 +0,0 @@ -# Pass 3: Documentation -- LibOrder.sol - -**Agent:** A10 -**File:** `src/lib/LibOrder.sol` (19 lines) - -## Evidence of Thorough Reading - -- **Library name:** `LibOrder` (line 10) -- **Imports:** `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5) -- **Functions:** - - `hash(OrderV4 memory order) internal pure returns (bytes32)` -- line 16 - -No custom types, errors, events, or constants are declared. - -## Documentation Inventory - -### Library-Level Documentation - -| Item | Present? | Notes | -|---|---|---| -| `@title` | Yes (line 7) | `LibOrder` | -| `@notice` | Yes (lines 8-9) | Describes consistent handling of `OrderV4` for determinism and security | - -**Assessment:** Adequate. The library-level NatSpec correctly summarizes the purpose. - -### Function: `hash` (line 16) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| Description | Yes (lines 11-13) | Explains hashing is secure and deterministic, notes use of `abi.encode` over `abi.encodePacked` to guard against collisions | -| `@param order` | Yes (line 14) | "The order to hash." | -| `@return` | Yes (line 15) | "The hash of `order`." | - -**Assessment:** Complete and accurate. The doc comment explains both the mechanism and the rationale for choosing `abi.encode`. - -## Accuracy Check - -1. The doc says `abi.encode` is used rather than `abi.encodePacked` -- confirmed at line 17: `keccak256(abi.encode(order))`. -2. The doc says this guards against potential collisions -- this is correct; `abi.encodePacked` on dynamic types can produce ambiguous encodings. -3. The `@return` says "The hash of `order`" -- accurate. - -## Findings - -**No findings.** Documentation for `LibOrder.sol` is complete, accurate, and well-written. Every function has NatSpec with parameter and return descriptions, and the rationale for design decisions is documented. diff --git a/audit/2026-03-13-01/pass3/LibOrderBook.md b/audit/2026-03-13-01/pass3/LibOrderBook.md deleted file mode 100644 index 56cf2009ae..0000000000 --- a/audit/2026-03-13-01/pass3/LibOrderBook.md +++ /dev/null @@ -1,122 +0,0 @@ -# Pass 3: Documentation -- LibOrderBook.sol - -**Agent:** A11 -**File:** `src/lib/LibOrderBook.sol` (126 lines) - -## Evidence of Thorough Reading - -- **Library name:** `LibOrderBook` (line 96) -- **Imports:** `CONTEXT_BASE_ROWS`, `CONTEXT_BASE_ROW_SENDER`, `CONTEXT_BASE_ROW_CALLING_CONTRACT`, `CONTEXT_BASE_COLUMN` from `LibContext.sol`; `TaskV2` from `IRaindexV6.sol`; `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4` from `IInterpreterV4.sol`; `LibNamespace`, `FullyQualifiedNamespace` from `LibNamespace.sol`; `LibContext` from `LibContext.sol` (lines 5-19) -- **Constants (file-level):** - - `CALLING_CONTEXT_COLUMNS = 4` (line 28) - - `CONTEXT_COLUMNS = CALLING_CONTEXT_COLUMNS + 1` (line 30) - - `CONTEXT_CALLING_CONTEXT_COLUMN = 1` (line 36) - - `CONTEXT_CALLING_CONTEXT_ROWS = 3` (line 37) - - `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH = 0` (line 39) - - `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER = 1` (line 40) - - `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY = 2` (line 41) - - `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN = 0` (line 43) - - `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID = 1` (line 44) - - `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE = 2` (line 45) - - `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER = 3` (line 46) - - `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN = 0` (line 48) - - `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID = 1` (line 49) - - `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE = 2` (line 50) - - `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER = 3` (line 51) - - `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT = 4` (line 52) - - `CONTEXT_CALCULATIONS_COLUMN = 2` (line 56) - - `CONTEXT_CALCULATIONS_ROWS = 2` (line 57) - - `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT = 0` (line 59) - - `CONTEXT_CALCULATIONS_ROW_IO_RATIO = 1` (line 60) - - `CONTEXT_VAULT_INPUTS_COLUMN = 3` (line 66) - - `CONTEXT_VAULT_OUTPUTS_COLUMN = 4` (line 69) - - `CONTEXT_VAULT_IO_TOKEN = 0` (line 72) - - `CONTEXT_VAULT_IO_TOKEN_DECIMALS = 1` (line 74) - - `CONTEXT_VAULT_IO_VAULT_ID = 2` (line 76) - - `CONTEXT_VAULT_IO_BALANCE_BEFORE = 3` (line 79) - - `CONTEXT_VAULT_IO_BALANCE_DIFF = 4` (line 84) - - `CONTEXT_VAULT_IO_ROWS = 5` (line 86) - - `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN = 5` (line 88) - - `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS = 1` (line 89) - - `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW = 0` (line 90) - - `CONTEXT_SIGNED_CONTEXT_START_COLUMN = 6` (line 92) - - `CONTEXT_SIGNED_CONTEXT_START_ROWS = 1` (line 93) - - `CONTEXT_SIGNED_CONTEXT_START_ROW = 0` (line 94) -- **Functions:** - - `doPost(bytes32[][] memory context, TaskV2[] memory post) internal` -- line 97 - -## Documentation Inventory - -### Library-Level Documentation - -| Item | Present? | Notes | -|---|---|---| -| `@title` | **No** | No `@title` tag on the library | -| `@notice` | **No** | No `@notice` tag on the library | - -**Assessment:** The library itself has no NatSpec documentation. However, the file-level constants have extensive `@dev` documentation. - -### Constants Documentation - -Most constants have `@dev` NatSpec comments. The following is the assessment: - -| Constant Group | Documented? | Notes | -|---|---|---| -| `CALLING_CONTEXT_COLUMNS` (line 28) | Yes | Via block comment lines 21-27 | -| `CONTEXT_COLUMNS` (line 30) | No | No doc comment | -| `CONTEXT_CALLING_CONTEXT_*` (lines 36-41) | Yes | Via block comment lines 32-35 | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_*` (lines 43-46) | No | No doc comments | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_*` (lines 48-52) | No | No doc comments | -| `CONTEXT_CALCULATIONS_*` (lines 56-60) | Yes | Via `@dev` on line 54-55 | -| `CONTEXT_VAULT_INPUTS_COLUMN` (line 66) | Yes | Via `@dev` on lines 62-65 | -| `CONTEXT_VAULT_OUTPUTS_COLUMN` (line 69) | Yes | Via `@dev` on lines 67-68 | -| `CONTEXT_VAULT_IO_*` (lines 72-86) | Yes | Each has `@dev` | -| `CONTEXT_SIGNED_CONTEXT_*` (lines 88-94) | No | No doc comments | - -### Function: `doPost` (line 97) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| Description | **No** | No NatSpec at all | -| `@param context` | **No** | Missing | -| `@param post` | **No** | Missing | - -**Assessment:** The sole function in this library has zero documentation. This is a significant gap given that `doPost` is the core post-evaluation dispatch function used by the OrderBook. - -## Accuracy Check of Existing Documentation - -1. **Line 23:** Typo "calculuate" should be "calculate". -2. **Line 82-83:** Typo "subtraced" should be "subtracted". -3. The `@dev` comment on `CALLING_CONTEXT_COLUMNS` (lines 21-27) explains the context column layout. It correctly notes that calling context is populated before calculate-order, with remaining columns only available to handle-IO. This is accurate. -4. The `@dev` comment on `CONTEXT_VAULT_IO_BALANCE_DIFF` (lines 80-83) says "The diff is ALWAYS POSITIVE as it is a `uint256` so it must be added to input balances and subtraced from output balances." This is accurate in intent (the diff is unsigned), though the typo should be fixed. - -## Findings - -### A11-P3-1: Missing NatSpec on `doPost` Function [LOW] - -**Severity:** LOW - -The `doPost` function at line 97 is the only function in the library and serves as the core post-evaluation dispatch mechanism. It has no NatSpec documentation at all -- no description, no `@param`, no `@return`. This function: -- Qualifies the namespace from `msg.sender` -- Iterates through post-tasks and evaluates each with non-empty bytecode -- Writes interpreter state if any writes are produced - -Without documentation, developers must read the implementation to understand its behavior, the meaning of `context`, and the significance of namespace qualification from `msg.sender`. - -### A11-P3-2: Typo "calculuate" in Constant Documentation [INFO] - -**Severity:** INFO - -Line 23: `/// available to handle IO as they depend on the full evaluation of calculuate` -- "calculuate" should be "calculate". - -### A11-P3-3: Typo "subtraced" in Constant Documentation [INFO] - -**Severity:** INFO - -Line 82: `/// `uint256` so it must be added to input balances and subtraced from output` -- "subtraced" should be "subtracted". - -### A11-P3-4: Missing Documentation on Deposit/Withdraw and Signed Context Constants [INFO] - -**Severity:** INFO - -The deposit-related context constants (lines 43-46), withdraw-related context constants (lines 48-52), and signed context constants (lines 88-94) have no `@dev` comments, unlike most other constants in the file. For consistency and maintainability, these should have brief `@dev` descriptions explaining their role. diff --git a/audit/2026-03-13-01/pass3/LibOrderBookArb.md b/audit/2026-03-13-01/pass3/LibOrderBookArb.md deleted file mode 100644 index 49f1043ffa..0000000000 --- a/audit/2026-03-13-01/pass3/LibOrderBookArb.md +++ /dev/null @@ -1,86 +0,0 @@ -# Pass 3: Documentation -- LibOrderBookArb.sol - -**Agent:** A12 -**File:** `src/lib/LibOrderBookArb.sol` (78 lines) - -## Evidence of Thorough Reading - -- **Library name:** `LibOrderBookArb` (line 20) -- **Imports:** `TaskV2` from `IRaindexV6.sol`; `IERC20` from OpenZeppelin; `LibOrderBook`; `Address` from OpenZeppelin; `SafeERC20` from OpenZeppelin; `IERC20Metadata` from OpenZeppelin; `LibDecimalFloat`, `Float` from `rain.math.float` (lines 5-11) -- **Errors (file-level):** - - `NonZeroBeforeArbStack()` -- line 14 - - `BadLender(address badLender)` -- line 18 -- **Using declarations:** - - `using SafeERC20 for IERC20` (line 21) -- **Functions:** - - `finalizeArb(TaskV2 memory task, address ordersInputToken, uint8 inputDecimals, address ordersOutputToken, uint8 outputDecimals) internal` -- line 23 - -## Documentation Inventory - -### Library-Level Documentation - -| Item | Present? | Notes | -|---|---|---| -| `@title` | **No** | No `@title` tag | -| `@notice` | **No** | No `@notice` tag | - -**Assessment:** The library itself has no NatSpec documentation. - -### Error: `NonZeroBeforeArbStack` (line 14) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| Description | Yes (line 13) | "Thrown when the stack is not empty after the access control dispatch." | - -**Assessment:** Adequate, but this error is dead code (identified in prior pass as A12-P2-1). The description itself is accurate for what the error was intended to represent. - -### Error: `BadLender` (line 18) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| Description | Yes (line 16) | "Thrown when the lender is not the trusted `OrderBook`." | -| `@param badLender` | Yes (line 17) | "The untrusted lender calling `onFlashLoan`." | - -**Assessment:** Adequate, but this error is also dead code (identified in prior pass as A12-P2-1). - -### Function: `finalizeArb` (line 23) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| Description | **No** | No NatSpec at all | -| `@param task` | **No** | Missing | -| `@param ordersInputToken` | **No** | Missing | -| `@param inputDecimals` | **No** | Missing | -| `@param ordersOutputToken` | **No** | Missing | -| `@param outputDecimals` | **No** | Missing | - -**Assessment:** The sole function in this library has zero NatSpec documentation. The function is non-trivial -- it transfers remaining token balances and native gas to `msg.sender`, constructs a context array with float-encoded balances, and delegates to `LibOrderBook.doPost`. Inline comments exist within the function body but no formal documentation. - -## Accuracy Check of Existing Documentation - -1. **Error NatSpec (lines 13, 16-17):** Both error descriptions are accurate for what the errors were designed for, although neither error is actually used anywhere in the codebase (noted in A12-P2-1). -2. **Inline comments in `finalizeArb`:** - - Line 34: "Send all unspent input tokens to the sender." -- Accurate. - - Line 44: "Send all unspent output tokens to the sender." -- Accurate. - - Lines 57-62: Comment about Slither false positive for sending gas -- Accurate, references the correct Slither issue. - - Line 65-66: "gasBalance can't overflow int256 because there isn't enough gas in existence" -- Accurate observation about total supply constraints on production chains. - -## Findings - -### A12-P3-1: Missing NatSpec on `finalizeArb` Function [LOW] - -**Severity:** LOW - -The `finalizeArb` function at line 23 has no NatSpec documentation. It has five parameters, none documented. This function performs several important operations: -1. Transfers remaining input and output token balances to `msg.sender` -2. Transfers remaining native gas to `msg.sender` -3. Encodes balances as decimal floats into a context array -4. Calls `LibOrderBook.doPost` to execute the post-evaluation task - -The function's role as the finalization step for arbitrage operations makes documentation important for downstream maintainers. - -### A12-P3-2: Missing Library-Level NatSpec [INFO] - -**Severity:** INFO - -The `LibOrderBookArb` library has no `@title` or `@notice` tags. Adding a library-level description would clarify that this library provides shared arbitrage finalization logic used by `OrderBookV6ArbOrderTaker` and `OrderBookV6FlashBorrower`. diff --git a/audit/2026-03-13-01/pass3/LibOrderBookDeploy.md b/audit/2026-03-13-01/pass3/LibOrderBookDeploy.md deleted file mode 100644 index 0d0faac927..0000000000 --- a/audit/2026-03-13-01/pass3/LibOrderBookDeploy.md +++ /dev/null @@ -1,60 +0,0 @@ -# Pass 3: Documentation -- LibOrderBookDeploy.sol - -**Agent:** A14 -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` (53 lines) - -## Evidence of Thorough Reading - -- **Library name:** `LibOrderBookDeploy` (line 24) -- **Imports:** - - `Vm` from `forge-std/Vm.sol` (line 5) - - `BYTECODE_HASH as ORDERBOOK_HASH`, `DEPLOYED_ADDRESS as ORDERBOOK_ADDR`, `RUNTIME_CODE as ORDERBOOK_RUNTIME_CODE` from generated `OrderBookV6.pointers.sol` (lines 7-11) - - `BYTECODE_HASH as SUB_PARSER_HASH`, `DEPLOYED_ADDRESS as SUB_PARSER_ADDR`, `RUNTIME_CODE as SUB_PARSER_RUNTIME_CODE` from generated `OrderBookV6SubParser.pointers.sol` (lines 12-16) -- **Constants:** - - `ORDERBOOK_DEPLOYED_ADDRESS` (line 27) - - `ORDERBOOK_DEPLOYED_CODEHASH` (line 31) - - `SUB_PARSER_DEPLOYED_ADDRESS` (line 35) - - `SUB_PARSER_DEPLOYED_CODEHASH` (line 39) -- **Functions:** - - `etchOrderBook(Vm vm) internal` -- line 45 - -## Documentation Inventory - -### Library-Level Documentation - -| Item | Present? | Notes | -|---|---|---| -| `@title` | Yes (line 18) | `LibOrderBookDeploy` | -| `@notice` | Yes (lines 19-23) | Describes purpose: library containing deployed address and code hash for OrderBook contracts deployed with rain standard zoltu deployer, enabling idempotent deployments with verifiable addresses and hashes | - -**Assessment:** Excellent. The library-level documentation clearly explains the purpose, the deployment mechanism (zoltu deployer), and the value proposition (idempotent deployments, automatic verification). - -### Constants - -| Constant | Documented? | Content | -|---|---|---| -| `ORDERBOOK_DEPLOYED_ADDRESS` (line 27) | Yes (lines 25-26) | "The address of the `OrderBookV6` contract when deployed with the rain standard zoltu deployer." | -| `ORDERBOOK_DEPLOYED_CODEHASH` (line 31) | Yes (lines 29-30) | "The code hash of the `OrderBookV6` contract when deployed with the rain standard zoltu deployer." | -| `SUB_PARSER_DEPLOYED_ADDRESS` (line 35) | Yes (lines 33-34) | "The address of the `OrderBookV6SubParser` contract when deployed with the rain standard zoltu deployer." | -| `SUB_PARSER_DEPLOYED_CODEHASH` (line 39) | Yes (lines 37-38) | "The code hash of the `OrderBookV6SubParser` contract when deployed with the rain standard zoltu deployer." | - -**Assessment:** All four constants are fully documented with consistent wording. - -### Function: `etchOrderBook` (line 45) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| `@notice` | Yes (lines 41-43) | "Etches the runtime bytecode of the orderbook and sub parser at their expected deterministic addresses. Skips any contract whose codehash already matches." | -| `@param vm` | Yes (line 44) | "The Forge `Vm` cheatcode interface." | - -**Assessment:** Complete. The description accurately covers the function behavior including the skip-if-matching optimization. - -## Accuracy Check - -1. **`@notice` on `etchOrderBook` (lines 41-43):** Says "Etches the runtime bytecode...at their expected deterministic addresses. Skips any contract whose codehash already matches." -- Confirmed at lines 46-51: the function checks `codehash` before calling `vm.etch`, and skips if already matching. -2. **Library-level `@notice`:** References "rain standard zoltu deployer" -- this is a known deployment mechanism used in the Rain ecosystem for deterministic contract deployment. -3. **Constant documentation:** Each constant correctly describes what it holds (address vs. code hash) and which contract it refers to (OrderBookV6 vs. OrderBookV6SubParser). - -## Findings - -**No findings.** Documentation for `LibOrderBookDeploy.sol` is complete, accurate, and thorough. Every constant and function has appropriate NatSpec with parameter descriptions. The library-level documentation provides clear context for the purpose and design rationale. diff --git a/audit/2026-03-13-01/pass3/LibOrderBookSubParser.md b/audit/2026-03-13-01/pass3/LibOrderBookSubParser.md deleted file mode 100644 index 37ba0e6aec..0000000000 --- a/audit/2026-03-13-01/pass3/LibOrderBookSubParser.md +++ /dev/null @@ -1,122 +0,0 @@ -# Pass 3: Documentation -- LibOrderBookSubParser.sol - -**Agent:** A13 -**File:** `src/lib/LibOrderBookSubParser.sol` (599 lines) - -## Evidence of Thorough Reading - -- **Library name:** `LibOrderBookSubParser` (line 98) -- **Imports:** `AuthoringMetaV2`, `OperandV2` from `ISubParserV4.sol`; `LibUint256Matrix`; `LibSubParse`; ~40 context constants from `LibOrderBook.sol` (lines 5-46) -- **File-level constants:** - - `SUB_PARSER_WORD_PARSERS_LENGTH = 2` (line 48) - - `EXTERN_PARSE_META_BUILD_DEPTH = 1` (line 49) - - `WORD_ORDER_CLEARER` through `WORD_WITHDRAW_TARGET_AMOUNT` -- 22 word constants (lines 51-80) - - `DEPOSIT_WORD_*` constants (lines 82-87) - - `WITHDRAW_WORD_*` constants (lines 89-95) -- **Using declarations:** - - `using LibUint256Matrix for uint256[][]` (line 99) -- **Functions (28 total):** - - `subParserSender` -- line 101 - - `subParserCallingContract` -- line 106 - - `subParserOrderHash` -- line 115 - - `subParserOrderOwner` -- line 124 - - `subParserOrderCounterparty` -- line 133 - - `subParserMaxOutput` -- line 143 - - `subParserIORatio` -- line 152 - - `subParserInputToken` -- line 161 - - `subParserInputTokenDecimals` -- line 170 - - `subParserInputVaultId` -- line 179 - - `subParserInputBalanceBefore` -- line 188 - - `subParserInputBalanceDiff` -- line 197 - - `subParserOutputToken` -- line 206 - - `subParserOutputTokenDecimals` -- line 215 - - `subParserOutputVaultId` -- line 224 - - `subParserOutputBalanceBefore` -- line 233 - - `subParserOutputBalanceDiff` -- line 242 - - `subParserSigners` -- line 251 - - `subParserDepositToken` -- line 260 - - `subParserDepositVaultId` -- line 269 - - `subParserDepositVaultBalanceBefore` -- line 279 - - `subParserDepositVaultBalanceAfter` -- line 291 - - `subParserWithdrawToken` -- line 303 - - `subParserWithdrawVaultId` -- line 312 - - `subParserWithdrawVaultBalanceBefore` -- line 322 - - `subParserWithdrawVaultBalanceAfter` -- line 334 - - `subParserWithdrawTargetAmount` -- line 346 - - `subParserSignedContext` -- line 357 - - `authoringMetaV2` -- line 369 - -## Documentation Inventory - -### Library-Level Documentation - -| Item | Present? | Notes | -|---|---|---| -| `@title` | Yes (line 97) | `LibOrderBookSubParser` | -| `@notice` | **No** | No `@notice` tag | - -**Assessment:** Minimal. Only `@title` is present; no description of the library's purpose. - -### File-Level Constants - -| Constant Group | Documented? | Notes | -|---|---|---| -| `SUB_PARSER_WORD_PARSERS_LENGTH` (line 48) | No | No doc comment | -| `EXTERN_PARSE_META_BUILD_DEPTH` (line 49) | No | No doc comment | -| `WORD_*` constants (lines 51-80) | No | No doc comments; the names are self-documenting as word string literals | -| `DEPOSIT_WORD_*` constants (lines 82-87) | No | No doc comments | -| `WITHDRAW_WORD_*` constants (lines 89-95) | No | No doc comments | - -### Functions: SubParser Dispatch Functions (27 functions, lines 101-365) - -**None of the 27 subparser dispatch functions have any NatSpec documentation.** - -All follow the same signature pattern: `function subParser*(uint256, uint256, OperandV2) internal pure returns (bool, bytes memory, bytes32[] memory)` and delegate to `LibSubParse.subParserContext(column, row)`. - -The unnamed parameters (`uint256, uint256`) receive no documentation explaining what they represent or why they are unused. - -### Function: `authoringMetaV2` (line 369) - -| NatSpec Tag | Present? | Content | -|---|---|---| -| Description | **No** | No NatSpec | -| `@return` | **No** | Missing | - -**Assessment:** This large function (230 lines) constructs the complete authoring metadata for all context words. It has no NatSpec despite being the primary metadata export of the library. - -## Accuracy Check of Existing Documentation - -1. **Line 507:** Typo "much" should be "must": `"...but the expression author much authorize the signer's public key."` should be `"...but the expression author must authorize the signer's public key."` - -2. **Authoring metadata string descriptions:** The inline description strings within `AuthoringMetaV2` struct literals serve as user-facing documentation for the Rainlang sub-parser. These descriptions are generally accurate: - - The "order-clearer" description (lines 381-382) correctly distinguishes the clearer from the counterparty. - - The "calculated-max-output" and "calculated-io-ratio" descriptions correctly note that values are 0 before calculations have been run. - - The input/output vault balance descriptions correctly state the diff is always positive and must be added/subtracted respectively. - - The "signed-context" description at line 507 has the typo noted above. - -3. **Comment at line 370:** "Add 2 for the signed context signers and signed context start columns. 1 for the deposit context. 1 for the withdraw context." This correctly explains the `CONTEXT_COLUMNS + 2 + 1 + 1` allocation. - -## Findings - -### A13-P3-1: No NatSpec on Any of the 28 SubParser Functions [LOW] - -**Severity:** LOW - -All 28 functions in `LibOrderBookSubParser` (27 subparser dispatch functions plus `authoringMetaV2`) have zero NatSpec documentation. While the function names are descriptive, there is no documentation explaining: -- What the unnamed `uint256, uint256` parameters represent (they appear to be dispatch metadata that these functions ignore) -- What the return tuple `(bool, bytes memory, bytes32[] memory)` means -- What the function does (maps a word to a context column/row reference) - -For the dispatch functions, a single shared doc comment block explaining the pattern would be sufficient, with individual functions only needing documentation where behavior differs (e.g., `subParserSigners` and `subParserSignedContext` which use the operand parameter). - -### A13-P3-2: Typo "much" in Signed Context Metadata Description [INFO] - -**Severity:** INFO - -Line 507: The authoring metadata string for "signed-context" contains `"...but the expression author much authorize the signer's public key."` The word "much" should be "must". - -### A13-P3-3: Missing Library-Level `@notice` [INFO] - -**Severity:** INFO - -The library has `@title` but no `@notice` or description. A brief explanation that this library provides sub-parser word dispatch functions mapping Rainlang context words to orderbook context grid positions would aid comprehension. diff --git a/audit/2026-03-13-01/pass3/OrderBookV6.md b/audit/2026-03-13-01/pass3/OrderBookV6.md deleted file mode 100644 index a53a931b81..0000000000 --- a/audit/2026-03-13-01/pass3/OrderBookV6.md +++ /dev/null @@ -1,267 +0,0 @@ -# Pass 3: Documentation -- OrderBookV6.sol - -**Agent:** A08 -**File:** `src/concrete/ob/OrderBookV6.sol` (1055 lines) - -## Evidence of Thorough Reading - -### Contract -- **Name:** `OrderBookV6` (line 198) -- **Inherits:** `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender` -- **Pragma:** `solidity =0.8.25` (line 3) - -### All Functions with Line Numbers - -| Function | Line | Visibility | Has NatSpec | -|----------|------|------------|-------------| -| `vaultBalance2` | 226 | external view | `@inheritdoc IRaindexV6` | -| `_vaultBalance` | 231 | internal view | No | -| `orderExists` | 249 | external view | `@inheritdoc IRaindexV6` | -| `entask2` | 254 | external | `@inheritdoc IRaindexV6` | -| `deposit4` | 259 | external | `@inheritdoc IRaindexV6` | -| `withdraw4` | 294 | external | `@inheritdoc IRaindexV6` | -| `addOrder4` | 333 | external | `@inheritdoc IRaindexV6` | -| `removeOrder3` | 383 | external | `@inheritdoc IRaindexV6` | -| `checkTokenSelfTrade` | 406 | internal pure | No | -| `quote2` | 413 | external view | `@inheritdoc IRaindexV6` | -| `takeOrders4` | 436 | external | `@inheritdoc IRaindexV6` | -| `clear3` | 596 | external | `@inheritdoc IRaindexV6` | -| `calculateOrderIO` | 701 | internal view | Yes (full NatSpec) | -| `increaseVaultBalance` | 823 | internal | No | -| `decreaseVaultBalance` | 854 | internal | No | -| `recordVaultIO` | 886 | internal | Yes (partial NatSpec) | -| `handleIO` | 916 | internal | No | -| `calculateClearStateChange` | 963 | internal pure | Yes (full NatSpec) | -| `calculateClearStateAlice` | 984 | internal pure | No | -| `pullTokens` | 1003 | internal | No | -| `pushTokens` | 1025 | internal | No | -| `_nonZeroVaultId` | 1045 | internal pure | No | -| `nonZeroVaultId` (modifier) | 1051 | -- | No | - -### Types, Errors, and Constants - -**Struct:** `OrderIOCalculationV4` (line 181) -- has detailed NatSpec for all fields on lines 152-180. - -**User-defined value types:** -- `Output18Amount` (line 192) -- no doc -- `Input18Amount` (line 194) -- no doc - -**Errors (lines 69-125):** - -| Error | Line | Has NatSpec | -|-------|------|-------------| -| `ReentrancyGuardReentrantCall()` | 69 | Yes (partial) | -| `NotOrderOwner(address)` | 73 | Yes, with `@param` | -| `TokenMismatch()` | 76 | Yes | -| `TokenSelfTrade()` | 79 | Yes | -| `TokenDecimalsMismatch()` | 83 | Yes | -| `MinimumIO(Float, Float)` | 88 | Yes, with `@param`s | -| `SameOwner()` | 91 | Yes | -| `UnsupportedCalculateInputs(uint256)` | 95 | Yes, with `@param` | -| `UnsupportedCalculateOutputs(uint256)` | 98 | Yes, with `@param` | -| `NegativeInput()` | 102 | Yes | -| `NegativeOutput()` | 105 | Yes | -| `NegativeVaultBalance(Float)` | 109 | Yes, with `@param` | -| `NegativeVaultBalanceChange(Float)` | 113 | Yes, with `@param` | -| `NegativePull()` | 116 | Yes | -| `NegativePush()` | 119 | Yes | -| `NegativeBounty()` | 122 | Yes | -| `ClearZeroAmount()` | 125 | Yes | - -**Constants (lines 127-150):** - -| Constant | Line | Has NatSpec | -|----------|------|-------------| -| `ORDER_LIVE` | 129 | Yes (`@dev`) | -| `ORDER_DEAD` | 134 | Yes (`@dev`) | -| `CALCULATE_ORDER_ENTRYPOINT` | 137 | Yes (`@dev`) | -| `HANDLE_IO_ENTRYPOINT` | 140 | Yes (`@dev`) | -| `CALCULATE_ORDER_MIN_OUTPUTS` | 143 | Yes (`@dev`) | -| `CALCULATE_ORDER_MAX_OUTPUTS` | 145 | Yes (`@dev`) | -| `HANDLE_IO_MIN_OUTPUTS` | 148 | Yes (`@dev`) | -| `HANDLE_IO_MAX_OUTPUTS` | 150 | Yes (`@dev`) | - -**Storage variables:** - -| Variable | Line | Has NatSpec | -|----------|------|-------------| -| `sOrders` | 215 | Yes (inline comments) | -| `sVaultBalances` | 222 | Yes (`@dev`) | - ---- - -## Systematic Documentation Audit - -### Public/External Functions - -All 10 public/external functions use `@inheritdoc IRaindexV6`, which delegates documentation to the interface. I verified each interface NatSpec in `lib/rain.raindex.interface/src/interface/IRaindexV6.sol`: - -| Function | Interface NatSpec Quality | Params Documented | Returns Documented | -|----------|--------------------------|-------------------|--------------------| -| `vaultBalance2` (iface line 320-325) | Good | `@param owner`, `@param token`, `@param vaultId` | `@return balance` | -| `orderExists` (iface line 395-398) | Good | `@param orderHash` | `@return exists` | -| `entask2` (iface line 327-333) | Good | `@param tasks` | N/A (void) | -| `deposit4` (iface line 335-369) | Good (extensive) | `@param token`, `@param vaultId`, `@param depositAmount`, `@param tasks` | N/A (void) | -| `withdraw4` (iface line 371-393) | Good (extensive) | `@param token`, `@param vaultId`, `@param targetAmount`, `@param tasks` | N/A (void) | -| `addOrder4` (iface line 416-447) | Good (extensive) | `@param config`, `@param tasks` | `@return stateChanged` | -| `removeOrder3` (iface line 449-461) | Good | `@param order`, `@param tasks` | `@return stateChanged` | -| `quote2` (iface line 400-414) | Good | `@param quoteConfig` | `@return exists`, `@return outputMax`, `@return ioRatio` | -| `takeOrders4` (iface line 463-506) | Good (extensive) | `@param config` | `@return totalTakerInput`, `@return totalTakerOutput` | -| `clear3` (iface line 508-561) | Good (extensive) | `@param alice`, `@param bob`, `@param clearConfig`, `@param aliceSignedContext`, `@param bobSignedContext` | N/A (void) | - -All public/external functions have complete documentation via interface inheritance. Parameters and return values are fully documented in the interface. - -### Internal Functions Documentation Check - -| Function | Doc Status | Quality | -|----------|------------|---------| -| `_vaultBalance` (line 231) | No NatSpec | Missing -- complex branching logic for vault ID 0 vs non-zero deserves documentation | -| `checkTokenSelfTrade` (line 406) | No NatSpec | Missing -- simple but undocumented | -| `calculateOrderIO` (lines 690-701) | Full NatSpec | Good: describes purpose, all 5 `@param`s documented, behavior explained | -| `increaseVaultBalance` (line 823) | No NatSpec | Missing -- important function with vault ID 0 special behavior | -| `decreaseVaultBalance` (line 854) | No NatSpec | Missing -- important function with vault ID 0 special behavior | -| `recordVaultIO` (lines 886-892) | Partial NatSpec | Has description and 2 of 3 `@param`s -- see finding A08-P3-1 | -| `handleIO` (line 916) | No NatSpec | Missing -- important function that dispatches interpreter eval | -| `calculateClearStateChange` (lines 963-970) | Full NatSpec | Good: describes purpose, both `@param`s, `@return` documented | -| `calculateClearStateAlice` (line 984) | No NatSpec | Missing -- non-trivial capping logic undocumented | -| `pullTokens` (line 1003) | No NatSpec | Missing -- important token transfer function with rounding behavior | -| `pushTokens` (line 1025) | No NatSpec | Missing -- important token transfer function with rounding behavior | -| `_nonZeroVaultId` (line 1045) | No NatSpec | Missing -- trivial but undocumented | -| `nonZeroVaultId` modifier (line 1051) | No NatSpec | Missing | - ---- - -## Findings - -### A08-P3-1 [LOW] Stale/inaccurate comment in `recordVaultIO` contradicts code execution order - -**Location:** Line 902 - -The NatSpec for `recordVaultIO` (lines 886-892) reads: - -``` -/// Given an order, final input and output amounts and the IO calculation -/// verbatim from `_calculateOrderIO`, dispatch the handle IO entrypoint if -/// it exists and update the order owner's vault balances. -/// @param input The input amount. -/// @param output The output amount. -/// @param orderIOCalculation The order IO calculation produced by -``` - -There are three documentation issues: - -1. **Stale function reference:** The doc says "from `_calculateOrderIO`" but the function is actually named `calculateOrderIO` (no leading underscore). The underscore prefix was likely from an earlier version. - -2. **Inaccurate description of behavior:** The doc says "dispatch the handle IO entrypoint if it exists." However, `recordVaultIO` does NOT dispatch handle IO -- it only records vault balance changes and emits `ContextV2`. The `handleIO` dispatch is a separate function called independently after `recordVaultIO`. This is misleading about the function's responsibilities. - -3. **Stale comment on execution order (line 902):** The inline comment says "Decrease before increasing so that if vault id == 0 then we pull tokens before pushing them." However, the code does the OPPOSITE: it calls `increaseVaultBalance` first (line 896), then `decreaseVaultBalance` (line 904). For vault ID 0, this means tokens are pushed before being pulled. The comment describes the inverse of the actual behavior. (Originally identified in Pass 1 as A08-2.) - -4. **Truncated `@param` tag:** The `@param orderIOCalculation` tag on line 892 reads "The order IO calculation produced by" and is truncated mid-sentence. The sentence never completes with what produces it. - ---- - -### A08-P3-2 [INFO] `HANDLE_IO_MAX_OUTPUTS` doc has typo: "response" should be "responds" - -**Location:** Line 149 - -```solidity -/// @dev Handle IO has no outputs as it only response to vault movements. -uint16 constant HANDLE_IO_MAX_OUTPUTS = 0; -``` - -The word "response" should be "responds" to match the grammatically correct version on line 147 ("it only responds to vault movements"). - ---- - -### A08-P3-3 [INFO] Contract-level NatSpec is minimal -- defers entirely to interface - -**Location:** Lines 196-198 - -```solidity -/// @title OrderBookV6 -/// See `IRaindexV6` for more documentation. -contract OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, OrderBookV6FlashLender { -``` - -The contract's own documentation is a single line deferring to the interface. While the interface documentation is excellent and thorough, the contract itself has implementation-specific behaviors not covered by the interface docs: - -- Vault ID 0 special behavior (vaultless orders pulling/pushing tokens directly) -- The TOFU token decimals resolution mechanism -- The Float-based internal accounting model -- The order of operations in `recordVaultIO` (increase then decrease) -- The flash loan interaction model with `takeOrders4` - -These are all documented in the interface, so this is not a gap per se, but a reader of the implementation file alone would need to consult a separate file for context. - ---- - -### A08-P3-4 [INFO] 11 internal functions lack NatSpec documentation - -**Location:** Various (see table above in "Internal Functions Documentation Check") - -The following internal functions have no NatSpec comments: - -1. `_vaultBalance` (line 231) -- vault balance retrieval with vault ID 0 branching and TOFU decimal resolution -2. `checkTokenSelfTrade` (line 406) -- self-trade guard -3. `increaseVaultBalance` (line 823) -- balance increase with vault ID 0 special handling (push tokens) -4. `decreaseVaultBalance` (line 854) -- balance decrease with vault ID 0 special handling (pull tokens) -5. `handleIO` (line 916) -- dispatches handle IO entrypoint to interpreter -6. `calculateClearStateAlice` (line 984) -- calculates one side of a clear with capping logic -7. `pullTokens` (line 1003) -- transfers tokens into the contract with rounding up -8. `pushTokens` (line 1025) -- transfers tokens out of the contract with truncation -9. `_nonZeroVaultId` (line 1045) -- vault ID zero guard -10. `nonZeroVaultId` modifier (line 1051) -- modifier wrapper for the above -11. `checkTokenSelfTrade` (line 406) -- prevents input==output token - -Of these, the most impactful gaps are `increaseVaultBalance`, `decreaseVaultBalance`, `pullTokens`, and `pushTokens` because they contain critical rounding behavior and vault ID 0 special-case logic that directly affects the economic correctness of the system. The rounding semantics (round up on pull, truncate on push) are only described in inline comments, not in function-level NatSpec. - ---- - -### A08-P3-5 [INFO] Unused types `Output18Amount` and `Input18Amount` have no documentation - -**Location:** Lines 192-194 - -```solidity -type Output18Amount is uint256; -type Input18Amount is uint256; -``` - -These types lack any NatSpec documentation. They are also unused in the contract (identified in Pass 1 as A08-4 and Pass 2 as A08-16). Since they appear to be vestigial from a pre-Float era, their lack of documentation compounds the confusion about their purpose. - ---- - -### A08-P3-6 [INFO] `OrderIOCalculationV4` struct NatSpec references outdated scaling behavior - -**Location:** Lines 152-173 - -The struct documentation extensively describes "18 decimal fixed point" scaling and rescaling behavior: - -- Line 155: "WILL BE RESCALED ACCORDING TO TOKEN DECIMALS to an 18 fixed point decimal number" -- Line 164: "IORatio is SCALED ACCORDING TO TOKEN DECIMALS to allow 18 decimal fixed point math" -- Line 166: "`1e18` returned from the expression is ALWAYS 'one'" - -However, in the current Float-based implementation, values returned by the expression are NOT 18-decimal fixed point. They are rain floating point values (`Float`). The `calculateOrderIO` function (line 701) reads `orderIORatio` and `orderOutputMax` directly from the stack as `Float` values (lines 794-797) without any 18-decimal conversion. The actual conversion to token-specific decimals only happens in `pullTokens`/`pushTokens` when tokens physically move. - -The examples about DAI/USDT at `1e18` ratio and `1e12` conversion (lines 168-173) describe behavior from a fixed-point version of the contract, not the current Float-based design. The NatSpec for `IORatio` references "THE ORDER DEFINES THE DECIMALS" (line 171), but in the current implementation, decimals come from the token's own `decimals()` call via TOFU, not from the order definition (the `IOV2.decimals` field is no longer present in the struct). - ---- - -## Summary - -### Public/External Function Documentation: Complete -All 10 public/external functions use `@inheritdoc IRaindexV6` and the interface provides thorough documentation with all parameters and return values described. - -### Internal Function Documentation: Sparse -11 of 13 internal functions lack NatSpec. The 2 that have NatSpec (`calculateOrderIO` and `calculateClearStateChange`) are well-documented. `recordVaultIO` has partial NatSpec but it is stale and inaccurate. - -### Error/Constant/Type Documentation: Good -All 17 errors have NatSpec with parameter tags. All 8 constants have `@dev` tags. The `OrderIOCalculationV4` struct has detailed documentation (though partially stale -- see A08-P3-6). The unused type aliases have no documentation. - -### Accuracy of Existing Documentation: Issues Found -- `recordVaultIO` NatSpec is stale in 4 ways (A08-P3-1, LOW) -- `OrderIOCalculationV4` struct docs reference obsolete 18-decimal fixed-point behavior (A08-P3-6, INFO) -- Typo in `HANDLE_IO_MAX_OUTPUTS` (A08-P3-2, INFO) - -### Finding Count -- **LOW:** 1 (A08-P3-1) -- **INFO:** 5 (A08-P3-2 through A08-P3-6) diff --git a/audit/2026-03-13-01/pass3/OrderBookV6ArbCommon.md b/audit/2026-03-13-01/pass3/OrderBookV6ArbCommon.md deleted file mode 100644 index 1d703bceda..0000000000 --- a/audit/2026-03-13-01/pass3/OrderBookV6ArbCommon.md +++ /dev/null @@ -1,155 +0,0 @@ -# Pass 3: Documentation -- OrderBookV6ArbCommon.sol - -**Agent:** A01 -**File:** `src/abstract/OrderBookV6ArbCommon.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract/Module Name -- `OrderBookV6ArbCommon` (abstract contract, line 34) - -### Struct Definitions (file scope) -- `OrderBookV6ArbConfig` (lines 21-25): fields `orderBook` (address), `task` (TaskV2), `implementationData` (bytes) - -### Error Definitions (file scope) -- `WrongTask()` (line 28) - -### Constant Definitions (file scope) -- `BEFORE_ARB_SOURCE_INDEX` (line 32): `SourceIndexV2.wrap(0)` - -### State Variables -- `iTaskHash` (line 39): `bytes32 public immutable`, initialized to `0` - -### Events -- `Construct(address sender, OrderBookV6ArbConfig config)` (line 37) - -### Functions/Modifiers (with line numbers) -- `constructor(OrderBookV6ArbConfig memory config)` (line 41) -- `modifier onlyValidTask(TaskV2 memory task)` (line 50) - -### Imports (lines 5-14) -- `EvaluableV4`, `SignedContextV1` from `IInterpreterCallerV4.sol` -- `IInterpreterV4`, `SourceIndexV2`, `DEFAULT_STATE_NAMESPACE` from `IInterpreterV4.sol` -- `IRaindexV6`, `TaskV2` from `IRaindexV6.sol` -- `LibContext` from `LibContext.sol` -- `LibNamespace` from `LibNamespace.sol` -- `LibEvaluable` from `LibEvaluable.sol` -- `using LibEvaluable for EvaluableV4` (line 35) - -## Documentation Inventory - -### File-Level / License Headers -- SPDX license identifier: present (line 1) -- SPDX copyright: present (line 2) -- Pragma: `^0.8.19` (line 3) - -### Struct: `OrderBookV6ArbConfig` (lines 16-25) -- **Top-level comment:** "Configuration for an arb contract to construct." (line 16) -- present and accurate. -- **`@param orderBook`:** "The `OrderBook` contract to arb against." (line 17) -- present and accurate. -- **`@param tasks`:** "The tasks to use as post for each arb." (line 18) -- **INACCURATE**: the param name in the doc says `tasks` (plural) but the actual struct field is `task` (singular, `TaskV2 task` on line 23). The description "as post for each arb" is also vague. -- **`@param implementationData`:** "The constructor data for the specific implementation of the arb contract." (lines 19-20) -- present and accurate. - -### Error: `WrongTask()` (line 28) -- **Comment:** "Thrown when the task does not match the expected hash." (line 27) -- present and accurate. - -### Constant: `BEFORE_ARB_SOURCE_INDEX` (line 32) -- **Comment:** `@dev` "Before arb" is evaluated before the flash loan is taken. Ostensibly allows for some kind of access control to the arb." (lines 30-31) -- present. Partially accurate. The description says "before the flash loan is taken" which is only true for the `OrderBookV6FlashBorrower` path. In `OrderBookV6ArbOrderTaker`, there is no flash loan; the before-arb logic runs before `takeOrders` is called directly. Also, this constant is defined but never used within this file -- it is redefined in `OrderBookV6ArbOrderTaker.sol` (line 29) with slightly different wording and consumed through `LibOrderBookArb`. - -### Contract: `OrderBookV6ArbCommon` (line 34) -- **No NatDoc on the contract declaration.** There is no `@title`, `@notice`, or `@dev` comment on the `abstract contract OrderBookV6ArbCommon` line. For comparison, the inheriting `OrderBookV6FlashBorrower` has a multi-paragraph `@title`/`@notice` block (though it has its own doc accuracy issues -- see A01-P3-4). - -### Event: `Construct` (line 37) -- **No documentation.** The event has no NatDoc comment describing its purpose or parameters. - -### State Variable: `iTaskHash` (line 39) -- **No documentation.** The public immutable variable has no NatDoc or `@dev` comment explaining its purpose, its zero-default meaning, or how it is set. - -### Constructor (lines 41-48) -- **No NatDoc.** The constructor has no `@param` or `@dev` documentation. There is one inline comment: "Emit events before any external calls are made." (line 42), which is accurate (though there are no external calls in this constructor, the comment likely establishes a pattern for inheriting contracts). - -### Modifier: `onlyValidTask` (lines 50-55) -- **No documentation.** The modifier has no NatDoc comment describing its purpose, parameters, or revert conditions. - -## Public/External Interface Documentation Audit - -The contract exposes one public interface item via auto-generated getter: - -| Item | Visibility | Documented? | Parameters Documented? | Return Documented? | -|------|-----------|-------------|----------------------|-------------------| -| `iTaskHash` (getter) | public | NO | N/A | NO | - -The constructor and modifier are not external-facing in the traditional sense but are part of the contract's API for inheriting contracts: - -| Item | Documented? | Parameters Documented? | Behavior Documented? | -|------|-------------|----------------------|---------------------| -| `constructor` | NO | NO (`config` param undocumented) | NO | -| `onlyValidTask` | NO | NO (`task` param undocumented) | NO (revert condition undocumented) | - -## Documentation Accuracy Review - -### Struct `@param tasks` vs actual field name `task` - -The NatDoc on line 18 says `@param tasks` but the struct field on line 23 is `task` (singular `TaskV2 task`). This is a name mismatch between documentation and implementation. Solidity compilers do not currently enforce NatDoc param name matching for struct fields, so this compiles without warning but misleads readers. - -### `BEFORE_ARB_SOURCE_INDEX` doc mentions "flash loan" only - -The `@dev` comment says "evaluated before the flash loan is taken" but this constant is intended for use by both flash-loan-based and non-flash-loan-based arb contracts. The `OrderBookV6ArbOrderTaker` path has no flash loan. Furthermore, this exact constant is redefined in `OrderBookV6ArbOrderTaker.sol` line 29 with wording "evaluabled before the arb is executed" (note also the typo "evaluabled" in that file). - -### `OrderBookV6FlashBorrower` title mismatch - -While not in this file, the inheriting `OrderBookV6FlashBorrower.sol` (line 32) has `@title OrderBookV5FlashBorrower` -- a stale V5 reference. This is noted here because this pass reviews documentation accuracy for the `OrderBookV6ArbCommon` family. - -## Findings - -### A01-P3-1 [LOW] Struct `@param` Name Mismatch: `tasks` vs `task` - -**Severity:** LOW - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:18` (NatDoc) vs line 23 (struct field) - -**Description:** The NatDoc comment for `OrderBookV6ArbConfig` documents `@param tasks` (plural) but the actual struct field is `task` (singular `TaskV2 task`). This mismatch between documentation and implementation could mislead readers into thinking the struct accepts multiple tasks. The prior version of this struct likely had a `TaskV2[] tasks` array field; the documentation was not updated when the field was changed to a single `TaskV2 task`. - -**Impact:** Developers integrating with this contract may incorrectly believe they can pass multiple tasks, leading to compilation errors or incorrect configuration. As a documentation-only issue in an abstract contract primarily used by sophisticated arb bot operators, the practical impact is low but the inaccuracy is clear. - -### A01-P3-2 [LOW] Missing Documentation on Contract, Event, State Variable, Constructor, and Modifier - -**Severity:** LOW - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:34` (contract), line 37 (event), line 39 (state variable), line 41 (constructor), line 50 (modifier) - -**Description:** The following items have no NatDoc documentation: - -1. **Contract `OrderBookV6ArbCommon`** (line 34): No `@title`, `@notice`, or `@dev`. Both inheriting contracts (`OrderBookV6FlashBorrower` and `OrderBookV6ArbOrderTaker`) have contract-level documentation, but the base abstract contract does not describe its purpose as the common base for arb contracts. - -2. **Event `Construct`** (line 37): No documentation on what the event signals or when it is emitted. No `@param` for `sender` or `config`. - -3. **State variable `iTaskHash`** (line 39): No documentation explaining that this holds the keccak256 hash of the configured task (or `bytes32(0)` if no task was configured), and that it is used by the `onlyValidTask` modifier for validation. - -4. **Constructor** (line 41): No `@param config` documentation. - -5. **Modifier `onlyValidTask`** (line 50): No documentation explaining the validation logic, the pass-through behavior when `iTaskHash == 0`, or the `WrongTask` revert condition. - -**Impact:** This contract is abstract and meant to be inherited. Without documentation, developers building new arb contract variants must read the implementation to understand the contract's behavior. The modifier's dual behavior (pass-through when unconfigured, hash-check when configured) is particularly non-obvious without documentation. - -### A01-P3-3 [LOW] `BEFORE_ARB_SOURCE_INDEX` Documentation Inaccurately Scoped to Flash Loans - -**Severity:** LOW - -**Location:** `src/abstract/OrderBookV6ArbCommon.sol:30-32` - -**Description:** The `@dev` comment says: "Before arb is evaluated before the flash loan is taken." This describes only the `OrderBookV6FlashBorrower` usage path. The constant is equally intended for `OrderBookV6ArbOrderTaker`, which does not use flash loans. The documentation should describe the constant generically as being evaluated before the arb executes, regardless of mechanism. - -Additionally, this constant is defined at file scope in `OrderBookV6ArbCommon.sol` but is never referenced within this file or by any contract that imports from it. It is independently redefined in `OrderBookV6ArbOrderTaker.sol` (line 29). The file-scope definition here is dead code with misleading documentation. - -**Impact:** Misleading documentation could cause a developer to believe this constant is only relevant to flash-loan-based arb, or to modify it here expecting the change to propagate, when in fact the actual consumers define their own copies. - -### A01-P3-4 [INFO] Stale V5 Reference in `OrderBookV6FlashBorrower` Title - -**Severity:** INFO - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol:32` - -**Description:** The `@title` says `OrderBookV5FlashBorrower` but the actual contract name is `OrderBookV6FlashBorrower`. This is a stale reference from a prior version. While this is in a different file, it is noted here as part of the documentation accuracy review for the `OrderBookV6ArbCommon` inheritance tree. - -**Impact:** No functional impact. Cosmetic documentation staleness. diff --git a/audit/2026-03-13-01/pass3/OrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass3/OrderBookV6ArbOrderTaker.md deleted file mode 100644 index 4c217b3ae3..0000000000 --- a/audit/2026-03-13-01/pass3/OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,92 +0,0 @@ -# Pass 3: Documentation — OrderBookV6ArbOrderTaker.sol - -**Agent:** A02 -**File:** `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence of Thorough Reading - -| Element | Kind | Line | Has Doc Comment | -|---|---|---|---| -| `NonZeroBeforeArbInputs(uint256)` | error | 25 | Yes (line 24) | -| `BEFORE_ARB_SOURCE_INDEX` | constant (`SourceIndexV2`) | 29 | Yes, `@dev` (lines 27-28) | -| `OrderBookV6ArbOrderTaker` | abstract contract | 31 | **No** | -| `constructor(OrderBookV6ArbConfig)` | constructor | 40 | **No** | -| `supportsInterface(bytes4)` | function (public view override) | 43 | `@inheritdoc IERC165` (line 42) | -| `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` | function (external payable) | 49 | `@inheritdoc IRaindexV6ArbOrderTaker` (line 48) | -| `onTakeOrders2(address, address, Float, Float, bytes)` | function (public virtual override) | 78 | `@inheritdoc IRaindexV6OrderTaker` (line 77) | - -Inheritance chain: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon`. - -## Documentation Verification per Function - -### `supportsInterface` (line 43) -Uses `@inheritdoc IERC165`. The inherited doc from OpenZeppelin ERC165 adequately describes the function's purpose. The override adds two additional interface IDs (`IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`) but does not document them. This is acceptable because `@inheritdoc` is the standard pattern and the implementation is self-explanatory. - -### `arb5` (line 49) -Uses `@inheritdoc IRaindexV6ArbOrderTaker`. The interface at `lib/rain.raindex.interface/src/interface/IRaindexV6ArbOrderTaker.sol` provides thorough documentation: -- Function purpose: described as executing arbitrage against a Raindex. -- `@param raindex` - documented. -- `@param takeOrders` - documented. -- `@param task` - documented. -- Return values: none (void), N/A. - -The interface doc states "Implementations MUST validate that `raindex` is a trusted contract." The implementation does **not** validate the `raindex` parameter -- it accepts any address. This is a documentation accuracy issue; the implementation's design intentionally delegates trust to the caller (as noted in pass 1, finding A02-3). The interface doc is misleading relative to this implementation's behavior. - -### `onTakeOrders2` (line 78) -Uses `@inheritdoc IRaindexV6OrderTaker`. The interface at `lib/rain.raindex.interface/src/interface/IRaindexV6OrderTaker.sol` provides thorough documentation: -- `@notice` describes callback semantics. -- All five parameters (`inputToken`, `outputToken`, `inputAmountSent`, `totalOutputAmount`, `takeOrdersData`) are documented with `@param`. -- The interface states "Implementations MUST validate that `msg.sender` is the trusted Raindex contract." - -The base implementation is an empty body with no access control. This contradicts the MUST requirement in the interface doc (also raised in pass 1, A02-1). There is no local `@dev` comment explaining this design decision. - -### Constructor (line 40) -No NatSpec. Delegates entirely to `OrderBookV6ArbCommon(config)`. A `@param config` tag would be useful but the constructor is simple passthrough so this is minor. - -## Findings - -### A02-P3-1 [LOW] Contract-level NatSpec missing (`@title` / `@notice`) - -**Location:** Line 31 - -The `OrderBookV6ArbOrderTaker` contract has no `@title` or `@notice` NatSpec tag. For an abstract contract that serves as the base for all order-taker arb strategies (GenericPool, RouteProcessor), a contract-level summary is important for discoverability and for automated documentation generators (e.g., `forge doc`). Every other abstract contract in the `src/abstract/` directory should document its purpose at the contract level. - -### A02-P3-2 [LOW] Typo in `BEFORE_ARB_SOURCE_INDEX` doc comment: "evaluabled" - -**Location:** Line 27 - -The `@dev` comment reads: - -``` -/// @dev "Before arb" is evaluabled before the arb is executed. -``` - -"evaluabled" is not a word. This should be "evaluated". The same constant is also defined in `OrderBookV6ArbCommon.sol` (line 32) with the correct wording "evaluated". This is a duplicate constant (flagged in pass 1, A02-2) with a degraded doc comment. - -### A02-P3-3 [LOW] `onTakeOrders2` empty body contradicts interface MUST requirement without explanation - -**Location:** Line 78 - -The `IRaindexV6OrderTaker` interface doc states: "Implementations MUST validate that `msg.sender` is the trusted Raindex contract." The base implementation is an empty no-op with no access control. There is no `@dev` comment explaining why this MUST requirement is intentionally not satisfied. A developer reading the interface and then the implementation would reasonably conclude this is a bug. A local `@dev` note should explain the design rationale (the contract holds no value between operations; the caller controls which orderbook is used). - -### A02-P3-4 [INFO] Documentation for error `NonZeroBeforeArbInputs` describes a dead code path - -**Location:** Lines 24-25 - -The error `NonZeroBeforeArbInputs(uint256 inputs)` is documented as "Thrown when 'before arb' wants inputs that we don't have" but is never used anywhere in this contract or any contract in the repository that inherits from it. The documented behavior cannot occur. This is consistent with pass 1 finding A02-2 (unused error). If the error is removed, the doc goes with it; if it is kept, the doc should note it is reserved for future use. - -### A02-P3-5 [INFO] `arb5` implementation does not satisfy interface's "MUST validate `raindex`" requirement - -**Location:** Line 49, interface line 15 - -The `IRaindexV6ArbOrderTaker` interface states "Implementations MUST validate that `raindex` is a trusted contract." The implementation does not perform any validation on the `orderBook` parameter. This is by design (the caller bears the risk), but the `@inheritdoc` tag imports the MUST language without qualification. A local `@dev` note clarifying the design choice would prevent confusion. - -### A02-P3-6 [INFO] Suppressed return values on line 65 lack explanatory comment - -**Location:** Line 65 - -```solidity -(totalTakerInput, totalTakerOutput); -``` - -This bare expression suppresses "unused variable" warnings for the return values of `takeOrders4`. There is no comment explaining why these values are intentionally discarded. A brief `// Return values intentionally unused.` comment would improve readability. diff --git a/audit/2026-03-13-01/pass3/OrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass3/OrderBookV6FlashBorrower.md deleted file mode 100644 index c9dca3837d..0000000000 --- a/audit/2026-03-13-01/pass3/OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,228 +0,0 @@ -# Pass 3: Documentation -- OrderBookV6FlashBorrower.sol - -**Agent:** A03 -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence of Thorough Reading - -### Contract Name -`OrderBookV6FlashBorrower` (abstract contract, line 62) - -### Inheritance -- `IERC3156FlashBorrower` (ERC-3156 flash borrower interface) -- `ReentrancyGuard` (OpenZeppelin reentrancy guard) -- `ERC165` (OpenZeppelin ERC-165 introspection) -- `OrderBookV6ArbCommon` (shared arb base with task validation) - -### Functions (with line numbers) -| Function | Line | Visibility | Documentation | -|----------|------|-----------|---------------| -| `constructor(OrderBookV6ArbConfig)` | 66 | N/A (constructor) | None | -| `supportsInterface(bytes4)` | 69 | public view virtual override | `@inheritdoc IERC165` | -| `_exchange(TakeOrdersConfigV5, bytes)` | 82 | internal virtual | Inline NatSpec (lines 73-80) | -| `onFlashLoan(address, address, uint256, uint256, bytes)` | 85 | external | `@inheritdoc IERC3156FlashBorrower` | -| `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` | 130 | external payable | Inline NatSpec (lines 109-129) | - -### Types / Errors / Constants -| Kind | Name | Line | Documentation | -|------|------|------|---------------| -| error | `BadInitiator(address badInitiator)` | 24 | NatSpec line 22-23 | -| error | `FlashLoanFailed()` | 27 | NatSpec line 26 | -| error | `SwapFailed()` | 30 | NatSpec line 29 | - -### Imports -Lines 5-20: 16 import statements. Several unused (see Pass 1 finding A03-4). - ---- - -## Documentation Audit - -### 1. Contract-level NatSpec (lines 32-61) - -**Title tag (line 32):** -``` -/// @title OrderBookV5FlashBorrower -``` - -The `@title` says "OrderBookV5FlashBorrower" but the actual contract declared on line 62 is `OrderBookV6FlashBorrower`. This is a stale copy-paste from a previous version. Identified in Pass 1 as A03-5 (INFO). Elevated here due to potential for confusion during integration or auditing. - -**`@notice` tag:** Missing. The text starting on line 33 has no `@notice` tag; it reads as freeform NatSpec. While Solidity NatSpec treats the first `///` block after `@title` as implicit `@notice`, this is informal. The description is otherwise accurate and thorough: it explains the flash-loan-based arbitrage pattern with a concrete DAI/USDT example (lines 37-51), and describes the minimal proxy cloning model with access gating (lines 53-61). - -**Accuracy issues in the example (lines 37-51):** -- Line 42: `IORatio = 1.01e18` -- The V6 orderbook uses Rain floating point (`Float`), not `1.01e18` fixed-point. The example uses fixed-point notation that reflects the V4/V5 era. This is misleading for V6. -- Line 43: `Order amount = 100e18` -- Same issue; V6 uses `Float` for amounts. -- Line 48: "Flash loan 100 USDT from `Orderbook`" -- The contract name is `OrderBook` (capital B) elsewhere in the codebase (e.g., `OrderBookV6ArbConfig.orderBook`). Minor inconsistency. -- The example is pedagogically correct (the arbitrage flow is accurately described) but the numeric notation is outdated. - -**Reference to `OrderBookFlashBorrower` (line 46):** -``` -/// The `OrderBookFlashBorrower` can: -``` -This references a class name that does not exist. It should be `OrderBookV6FlashBorrower`. Another stale reference. - -### 2. `constructor` (line 66) - -No NatSpec. Constructors with parameters should document them. The parameter `config` is of type `OrderBookV6ArbConfig` which is documented in `OrderBookV6ArbCommon.sol` (lines 16-25). The constructor is a single-line passthrough, so the omission is low impact but technically incomplete. - -### 3. `supportsInterface` (line 69) - -Uses `@inheritdoc IERC165`. Appropriate -- the function overrides ERC165 and the inherited documentation from the interface is sufficient. No issues. - -### 4. `_exchange` (lines 73-82) - -Documentation (lines 73-80): -``` -/// Hook that inheriting contracts MUST implement in order to achieve -/// anything other than raising the ambient temperature of the room. -/// `_exchange` is responsible for converting the flash loaned assets into -/// the assets required to fill the orders. -``` - -**Parameter documentation:** -- `@param takeOrders` -- "As per `arb`." This is a forward reference to `arb4` (the only `arb`-like function). Acceptable but could be more specific. -- `@param exchangeData` -- "As per `arb`." Same forward reference. -- No `@return` needed (void function). - -**Accuracy:** The description is accurate. The function body is empty (`{}`) which is correct for a virtual hook. - -**Issue:** The comment says "MUST implement" but the function has a default empty body (`internal virtual {}`), so inheriting contracts are not forced to implement it -- they can silently do nothing. The word "MUST" implies a compile-time requirement, but this is a runtime expectation only. - -### 5. `onFlashLoan` (line 84-107) - -Uses `@inheritdoc IERC3156FlashBorrower`. The inherited documentation from `IERC3156FlashBorrower` (in the interface file) says: -``` -@dev Receive a flash loan. -@param initiator The initiator of the loan. -@param token The loan currency. -@param amount The amount of tokens lent. -@param fee The additional amount of tokens to repay. -@param data Arbitrary data structure, intended to contain user-defined parameters. -@return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" -``` - -The function signature on line 85 uses unnamed parameters for `token`, `amount`, and `fee`: -```solidity -function onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data) -``` - -This means the inherited `@param` tags for `token`, `amount`, and `fee` do not match any named parameter. Tooling like Etherscan and documentation generators may produce confusing output. The parameters are deliberately unnamed because they are not used in the function body, which is valid Solidity but creates a documentation mismatch. - -**Inline comments (lines 86-106):** -- Line 86-89: "As per reference implementation" -- refers to the ERC3156 reference implementation. Accurate. -- Line 94-96: Correctly describes the `_exchange` dispatch. -- Line 98-104: "At this point `exchange` should have sent the tokens..." -- refers to `exchange` (without underscore) but the actual function is `_exchange`. Minor stale reference. -- Line 103: `IRaindexV6(msg.sender).takeOrders4(takeOrders)` -- the comment does not explain why `msg.sender` is treated as the orderbook. In a correctly functioning flow, `msg.sender` is the flash lender (orderbook), but there is no validation of this (as noted in Pass 1 finding A03-1). -- Line 104: `(totalInput, totalOutput);` -- unused return values are silenced. No documentation explains why these are discarded. - -### 6. `arb4` (lines 109-165) - -**Function-level NatSpec (lines 109-129):** -The documentation is structured in three paragraphs describing the arb flow: -1. Access gate evaluation (lines 110-115) -2. Flash loan + exchange (lines 117-119) -3. Order taking + profit (lines 121-122) - -**Parameter documentation:** -- `@param takeOrders` (line 124): "As per `IOrderBookV5.takeOrders3`." This is a **stale reference**. The contract uses `IRaindexV6.takeOrders4` (line 103). There is no `IOrderBookV5` or `takeOrders3` in the current codebase. -- `@param exchangeData` (lines 125-129): Well documented. However, the example reference to "`GenericPoolOrderBookV5FlashBorrower`" (line 128) is **stale** -- the current concrete implementation is `GenericPoolOrderBookV6FlashBorrower`. -- `@param orderBook` -- **Missing**. The first parameter `IRaindexV6 orderBook` has no `@param` tag. -- `@param task` -- **Missing**. The fourth parameter `TaskV2 calldata task` has no `@param` tag. The task controls post-arb evaluation and is validated by the `onlyValidTask` modifier -- this should be documented. - -**Return values:** None (the function is `void`). No `@return` needed. - -**Inline comments (lines 136-164):** -- Line 136-139: Correctly documents the early revert for zero orders. -- Line 141-142: Correctly documents the encoding for flash loan callback. -- Line 143-146: Correctly documents the token resolution logic. -- Line 151-153: "We can't repay more than the minimum that the orders are going to give us" -- This comment describes the flash loan amount rationale but does not explain the decimal conversion. As noted in Pass 1 finding A03-3, the decimals used here (`inputDecimals`) may be wrong. -- Line 155-157: Correctly describes the flash loan dispatch. - ---- - -## Findings - -### A03-P3-1 [LOW] Stale `@title` tag: "OrderBookV5FlashBorrower" instead of "OrderBookV6FlashBorrower" - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, line 32 - -**Description:** -The NatSpec `@title` reads `OrderBookV5FlashBorrower` but the contract is `OrderBookV6FlashBorrower`. This was noted as INFO in Pass 1 (A03-5) but the documentation pass confirms it is a documentation defect that could confuse integrators reading generated docs or ABI metadata. Additionally, line 46 references `OrderBookFlashBorrower` (no version number), another stale name. - -**Recommendation:** Change line 32 to `@title OrderBookV6FlashBorrower` and line 46 to `OrderBookV6FlashBorrower`. - ---- - -### A03-P3-2 [LOW] Stale interface and contract references in `arb4` param docs - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, lines 124, 128 - -**Description:** -- Line 124: `@param takeOrders As per IOrderBookV5.takeOrders3.` -- should reference `IRaindexV6.takeOrders4`. -- Line 128: references `GenericPoolOrderBookV5FlashBorrower` -- should be `GenericPoolOrderBookV6FlashBorrower`. - -These are version-bump copy-paste artifacts. They point readers to nonexistent interfaces and contracts. - -**Recommendation:** Update both references to their V6 equivalents. - ---- - -### A03-P3-3 [LOW] Missing `@param` documentation for `orderBook` and `task` in `arb4` - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, lines 130-135 - -**Description:** -The `arb4` function accepts four parameters but only two have `@param` tags: -- `orderBook` (type `IRaindexV6`) -- not documented. This is the target orderbook for the flash loan and order taking. -- `task` (type `TaskV2`) -- not documented. This controls the post-arb evaluation via `onlyValidTask` modifier and `finalizeArb`. - -Both parameters are important for callers to understand the function's behavior. - -**Recommendation:** Add `@param orderBook` and `@param task` tags. - ---- - -### A03-P3-4 [INFO] Inline comment refers to `exchange` instead of `_exchange` - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, line 98 - -**Description:** -The comment says `exchange should have sent the tokens` but the actual function name is `_exchange` (with underscore prefix). Minor naming inconsistency. - -**Recommendation:** Change "exchange" to "`_exchange`" in the comment. - ---- - -### A03-P3-5 [INFO] `_exchange` docs say "MUST implement" but function has default empty body - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, line 73 - -**Description:** -The NatSpec says inheriting contracts "MUST implement" `_exchange`, but the function is `internal virtual {}` with an empty default body. Inheriting contracts can silently skip implementation. The documentation implies a stronger contract than the code enforces. - -**Recommendation:** Reword to "SHOULD override" or "is expected to override" to match the actual enforcement level, or make the function `abstract` (remove the body) if the intent is to require implementation. - ---- - -### A03-P3-6 [INFO] Numeric notation in example uses fixed-point (`e18`) instead of Rain `Float` - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol`, lines 42-43 - -**Description:** -The NatSpec example uses `1.01e18` and `100e18` notation for IO ratios and amounts. In V6, the orderbook uses Rain floating point (`Float`) for all amounts and ratios, not fixed-point `e18` values. The example is pedagogically clear but technically inaccurate for the current version. - -**Recommendation:** Update the example to use `Float` notation or add a note that the numbers are simplified for illustration. - ---- - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A03-P3-1 | LOW | Stale `@title` tag: V5 instead of V6 | -| A03-P3-2 | LOW | Stale interface/contract references in `arb4` param docs | -| A03-P3-3 | LOW | Missing `@param` for `orderBook` and `task` in `arb4` | -| A03-P3-4 | INFO | Inline comment refers to `exchange` instead of `_exchange` | -| A03-P3-5 | INFO | `_exchange` docs say "MUST" but body allows silent no-op | -| A03-P3-6 | INFO | Numeric notation uses fixed-point instead of Float | - -Overall documentation quality is moderate. The contract-level description is detailed and the arbitrage flow example is helpful. However, the documentation has not been fully updated since the V5-to-V6 migration: the title, interface references, contract name references, and numeric notation all retain V5-era artifacts. The `arb4` function is missing `@param` tags for two of its four parameters, and `onFlashLoan` has unnamed parameters that conflict with inherited `@param` tags. diff --git a/audit/2026-03-13-01/pass3/OrderBookV6FlashLender.md b/audit/2026-03-13-01/pass3/OrderBookV6FlashLender.md deleted file mode 100644 index 53aa6a3202..0000000000 --- a/audit/2026-03-13-01/pass3/OrderBookV6FlashLender.md +++ /dev/null @@ -1,77 +0,0 @@ -# Pass 3: Documentation -- OrderBookV6FlashLender.sol - -**Agent:** A04 -**File:** `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence of Thorough Reading - -- **Contract:** `OrderBookV6FlashLender` (abstract, line 29), inherits `IERC3156FlashLender`, `ERC165` -- **Imports:** `ERC165`, `IERC165` (OZ), `IERC20` (OZ), `SafeERC20` (OZ), `IERC3156FlashBorrower`, `ON_FLASH_LOAN_CALLBACK_SUCCESS`, `IERC3156FlashLender` -- **Error:** `FlashLenderCallbackFailed(bytes32 result)` (line 18) -- **Constant:** `FLASH_FEE = 0` (line 23, file-level) -- **Functions:** - - `supportsInterface(bytes4)` -- public view virtual override, line 33 - - `flashLoan(IERC3156FlashBorrower, address, uint256, bytes)` -- external override, line 38 - - `flashFee(address, uint256)` -- external pure override, line 70 - - `maxFlashLoan(address)` -- external view override, line 78 - -## Documentation Coverage - -### File-level - -| Item | Has NatSpec | Quality | -|------|-------------|---------| -| Error `FlashLenderCallbackFailed` | Yes (lines 15-17) | Good. Describes when thrown and documents the `result` parameter. | -| Constant `FLASH_FEE` | Yes (lines 20-22) | Good. `@dev` explains rationale for zero fee. | -| Contract `OrderBookV6FlashLender` | Yes (lines 25-28) | Good. `@title` and `@notice` identify purpose and reference the EIP-3156 spec. | - -### Function-level - -| Function | Has NatSpec | Notes | -|----------|-------------|-------| -| `supportsInterface` (line 33) | `@inheritdoc IERC165` | Adequate -- inherited doc is sufficient for a standard override. | -| `flashLoan` (line 38) | `@inheritdoc IERC3156FlashLender` | Adequate -- inherited doc covers params and return. Inline comment (lines 50-62) adds valuable security rationale for the `safeTransferFrom` pattern and Slither suppression. | -| `flashFee` (line 70) | `@inheritdoc IERC3156FlashLender` | Acceptable, but see A04-P3-2 below regarding unnamed parameters. | -| `maxFlashLoan` (line 78) | Custom NatSpec (lines 74-76) + `@inheritdoc` (line 77) | Inaccurate -- see A04-P3-1 below. | - -## Findings - -### A04-P3-1 [LOW] Misleading NatSpec on `maxFlashLoan` -- claims active-debt guard that does not exist - -**Location:** Lines 74-76 - -The NatSpec states: - -> If there is an active debt then loans are disabled so the max becomes `0` until after repayment. - -The actual implementation (line 79) simply returns `IERC20(token).balanceOf(address(this))`. There is no active-debt tracking, no boolean flag, and no logic that returns `0` during an outstanding loan. A `grep` for "active.*debt", "flashLoanActive", and related patterns across the entire `src/` tree returns zero matches beyond this comment itself. - -This is the same finding as A04-1 from Pass 1, now confirmed from a documentation-accuracy perspective. The comment is not merely aspirational -- it describes behaviour that a reader would reasonably expect the code to enforce but that does not exist at all. This could mislead integrators into believing re-entrant flash loans are impossible when they are not. - -**Recommendation:** Remove the sentence about active debt entirely. The accurate description is just the first sentence: there is no limit other than the current token balance held by the contract. Alternatively, if active-debt tracking is desired functionality, implement it. - -### A04-P3-2 [INFO] `flashFee` drops parameter names, reducing documentation linkage - -**Location:** Line 70 - -```solidity -function flashFee(address, uint256) external pure override returns (uint256) { -``` - -The interface (`IERC3156FlashLender`) documents `@param token` and `@param amount`. The implementation drops both parameter names. While valid Solidity (the parameters are unused and the fee is constant), the unnamed parameters make it harder for readers to correlate `@inheritdoc` documentation with the actual signature. This is purely informational since `@inheritdoc` still renders correctly in tooling. - -### A04-P3-3 [INFO] No `@param` / `@return` on the custom `maxFlashLoan` comment - -**Location:** Lines 74-77 - -The custom NatSpec block for `maxFlashLoan` does not include `@param token` or `@return` tags. The `@inheritdoc` on line 77 pulls these from the interface, so they are technically present, but the custom comment block preceding `@inheritdoc` adds prose without structured parameter documentation. This is standard practice and not a defect, but noting for completeness. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A04-P3-1 | LOW | Misleading NatSpec on `maxFlashLoan` claims active-debt guard that does not exist | -| A04-P3-2 | INFO | `flashFee` drops parameter names, reducing documentation linkage | -| A04-P3-3 | INFO | No `@param`/`@return` on custom `maxFlashLoan` comment | - -One LOW finding (A04-P3-1) requires a fix file. The two INFO findings are cosmetic and do not warrant fix files. diff --git a/audit/2026-03-13-01/pass3/OrderBookV6SubParser.md b/audit/2026-03-13-01/pass3/OrderBookV6SubParser.md deleted file mode 100644 index 0f7b20aa51..0000000000 --- a/audit/2026-03-13-01/pass3/OrderBookV6SubParser.md +++ /dev/null @@ -1,117 +0,0 @@ -# Pass 3: Documentation -- OrderBookV6SubParser.sol - -**Agent:** A09 -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract - -- `OrderBookV6SubParser` (line 71) -- inherits `BaseRainterpreterSubParser` - -### Imports (lines 5-68) - -- `LibParseOperand`, `BaseRainterpreterSubParser`, `OperandV2`, `IParserToolingV1` from rain.interpreter -- `LibConvert` from rain.lib.typecast -- `BadDynamicLength` from rain.interpreter (unused in this file -- imported but never referenced) -- `LibExternOpContextSender` from rain.interpreter (unused in this file -- imported but never referenced) -- `LibUint256Matrix` from rain.solmem -- All `LibOrderBookSubParser` symbols and constants from `../../lib/LibOrderBookSubParser.sol` -- All context constants from `../../lib/LibOrderBook.sol` -- Generated constants from `../../generated/OrderBookV6SubParser.pointers.sol` -- `IDescribedByMetaV1` from rain.metadata - -### Using Declarations - -- `using LibUint256Matrix for uint256[][];` (line 72) - -### Functions (with line numbers) - -| # | Function | Visibility | Mutability | Lines | NatSpec | -|---|----------|-----------|------------|-------|---------| -| 1 | `describedByMetaV1()` | external | pure | 75-77 | `@inheritdoc IDescribedByMetaV1` | -| 2 | `subParserParseMeta()` | internal | pure virtual override | 80-82 | `@inheritdoc BaseRainterpreterSubParser` | -| 3 | `subParserWordParsers()` | internal | pure virtual override | 85-87 | `@inheritdoc BaseRainterpreterSubParser` | -| 4 | `subParserOperandHandlers()` | internal | pure virtual override | 90-92 | `@inheritdoc BaseRainterpreterSubParser` | -| 5 | `buildLiteralParserFunctionPointers()` | external | pure | 95-97 | `@inheritdoc IParserToolingV1` | -| 6 | `buildOperandHandlerFunctionPointers()` | external | pure | 100-184 | `@inheritdoc IParserToolingV1` | -| 7 | `buildSubParserWordParsers()` | external | pure | 186-306 | **None** | - -### Types, Errors, Constants - -- No custom types, errors, or constants are declared directly in this contract. All constants are imported from `LibOrderBook.sol`, `LibOrderBookSubParser.sol`, and the generated pointers file. - -### Imported but Unused Symbols - -- `BadDynamicLength` (line 12) -- imported but never used in this file -- `LibExternOpContextSender` (line 13) -- imported but never used in this file - -## Documentation Audit - -### 1. Contract-Level Documentation - -**Finding: No contract-level NatSpec.** - -The contract `OrderBookV6SubParser` has no `@title`, `@notice`, or `@dev` documentation. The base class `BaseRainterpreterSubParser` has a detailed doc comment explaining the subparser workflow, but the concrete contract itself has no documentation explaining: -- What it is (an OrderBook-specific sub parser for Rainlang) -- What context words it provides (order clearer, orderbook, order hash, owner, counterparty, vault I/O, calculations, signed context, deposit/withdraw context) -- How it relates to the orderbook's context grid - -### 2. Function-Level Documentation - -#### Functions with `@inheritdoc` (adequate) - -Functions 1-6 all use `@inheritdoc` to reference their parent interface or base class. The parent documentation is present and adequate: - -- `describedByMetaV1()` -- `@inheritdoc IDescribedByMetaV1`: parent has `@return` tag. -- `subParserParseMeta()` -- `@inheritdoc BaseRainterpreterSubParser`: parent has brief description. -- `subParserWordParsers()` -- `@inheritdoc BaseRainterpreterSubParser`: parent has brief description. -- `subParserOperandHandlers()` -- `@inheritdoc BaseRainterpreterSubParser`: parent has brief description. -- `buildLiteralParserFunctionPointers()` -- `@inheritdoc IParserToolingV1`: parent has detailed description. -- `buildOperandHandlerFunctionPointers()` -- `@inheritdoc IParserToolingV1`: parent has detailed description. - -#### Function without documentation - -**Finding P3-A09-01 [LOW]: `buildSubParserWordParsers()` (line 186) has no NatSpec.** - -This is an `external pure` function that implements `ISubParserToolingV1.buildSubParserWordParsers()`. It is the largest function in the contract (120 lines) and constructs the complete word parser function pointer table for all context columns including deposit and withdraw contexts. It should have `@inheritdoc ISubParserToolingV1` to link to the interface documentation, consistent with how all other public/external functions in the contract are documented. - -### 3. Inline Comment Accuracy - -#### `buildOperandHandlerFunctionPointers()` (lines 100-184) - -- Lines 101-104: Comments say "Add 2 columns for signers and signed context start. Add 1 for deposit context. Add 1 for withdraw context." This matches the `CONTEXT_COLUMNS + 2 + 1 + 1` calculation on line 105. **Accurate.** -- The handler assignments (lines 109-176) correctly match each context constant to its operand handler type: - - Most use `handleOperandDisallowed` (no operands allowed). - - `contextSignersHandlers` uses `handleOperandSingleFullNoDefault` (line 142) -- signers takes a signer index operand. - - `contextSignedContextHandlers` uses `handleOperandDoublePerByteNoDefault` (line 147) -- signed context takes column and row as two bytes. -- **Accurate.** - -#### `buildSubParserWordParsers()` (lines 186-306) - -- Lines 187-194: Same comment as `buildOperandHandlerFunctionPointers` about column count. Matches `CONTEXT_COLUMNS + 2 + 1 + 1` on line 194. **Accurate.** -- Lines 267, 283: Inline comments "// Deposits" and "// Withdraws" correctly annotate the sections. **Accurate.** - -### 4. Documentation Accuracy vs Implementation - -- `describedByMetaV1()` is declared `pure` while the interface declares it `view`. This is valid Solidity (pure is a stricter guarantee than view), so the `@inheritdoc` is accurate. -- `buildLiteralParserFunctionPointers()` returns empty bytes (`""`), consistent with the contract having no literal parsers. The inherited doc from `IParserToolingV1` is general-purpose and does not claim specific behavior, so this is accurate. - -### 5. Unused Imports - -**Finding P3-A09-02 [INFO]: Two unused imports.** - -- `BadDynamicLength` (line 12) is imported from `rain.interpreter/error/ErrOpList.sol` but never referenced in the contract. -- `LibExternOpContextSender` (line 13) is imported from `rain.interpreter/lib/extern/reference/op/LibExternOpContextSender.sol` but never referenced. - -These are not documentation issues per se, but they add noise and could mislead readers about the contract's dependencies. - -## Summary of Findings - -| ID | Severity | Description | -|----|----------|-------------| -| P3-A09-01 | LOW | `buildSubParserWordParsers()` has no NatSpec documentation; should use `@inheritdoc ISubParserToolingV1` | -| P3-A09-02 | INFO | Two unused imports: `BadDynamicLength` and `LibExternOpContextSender` | - -No contract-level NatSpec exists, but this is consistent with the pattern used by other concrete contracts in the codebase that rely on base class documentation. The single missing `@inheritdoc` on `buildSubParserWordParsers` is a clear omission since every other function in the contract follows this pattern. diff --git a/audit/2026-03-13-01/pass3/RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass3/RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index dbb4032a5b..0000000000 --- a/audit/2026-03-13-01/pass3/RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,132 +0,0 @@ -# Pass 3: Documentation -- RouteProcessorOrderBookV6ArbOrderTaker.sol - -**Agent:** A07 -**File:** `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Name -`RouteProcessorOrderBookV6ArbOrderTaker` (line 14), inherits `OrderBookV6ArbOrderTaker`. - -### Functions (with line numbers) -| Function | Visibility | Line | -|---|---|---| -| `constructor(OrderBookV6ArbConfig memory config)` | public | 20 | -| `onTakeOrders2(address, address, Float, Float, bytes calldata)` | public virtual override | 26 | -| `fallback()` | external | 52 | - -### State Variables -| Variable | Type | Line | -|---|---|---| -| `iRouteProcessor` | `IRouteProcessor public immutable` | 18 | - -### Types, Errors, Constants -None defined locally. All inherited from parent contracts. - -### Imports (lines 5-12) -- `IRouteProcessor` (line 5) -- `IERC20` (line 6) -- `SafeERC20` (line 7) -- `Address` (line 8) -- `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float` (line 10) -- `LibDecimalFloat` (line 11) -- `IERC20Metadata` (line 12) - ---- - -## Documentation Inventory - -### Contract-Level Documentation -**Missing.** No `@title`, `@notice`, or `@dev` NatSpec on the contract declaration at line 14. The contract integrates with SushiSwap's RouteProcessor for executing token swaps, which is a non-obvious external dependency that should be documented. - -### Function Documentation - -#### `constructor` (line 20) -No NatSpec. The constructor decodes `config.implementationData` as `(address routeProcessor)` and stores it as `iRouteProcessor`. This decode expectation is undocumented -- callers must read the source to know what `implementationData` should contain. - -#### `onTakeOrders2` (line 26) -Has `/// @inheritdoc OrderBookV6ArbOrderTaker` which chains to the interface docs in `IRaindexV6OrderTaker`. The interface provides parameter-level documentation. - -**Issue:** The implementation has substantial logic not described by the inherited docs: -- `takeOrdersData` is decoded as `(bytes route)` -- the SushiSwap route data -- `inputAmountSent` is converted from Float to fixed-decimal using `LibDecimalFloat.toFixedDecimalLossy` -- The lossy flag for `inputAmountSent` is silently discarded (line 38) -- `totalOutputAmount` is also converted, and if lossy, `outputTokenAmount` is incremented by 1 (lines 39-43) to ensure the minimum output is met -- The route processor is called with these computed values -- `amountOut` from the route processor is discarded (line 48) - -None of these implementation-specific behaviors are documented. - -#### `iRouteProcessor` (line 18) -No NatSpec on the public immutable state variable. Should document that this is the SushiSwap RouteProcessor address set at construction time. - -#### `fallback` (line 52) -Has `/// Allow receiving gas.` -- same misleading comment as the sibling contracts. Not payable, cannot receive ETH. Identified as A07-3 (INFO) in Pass 1. - ---- - -## Findings - -### A07-P3-1 [LOW] Missing contract-level NatSpec documentation - -**Location:** Line 14 - -**Description:** -`RouteProcessorOrderBookV6ArbOrderTaker` has no `@title`, `@notice`, or `@dev` NatSpec. This contract integrates with SushiSwap's `IRouteProcessor`, a specific external protocol dependency. Integrators need to know: -- That this contract is specifically for SushiSwap RouteProcessor-based arbitrage -- That `config.implementationData` must encode `(address routeProcessor)` -- That `takeOrdersData` must encode `(bytes route)` where `route` is a SushiSwap route - -None of this is documented. Compare with `GenericPoolOrderBookV6FlashBorrower` which has thorough contract-level docs. - -**Recommendation:** Add `@title` and `@notice` block, e.g.: -``` -/// @title RouteProcessorOrderBookV6ArbOrderTaker -/// @notice Arb order taker that uses SushiSwap's RouteProcessor for token -/// swaps. The `takeOrdersData` is decoded as a single `bytes route` parameter -/// that is passed directly to `IRouteProcessor.processRoute`. The constructor -/// expects `implementationData` to encode `(address routeProcessor)`. -``` - -### A07-P3-2 [LOW] Undocumented lossy conversion and silent discard of precision flag - -**Location:** Lines 36-38 - -**Description:** -The conversion of `inputAmountSent` from Float to fixed-decimal is documented nowhere. More importantly, the `losslessInputAmount` boolean is silently discarded: -```solidity -(uint256 inputTokenAmount, bool losslessInputAmount) = - LibDecimalFloat.toFixedDecimalLossy(inputAmountSent, IERC20Metadata(inputToken).decimals()); -(losslessInputAmount); -``` - -In contrast, `totalOutputAmount`'s lossy flag IS checked and handled (incrementing `outputTokenAmount` if lossy). The asymmetric handling of these two precision flags is a design decision that deserves a `@dev` comment explaining why input precision loss is acceptable but output precision loss requires compensation. - -This was noted as A07-2 (INFO) in Pass 1 from a correctness angle. From a documentation perspective, the lack of any comment explaining this asymmetry makes the code harder to audit and maintain. - -**Recommendation:** Add a `@dev` comment explaining the rationale, e.g.: -``` -// Input amount precision loss is acceptable because it only reduces -// the amount sent to the route processor (we sell slightly less). -// Output amount precision loss is NOT acceptable because it could -// reduce the minimum output below the order's requirement, so we -// round up by 1 to compensate. -``` - -### A07-P3-3 [INFO] Misleading fallback comment (confirmed from Pass 1) - -**Location:** Lines 51-52 - -**Description:** -Same issue as A05-P3-2 and A06-P3-1. The `/// Allow receiving gas.` comment on the non-payable `fallback()` is factually incorrect. Previously identified as A07-3 in Pass 1. - -### A07-P3-4 [INFO] No NatSpec on public immutable `iRouteProcessor` - -**Location:** Line 18 - -**Description:** -The `iRouteProcessor` public immutable has no documentation. Readers must infer from context that this is the SushiSwap RouteProcessor address. A `@notice` or `@dev` comment would improve discoverability, e.g.: -``` -/// @notice The SushiSwap RouteProcessor used for token swaps during arb execution. -``` diff --git a/audit/2026-03-13-01/pass4/Deploy.md b/audit/2026-03-13-01/pass4/Deploy.md deleted file mode 100644 index b43b3555cf..0000000000 --- a/audit/2026-03-13-01/pass4/Deploy.md +++ /dev/null @@ -1,151 +0,0 @@ -# Pass 4: Code Quality -- Deploy.sol - -**Agent:** A15 -**File:** `script/Deploy.sol` - -## Evidence of Thorough Reading - -**Contract name:** `Deploy` (inherits `Script` from forge-std), lines 46-176. - -**Line-by-line inventory:** - -| Element | Lines | Kind | -|---|---|---| -| License + pragma | 1-3 | `=0.8.25` (matches all `script/*.sol` files) | -| Imports | 5-22 | 18 statements, 12 unique source files | -| `DEPLOYMENT_SUITE_ALL` | 24 | `bytes32` file-level constant | -| `DEPLOYMENT_SUITE_RAINDEX` | 25 | `bytes32` file-level constant | -| `DEPLOYMENT_SUITE_SUBPARSER` | 26 | `bytes32` file-level constant | -| `DEPLOYMENT_SUITE_ROUTE_PROCESSOR` | 27 | `bytes32` file-level constant | -| `DEPLOYMENT_SUITE_ARB` | 28 | `bytes32` file-level constant | -| `ROUTE_PROCESSOR_4_CREATION_CODE` | 38-39 | `bytes` file-level constant (~16 KB hex literal) | -| `ROUTE_PROCESSOR_4_BYTECODE_HASH` | 41-42 | `bytes32` file-level constant | -| `BadRouteProcessor` error | 44 | file-level error | -| `sDepCodeHashes` | 50 | `mapping(string => mapping(address => bytes32))` state var | -| `deployRouter()` | 52-59 | `internal` function, uses inline assembly | -| `run()` | 61-175 | `external` function, main entry point | - -**Import analysis (18 imports across lines 5-22):** -- Line 5: `Script, console2` from `forge-std/Script.sol` -- Line 6: `OrderBookV6, EvaluableV4, TaskV2, SignedContextV1` from `src/concrete/ob/OrderBookV6.sol` -- Line 7: `OrderBookV6SubParser` from `src/concrete/parser/OrderBookV6SubParser.sol` -- Lines 8-11: Arb contracts and config struct from `src/concrete/arb/*.sol` and `src/abstract/OrderBookV6ArbCommon.sol` -- Lines 12-14: Metadata libraries from `rain.metadata/` -- Lines 15-16: Float deploy and TOFU decimals from `rain.math.float/` and `rain.tofu.erc20-decimals/` -- Lines 17-18: Interpreter interfaces from `rain.interpreter.interface/` -- Line 19: `LibRainDeploy` from `rain.deploy/` -- Lines 20-22: Internal deploy library and generated pointer files from `src/` - -**Assembly blocks:** Two -- line 55 (`"memory-safe"` annotated) and line 130 (bare `assembly {}`). - -## Build Check - -Unable to run `forge build` in this session (Bash tool not available). Build warnings could not be verified. The unused `OrderBookV6` import (finding A15-P4-1) may produce a compiler warning depending on forge-lint / solc configuration. - -## Bare `src/` Import Scan - -Searched all `src/`, `test/`, and `script/` directories for bare `src/` import paths. - -**Results in `src/`:** Zero matches. All intra-source imports use relative paths (e.g., `../../lib/`, `../lib/`). - -**Results in `script/`:** 14 matches across `Deploy.sol` and `BuildPointers.sol`. All use `src/` paths to import from the source tree, which is the standard Foundry convention for cross-directory imports from `script/` and `test/`. - -**Results in `test/`:** 50+ matches across test utilities and test files, all following the same Foundry convention. - -**Assessment:** The `src/` import paths from `script/` and `test/` are idiomatic Foundry. No bare `src/` paths exist within `src/` itself. No issue. - -## Findings - -### A15-P4-1 [LOW] Unused import: `OrderBookV6` type is imported but never used - -**Location:** Line 6 - -```solidity -import {OrderBookV6, EvaluableV4, TaskV2, SignedContextV1} from "src/concrete/ob/OrderBookV6.sol"; -``` - -The `OrderBookV6` type is imported but never referenced as a type in the file body. The only appearances of the string "OrderBookV6" beyond the import are: -- String literals in `console2.log` calls (lines 71, 95) -- these are literal strings, not type references. -- String literals passed to `LibRainDeploy.deployAndBroadcast` (lines 81, 105) -- also literal strings. -- Import path for the generated pointers file (line 21) -- a different import. - -The remaining symbols (`EvaluableV4`, `TaskV2`, `SignedContextV1`) are used in lines 143-168. - -### A15-P4-2 [LOW] `EvaluableV4`, `TaskV2`, `SignedContextV1` imported through a concrete contract rather than their canonical source - -**Location:** Line 6 - -These three types are imported from `src/concrete/ob/OrderBookV6.sol`, which itself re-exports them from `rain.raindex.interface/interface/IRaindexV6.sol`. Importing framework-level types through a concrete contract creates unnecessary coupling. If `OrderBookV6.sol` were to stop re-exporting one of these symbols, `Deploy.sol` would break even though the types remain available from their canonical source. - -The canonical import path used throughout the rest of the codebase is: -``` -import {EvaluableV4, TaskV2, SignedContextV1} from "rain.raindex.interface/interface/IRaindexV6.sol"; -``` - -### A15-P4-3 [LOW] Inconsistent `address()` cast on `raindex` variable - -**Location:** Lines 142, 153, 165 - -The `raindex` variable is declared as `address` (line 67). When passed to `OrderBookV6ArbConfig`, it is wrapped in a redundant `address()` cast on lines 142 and 153 (`address(raindex)`) but passed bare on line 165 (`raindex`). This is a style inconsistency within a single function across three structurally identical call sites. - -All three should use bare `raindex` since it is already `address`-typed. - -### A15-P4-4 [LOW] Missing `"memory-safe"` annotation on second assembly block - -**Location:** Line 130 - -```solidity -assembly { - routeProcessor4BytecodeHash := extcodehash(routeProcessor) -} -``` - -The first assembly block at line 55 correctly uses `assembly ("memory-safe")`. The second block at line 130 uses bare `assembly`. This block reads `extcodehash` from the stack and writes to a local variable without touching memory, so it qualifies as memory-safe. The inconsistency within the same file is a code quality issue, and the missing annotation can prevent the optimizer from making certain optimizations around the assembly block. - -### A15-P4-5 [LOW] Repeated `TaskV2`/`EvaluableV4` zero-value boilerplate across three deployment sites - -**Location:** Lines 140-149, 151-160, 163-172 - -The following pattern is copy-pasted three times with only the outer constructor and `implementationData` differing: - -```solidity -OrderBookV6ArbConfig( - address(raindex), - TaskV2({ - evaluable: EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex""), - signedContext: new SignedContextV1[](0) - }), - ... -) -``` - -Each instantiation constructs a zero/empty `TaskV2` with an empty `EvaluableV4`. This could be extracted to a local variable declared once: - -```solidity -TaskV2 memory emptyTask = TaskV2({ - evaluable: EvaluableV4(IInterpreterV4(address(0)), IInterpreterStoreV3(address(0)), hex""), - signedContext: new SignedContextV1[](0) -}); -``` - -This would reduce duplication, improve readability, and make it easier to change the default task configuration if needed. - -### A15-P4-6 [INFO] `console2` import is only used in deployment logging - -**Location:** Line 5 - -`console2` is imported alongside `Script` from forge-std and used only on lines 71 and 95 for `console2.log` deployment progress messages. This is fine for a deployment script but note that `console2.log` calls are no-ops at runtime -- they only produce output during `forge script` execution. If the import or log calls were removed, no behavior would change. This is informational only as deploy-script logging is standard practice. - -### A15-P4-7 [INFO] Pragma version `=0.8.25` is consistent across all script files - -All four files in `script/` use `pragma solidity =0.8.25`, matching the `solc` version in `foundry.toml`. Source files in `src/` use a mix of `=0.8.25` (concrete contracts, generated files) and `^0.8.19`/`^0.8.18`/`^0.8.25` (abstracts, libraries). This split is intentional and consistent: concrete/deployable contracts pin exact versions while reusable libraries allow compatible ranges. No issue. - -### A15-P4-8 [INFO] No commented-out code found - -Reviewed all comment lines. All are either license/SPDX headers, NatSpec documentation, or inline clarification comments (lines 111, 139, 162). No commented-out code is present. - -### A15-P4-9 [INFO] Two deployment string literals duplicate source paths - -**Location:** Lines 81, 105 - -The strings `"src/concrete/ob/OrderBookV6.sol:OrderBookV6"` and `"src/concrete/parser/OrderBookV6SubParser.sol:OrderBookV6SubParser"` are hardcoded source path references passed to `LibRainDeploy.deployAndBroadcast`. These are Foundry artifact identifiers and must match actual file paths, so hardcoding is the expected pattern. No issue, but noted as a maintenance concern: if files are moved, these strings must be updated manually. diff --git a/audit/2026-03-13-01/pass4/GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass4/GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 140020d7bc..0000000000 --- a/audit/2026-03-13-01/pass4/GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,96 +0,0 @@ -# Pass 4: Code Quality -- GenericPoolOrderBookV6ArbOrderTaker.sol - -**Agent:** A05 -**File:** `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Structure -- **License:** `LicenseRef-DCL-1.0` (line 1), copyright 2020 Rain Open Source Software Ltd (line 2) -- **Pragma:** `=0.8.25` (line 3) -- pinned, consistent with `foundry.toml` solc setting and all other concrete contracts -- **Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (line 11), inherits `OrderBookV6ArbOrderTaker` -- **Using declarations:** `SafeERC20 for IERC20` (line 12), `Address for address` (line 13) -- **Constructor:** line 15, passthrough to parent -- **`onTakeOrders2`:** lines 18-35, public virtual override, calls super, decodes `takeOrdersData` as `(address spender, address pool, bytes encodedFunctionCall)`, does forceApprove/call/revoke pattern -- **`fallback()`:** line 38, external, non-payable, empty body - -### Imports (lines 5-9) -| Import | Source | Used? | -|---|---|---| -| `IERC20` | `openzeppelin-contracts/contracts/token/ERC20/IERC20.sol` | Yes (line 29, 34 -- `IERC20(inputToken).forceApprove(...)`) | -| `SafeERC20` | `openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol` | Yes (line 12 -- `using SafeERC20 for IERC20`) | -| `Address` | `openzeppelin-contracts/contracts/utils/Address.sol` | Yes (line 13, 30 -- `pool.functionCallWithValue(...)`) | -| `OrderBookV6ArbOrderTaker` | `../../abstract/OrderBookV6ArbOrderTaker.sol` | Yes (line 11 -- inheritance, line 25 -- `super.onTakeOrders2`) | -| `OrderBookV6ArbConfig` | `../../abstract/OrderBookV6ArbOrderTaker.sol` | Yes (line 15 -- constructor parameter) | -| `Float` | `../../abstract/OrderBookV6ArbOrderTaker.sol` | Yes (lines 22-23 -- function parameters) | - -### Line-by-line observations -- Line 25: `super.onTakeOrders2(...)` -- delegates to parent which is a no-op body `{}`. This is an intentional extension point; calling super is correct for the override chain. -- Lines 31-33: `returnData` is assigned then consumed by `(returnData);` to suppress the "unused variable" compiler warning. This is a deliberate pattern, documented by the inline comment on lines 31-32. -- Line 30: `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -- forwards full ETH balance. This is the `Address` library being used via the `using` declaration. - ---- - -## Code Quality Review - -### 1. Style Consistency - -**Pragma:** `=0.8.25` is consistent with all other concrete contracts (`GenericPoolOrderBookV6FlashBorrower`, `RouteProcessorOrderBookV6ArbOrderTaker`, `OrderBookV6SubParser`, `OrderBookV6`). Abstract contracts use `^0.8.19` which is intentional (libraries are compatible with a range). - -**Import style:** Uses relative path `../../abstract/` for local imports and named remappings (`openzeppelin-contracts/`) for external deps. This is consistent with sibling contracts. - -**`using` declarations:** Both `SafeERC20` and `Address` are declared and used. No redundancy. - -**Variable naming:** `inputToken`, `outputToken`, `spender`, `pool`, `encodedFunctionCall` -- clear and descriptive. Consistent with the sibling `GenericPoolOrderBookV6FlashBorrower` which uses identical names. - -### 2. Leaky Abstractions - -No leaky abstractions detected. The contract is a thin concrete implementation of the `OrderBookV6ArbOrderTaker` template. The decode pattern `(spender, pool, encodedFunctionCall)` is self-contained in this contract. - -### 3. Commented-Out Code - -No commented-out code. The only inline comments are: -- Lines 31-32: explains why `returnData` is unused (intentional, not commented-out logic) -- Line 37: `/// Allow receiving gas.` (misleading but not commented-out code; already filed in prior passes) - -### 4. Build Warnings - -The `(returnData);` pattern on line 33 is the standard Solidity idiom for suppressing unused variable warnings. No build warnings expected from this file. - -### 5. Dependency Consistency - -All imports use the established remapping paths from `foundry.toml`. No bare `src/` imports. No imports from unexpected or inconsistent sources. - -### 6. Dead Code - -No dead code in this contract. All imports, using declarations, functions, and variables are used. - -### 7. Fallback Function - -The `fallback() external {}` on line 38 is not `payable`. As noted in prior passes, the comment is misleading. From a code quality standpoint, the fallback is an empty function with no purpose documented. If it exists to accept arbitrary calldata from pool callbacks, that is a valid purpose but should be documented. If it is vestigial, it adds surface area for no benefit. - ---- - -## Findings - -### A05-P4-1 [INFO] Redundant `super.onTakeOrders2` call to no-op parent - -**Location:** Line 25 - -**Description:** -The `onTakeOrders2` override calls `super.onTakeOrders2(inputToken, outputToken, inputAmountSent, totalOutputAmount, takeOrdersData)` but the parent `OrderBookV6ArbOrderTaker.onTakeOrders2` has an empty body `{}` (line 78 of `OrderBookV6ArbOrderTaker.sol`). The super call compiles to a no-op and wastes gas (albeit minimal -- mostly the cost of the function dispatch). - -This is a deliberate defensive pattern: if the parent ever adds logic, this override will correctly chain to it. From a pure code quality perspective this is fine, but it should be noted that the call currently does nothing. No fix recommended -- the defensive pattern is appropriate. - -### A05-P4-2 [INFO] No findings requiring fixes - -All imports are used, no dead code, no style inconsistencies, no bare `src/` imports, no commented-out code. The contract is clean and well-structured. Previous passes have already filed the substantive issues (missing NatSpec, misleading fallback comment, test gaps). - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A05-P4-1 | INFO | Redundant `super.onTakeOrders2` call to no-op parent | - -No LOW+ findings. No fix files needed for this contract in Pass 4. diff --git a/audit/2026-03-13-01/pass4/GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass4/GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index d2f718ebdc..0000000000 --- a/audit/2026-03-13-01/pass4/GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,128 +0,0 @@ -# Pass 4: Code Quality -- GenericPoolOrderBookV6FlashBorrower.sol - -**Agent:** A06 -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Structure -- **License:** `LicenseRef-DCL-1.0` (line 1), copyright 2020 Rain Open Source Software Ltd (line 2) -- **Pragma:** `=0.8.25` (line 3) -- pinned, consistent with all concrete contracts -- **Contract:** `GenericPoolOrderBookV6FlashBorrower` (line 27), inherits `OrderBookV6FlashBorrower` -- **NatSpec block:** lines 17-26, thorough contract-level documentation -- **Using declarations:** `SafeERC20 for IERC20` (line 28), `Address for address` (line 29) -- **Constructor:** line 31, passthrough to parent -- **`_exchange`:** lines 34-45, internal virtual override, decodes `exchangeData` as `(address spender, address pool, bytes encodedFunctionCall)`, reads `borrowedToken` from takeOrders, does forceApprove/call/revoke -- **`fallback()`:** line 48, external, non-payable, empty body - -### Imports (lines 5-15) -| Import | Source | Used in this file? | -|---|---|---| -| `IERC3156FlashLender` | `rain.raindex.interface/interface/ierc3156/IERC3156FlashLender.sol` | **NO** | -| `IERC3156FlashBorrower` | `rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol` | **NO** | -| `OrderBookV6FlashBorrower` | `../../abstract/OrderBookV6FlashBorrower.sol` | Yes (line 27 -- inheritance) | -| `SafeERC20` | `../../abstract/OrderBookV6FlashBorrower.sol` (re-export) | Yes (line 28 -- using declaration) | -| `IERC20` | `../../abstract/OrderBookV6FlashBorrower.sol` (re-export) | Yes (lines 40, 44 -- `IERC20(borrowedToken).forceApprove(...)`) | -| `Address` | `../../abstract/OrderBookV6FlashBorrower.sol` (re-export) | Yes (line 29, 41 -- `pool.functionCallWithValue(...)`) | -| `TakeOrdersConfigV5` | `../../abstract/OrderBookV6FlashBorrower.sol` (re-export) | Yes (line 34 -- function parameter) | -| `OrderBookV6ArbConfig` | `../../abstract/OrderBookV6FlashBorrower.sol` (re-export) | Yes (line 31 -- constructor parameter) | - -### Line-by-line observations -- Line 38: `takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token` -- extracts the borrowed token address. This is a deep access into the struct. The parent `arb4` validates `orders.length > 0` before calling `_exchange`, so `[0]` is safe. -- Lines 42-43: `returnData` pattern identical to sibling `GenericPoolOrderBookV6ArbOrderTaker` -- suppresses unused variable warning. -- Line 41: `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -- forwards full ETH balance, same pattern as sibling. - ---- - -## Code Quality Review - -### 1. Style Consistency - -**Pragma:** `=0.8.25`, consistent with all concrete contracts. - -**Import style:** Mixed approach. Lines 5-6 import `IERC3156FlashLender` and `IERC3156FlashBorrower` directly from `rain.raindex.interface`. Lines 8-15 import everything else as re-exports from the parent abstract `OrderBookV6FlashBorrower.sol`. This mixed import style differs from the sibling `GenericPoolOrderBookV6ArbOrderTaker` which imports `IERC20`, `SafeERC20`, and `Address` directly from `openzeppelin-contracts` rather than via parent re-exports. - -**Using declarations:** Both `SafeERC20` and `Address` are declared and used. No redundancy. - -**Variable naming:** Consistent with sibling contracts: `spender`, `pool`, `encodedFunctionCall`, `borrowedToken`, `returnData`. - -### 2. Leaky Abstractions - -No leaky abstractions. The contract cleanly overrides `_exchange` without exposing parent internals. - -### 3. Commented-Out Code - -No commented-out code. Inline comments explain the `returnData` suppression (line 42) and the fallback purpose (line 47). - -### 4. Build Warnings - -No expected build warnings. The `(returnData);` pattern suppresses the unused variable warning. - -### 5. Dependency Consistency - -No bare `src/` imports. Uses remapped paths consistently. - -### 6. Dead Code - -**Two unused imports identified:** - -- **Line 5:** `IERC3156FlashLender` -- imported but never referenced in the contract body. This interface is not implemented by this contract (it implements the borrower side, not the lender side). The parent `OrderBookV6FlashBorrower` does not use it either (it uses `IERC3156FlashBorrower`). This import is dead code. - -- **Line 6:** `IERC3156FlashBorrower` -- imported but never referenced in this contract's body. The parent abstract contract `OrderBookV6FlashBorrower` already inherits `IERC3156FlashBorrower`, so this concrete contract gets the interface through inheritance. The standalone import in this file is unnecessary. - -### 7. Inconsistent Import Style vs Sibling - -The sibling `GenericPoolOrderBookV6ArbOrderTaker` imports `IERC20`, `SafeERC20`, and `Address` directly from OpenZeppelin. This contract imports them as re-exports from the parent abstract contract. While both approaches work, the inconsistency between sibling contracts in the same directory is a minor style concern. - ---- - -## Findings - -### A06-P4-1 [LOW] Unused import `IERC3156FlashLender` - -**Location:** Line 5 - -**Description:** -`IERC3156FlashLender` is imported from `rain.raindex.interface/interface/ierc3156/IERC3156FlashLender.sol` but is never referenced anywhere in the contract. This contract is a flash loan **borrower**, not a lender. The import is dead code that misleads readers into thinking this contract interacts with or implements the lender interface. - -This was previously noted as A06-P3-2 (INFO) in Pass 3. In a code quality context, unused imports are dead code that should be removed. - -**Recommendation:** Remove line 5: -```solidity -// DELETE: import {IERC3156FlashLender} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashLender.sol"; -``` - -### A06-P4-2 [LOW] Unused import `IERC3156FlashBorrower` - -**Location:** Line 6 - -**Description:** -`IERC3156FlashBorrower` is imported directly but never referenced in this contract's body. The interface is already available through the inheritance chain: `GenericPoolOrderBookV6FlashBorrower` -> `OrderBookV6FlashBorrower` -> `IERC3156FlashBorrower`. The standalone import on line 6 adds no value and creates unnecessary coupling to the import path. - -**Recommendation:** Remove line 6: -```solidity -// DELETE: import {IERC3156FlashBorrower} from "rain.raindex.interface/interface/ierc3156/IERC3156FlashBorrower.sol"; -``` - -### A06-P4-3 [INFO] Inconsistent import style vs sibling contract - -**Location:** Lines 8-15 - -**Description:** -This contract imports `SafeERC20`, `IERC20`, `Address`, and `TakeOrdersConfigV5` as re-exports from the parent abstract `OrderBookV6FlashBorrower.sol` (lines 8-15). The sibling `GenericPoolOrderBookV6ArbOrderTaker.sol` imports the same types (`IERC20`, `SafeERC20`, `Address`) directly from their original OpenZeppelin sources. - -Both approaches are functionally correct, but the inconsistency between two contracts in the same directory that serve the same architectural purpose (concrete arb implementations) is a minor style issue. A consistent import style across the `src/concrete/arb/` directory would improve readability. - -### A06-P4-4 [INFO] Redundant `super._exchange` call to no-op parent (NOT present, but worth noting) - -The `_exchange` override does NOT call `super._exchange()`, unlike the sibling `GenericPoolOrderBookV6ArbOrderTaker` which calls `super.onTakeOrders2()`. The parent `OrderBookV6FlashBorrower._exchange` is also a no-op `{}`. The asymmetry between siblings is noted: one calls super (defensive), the other does not (lean). Both are correct since the parent is a no-op. This is informational only. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A06-P4-1 | LOW | Unused import `IERC3156FlashLender` | -| A06-P4-2 | LOW | Unused import `IERC3156FlashBorrower` | -| A06-P4-3 | INFO | Inconsistent import style vs sibling contract | -| A06-P4-4 | INFO | Asymmetric super call pattern vs sibling | diff --git a/audit/2026-03-13-01/pass4/LibOrder.md b/audit/2026-03-13-01/pass4/LibOrder.md deleted file mode 100644 index 34c65a9be3..0000000000 --- a/audit/2026-03-13-01/pass4/LibOrder.md +++ /dev/null @@ -1,31 +0,0 @@ -# Pass 4: Code Quality -- LibOrder.sol - -**Agent:** A10 -**File:** `src/lib/LibOrder.sol` (19 lines) - -## Evidence of Thorough Reading - -- SPDX license `LicenseRef-DCL-1.0` (line 1) -- Pragma `^0.8.18` (line 3) -- the most permissive lower bound among the lib files -- Single import: `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5) -- Library `LibOrder` contains one function: `hash(OrderV4 memory order)` (line 16) -- Uses `keccak256(abi.encode(order))` with NatSpec explaining `abi.encode` is preferred over `abi.encodePacked` to prevent collisions (lines 11-13) -- Fully documented with NatSpec `@param` and `@return` tags - -## Findings - -### P4-A10-01 (INFO): Pragma Version Divergence - -**Line:** 3 -**Details:** This file uses `pragma solidity ^0.8.18` while most other library files in `src/lib/` use `^0.8.19` and concrete contracts use `=0.8.25`. The lower bound is not incorrect but is inconsistent with siblings. This is informational only -- widening compatibility is a valid design choice for a standalone utility library. - -### P4-A10-02 (INFO): No Issues Found - -The file is minimal, well-documented, has no dead code, no commented-out code, no bare `src/` imports, and no leaky abstractions. The single import is used. Style is consistent. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| P4-A10-01 | INFO | Pragma `^0.8.18` is lower than sibling libs (`^0.8.19`) | -| P4-A10-02 | INFO | Clean file, no issues | diff --git a/audit/2026-03-13-01/pass4/LibOrderBook.md b/audit/2026-03-13-01/pass4/LibOrderBook.md deleted file mode 100644 index f319580fee..0000000000 --- a/audit/2026-03-13-01/pass4/LibOrderBook.md +++ /dev/null @@ -1,45 +0,0 @@ -# Pass 4: Code Quality -- LibOrderBook.sol - -**Agent:** A11 -**File:** `src/lib/LibOrderBook.sol` (125 lines) - -## Evidence of Thorough Reading - -- Pragma `^0.8.19` (line 3) -- Re-exports `CONTEXT_BASE_ROWS`, `CONTEXT_BASE_ROW_SENDER`, `CONTEXT_BASE_ROW_CALLING_CONTRACT`, `CONTEXT_BASE_COLUMN` from `rain.interpreter.interface/lib/caller/LibContext.sol` (lines 5-10) -- Imports: `TaskV2`, `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4`, `LibNamespace`, `FullyQualifiedNamespace`, `LibContext` (lines 11-19) -- File-level constants (lines 22-94): `CALLING_CONTEXT_COLUMNS`, `CONTEXT_COLUMNS`, calling context rows, deposit/withdraw context rows, calculations rows, vault IO rows, signed context rows -- `CONTEXT_COLUMNS = CALLING_CONTEXT_COLUMNS + 1` (line 30) -- Library `LibOrderBook` has one function `doPost` (line 97) -- `doPost` uses `(stack)` on line 118 to suppress unused return value warning -- Deposit and withdraw calling context row constants (lines 43-52) overlap numerically with each other (both start at 0) -- they represent different sub-contexts that reuse column 1 - -## Findings - -### P4-A11-01 (LOW): Typo in Comment -- "calculuate" - -**Line:** 23 -**Details:** The comment reads "the full evaluation of calculuate order" -- "calculuate" should be "calculate". - -### P4-A11-02 (LOW): Typo in Comment -- "subtraced" - -**Line:** 82 -**Details:** The comment reads "must be added to input balances and subtraced from output balances" -- "subtraced" should be "subtracted". - -### P4-A11-03 (INFO): Overlapping Constant Values for Deposit/Withdraw Context Rows - -**Lines:** 43-52 -**Details:** `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` and `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` are both `0`, and the pattern continues through the overlapping rows. These represent different evaluation contexts (deposit vs withdraw) that reuse column index 1 (`CONTEXT_CALLING_CONTEXT_COLUMN`). The naming and comments make this clear enough, but it is worth noting that these are mutually exclusive contexts -- they cannot both be valid in the same evaluation. - -### P4-A11-04 (INFO): Style Consistency - -All constants use `SCREAMING_SNAKE_CASE`, the library name follows `PascalCase`, and there is no commented-out code or dead code. All imports are used. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| P4-A11-01 | LOW | Typo "calculuate" in comment (line 23) | -| P4-A11-02 | LOW | Typo "subtraced" in comment (line 82) | -| P4-A11-03 | INFO | Overlapping deposit/withdraw constant values (by design) | -| P4-A11-04 | INFO | Style consistency is good | diff --git a/audit/2026-03-13-01/pass4/LibOrderBookArb.md b/audit/2026-03-13-01/pass4/LibOrderBookArb.md deleted file mode 100644 index 735a6ab55c..0000000000 --- a/audit/2026-03-13-01/pass4/LibOrderBookArb.md +++ /dev/null @@ -1,44 +0,0 @@ -# Pass 4: Code Quality -- LibOrderBookArb.sol - -**Agent:** A12 -**File:** `src/lib/LibOrderBookArb.sol` (77 lines) - -## Evidence of Thorough Reading - -- Pragma `^0.8.19` (line 3) -- Imports: `TaskV2`, `IERC20`, `LibOrderBook`, `Address`, `SafeERC20`, `IERC20Metadata`, `LibDecimalFloat`, `Float` (lines 5-11) -- Error `NonZeroBeforeArbStack()` (line 14) -- defined here, used nowhere in this file -- Error `BadLender(address badLender)` (line 18) -- defined here, used nowhere in this file -- `using SafeERC20 for IERC20` (line 21) -- `finalizeArb` function (lines 23-76): transfers input token balance, output token balance, and native gas to `msg.sender`, encodes as floats into context, calls `LibOrderBook.doPost` -- `(lossless)` suppression pattern on lines 40 and 52 to silence unused variable warnings -- `forge-lint: disable-next-line(unsafe-typecast)` on line 67 for `int256(gasBalance)` cast with justification - -## Findings - -### P4-A12-01 (LOW): Unused Import `IERC20Metadata` - -**Line:** 10 -**Details:** `IERC20Metadata` is imported from OpenZeppelin but never used in the library. It is not referenced in `finalizeArb` or anywhere else in the file. - -### P4-A12-02 (LOW): Errors Defined But Not Used in This File - -**Lines:** 14, 18 -**Details:** `NonZeroBeforeArbStack` and `BadLender` are defined here but never referenced in this library. They are imported by `OrderBookV6FlashBorrower.sol` and `OrderBookV6ArbOrderTaker.sol`, but those files also never use them -- neither file contains a `revert NonZeroBeforeArbStack()` or `revert BadLender(...)` statement. These appear to be vestigial errors from a previous version. While defining errors in a shared location for re-export is a valid pattern, the fact that no file in `src/` actually reverts with either error makes them dead code. - -### P4-A12-03 (INFO): Consistent Use of SafeERC20 - -The library correctly uses `safeTransfer` via `SafeERC20` for all ERC20 transfers and `Address.sendValue` for native gas transfers. This is consistent and correct. - -### P4-A12-04 (INFO): No Commented-Out Code, No Bare `src/` Imports - -Clean file otherwise. Import paths use proper package-relative paths. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| P4-A12-01 | LOW | Unused import `IERC20Metadata` | -| P4-A12-02 | LOW | `NonZeroBeforeArbStack` and `BadLender` errors defined but never used in any src file | -| P4-A12-03 | INFO | Consistent SafeERC20/Address usage (positive) | -| P4-A12-04 | INFO | Clean file, no bare `src/` imports | diff --git a/audit/2026-03-13-01/pass4/LibOrderBookDeploy.md b/audit/2026-03-13-01/pass4/LibOrderBookDeploy.md deleted file mode 100644 index 82ef5404ac..0000000000 --- a/audit/2026-03-13-01/pass4/LibOrderBookDeploy.md +++ /dev/null @@ -1,38 +0,0 @@ -# Pass 4: Code Quality -- LibOrderBookDeploy.sol - -**Agent:** A14 -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` (53 lines) - -## Evidence of Thorough Reading - -- Pragma `^0.8.25` (line 3) -- higher minimum than other lib files -- Import of `Vm` from `forge-std/Vm.sol` (line 5) -- a test/script-only dependency -- Imports from two generated pointer files: `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` for both `OrderBookV6` and `OrderBookV6SubParser` (lines 7-16) -- Library `LibOrderBookDeploy` defines four constants aliasing the generated values (lines 27-39) -- `etchOrderBook(Vm vm)` function (lines 45-52) conditionally etches runtime code using Forge cheatcodes, only if codehash doesn't match - -## Findings - -### P4-A14-01 (LOW): `forge-std` Dependency in Production Source - -**Line:** 5 -**Details:** This file is located in `src/lib/deploy/` (production source tree) but imports `Vm` from `forge-std/Vm.sol`. The `Vm` type is only available in Forge test/script environments. Including this in `src/` means any contract that transitively imports this library will pull in a forge-std dependency, which is not appropriate for production deployments. This file would be better placed in `script/` or `test/` since `etchOrderBook` is only useful in Forge environments. - -Note: While this is a code quality concern, the library is only consumed by test/script code in practice. Moving it out of `src/` would be the cleanest fix. - -### P4-A14-02 (INFO): Pragma Divergence - -**Line:** 3 -**Details:** Uses `^0.8.25` while sibling libraries use `^0.8.19`. This is likely intentional to match the concrete contracts that use `=0.8.25`, but is the highest minimum among all lib files. - -### P4-A14-03 (INFO): Clean Code Quality - -No dead code, no commented-out code, no bare `src/` imports. The four constant aliases are all used either directly or exported. The `etchOrderBook` function is well-documented with NatSpec. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| P4-A14-01 | LOW | `forge-std/Vm.sol` imported in production `src/` tree | -| P4-A14-02 | INFO | Pragma `^0.8.25` higher than sibling libs | -| P4-A14-03 | INFO | Clean code quality otherwise | diff --git a/audit/2026-03-13-01/pass4/LibOrderBookSubParser.md b/audit/2026-03-13-01/pass4/LibOrderBookSubParser.md deleted file mode 100644 index f15a9d50fa..0000000000 --- a/audit/2026-03-13-01/pass4/LibOrderBookSubParser.md +++ /dev/null @@ -1,54 +0,0 @@ -# Pass 4: Code Quality -- LibOrderBookSubParser.sol - -**Agent:** A13 -**File:** `src/lib/LibOrderBookSubParser.sol` (599 lines) - -## Evidence of Thorough Reading - -- Pragma `^0.8.19` (line 3) -- Imports: `AuthoringMetaV2`, `OperandV2`, `LibUint256Matrix`, `LibSubParse`, plus 28 context constants from `LibOrderBook.sol` (lines 5-46) -- File-level constants: `SUB_PARSER_WORD_PARSERS_LENGTH = 2` (line 48), `EXTERN_PARSE_META_BUILD_DEPTH = 1` (line 49) -- 21 `WORD_*` byte string constants for all sub-parser keywords (lines 51-80) -- 13 `DEPOSIT_WORD_*` / `WITHDRAW_WORD_*` index constants (lines 82-95) -- 17 `subParser*` functions (lines 101-366), each calling `LibSubParse.subParserContext` with appropriate column/row -- `subParserSigners` uses `OperandV2.unwrap(operand)` directly (line 257) -- `subParserSignedContext` unpacks two bytes from operand: column = low byte, row = next byte (lines 362-363) -- `authoringMetaV2()` (lines 369-598) builds the complete authoring metadata for all context columns -- Two assembly blocks in `authoringMetaV2` at lines 588 and 593 -- neither annotated as `"memory-safe"` -- `depositMeta` indexing uses `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN + 1` pattern (lines 524-541) which adds `+1` to offset past the depositor entry at index 0 -- All `subParser*` functions have `//slither-disable-next-line unused-return` annotations - -## Findings - -### P4-A13-01 (LOW): Typo in AuthoringMeta Description -- "much authorize" - -**Line:** 507 -**Details:** The description string for signed context reads: "the expression author much authorize the signer's public key." This should be "must authorize". - -### P4-A13-02 (LOW): Assembly Blocks Missing `"memory-safe"` Annotation - -**Lines:** 588, 593 -**Details:** The two assembly blocks in `authoringMetaV2()` perform type-punning casts (`metaUint256 := meta` and `metaFlattened := metaUint256Flattened`). These are the same pattern as the assembly blocks in `OrderBookV6SubParser.sol` (lines 179, 301) which ARE annotated as `("memory-safe")`. The inconsistency could cause the optimizer to treat these blocks differently. Since these are pure type-reinterpretation casts on memory-safe pointers, they should be annotated. - -### P4-A13-03 (INFO): `EXTERN_PARSE_META_BUILD_DEPTH` Defined Here but Only Used in Scripts - -**Line:** 49 -**Details:** `EXTERN_PARSE_META_BUILD_DEPTH` is defined in this library file but is only used in `script/BuildPointers.sol`. This is not strictly dead code in the library (it is a file-level constant exported for use by scripts), but it means the library itself does not use this constant. - -### P4-A13-04 (INFO): Consistent Slither Suppression Pattern - -All 17 `subParser*` functions consistently use `//slither-disable-next-line unused-return` before the `return` statement. This is uniform and correct. - -### P4-A13-05 (INFO): No Bare `src/` Imports, No Commented-Out Code - -All import paths use proper relative (`./`) or package-qualified paths. No commented-out code sections found. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| P4-A13-01 | LOW | Typo "much" -> "must" in authoring meta description (line 507) | -| P4-A13-02 | LOW | Assembly blocks missing `"memory-safe"` annotation (lines 588, 593) | -| P4-A13-03 | INFO | `EXTERN_PARSE_META_BUILD_DEPTH` only used externally in scripts | -| P4-A13-04 | INFO | Consistent slither suppression pattern (positive) | -| P4-A13-05 | INFO | Clean imports and no commented-out code | diff --git a/audit/2026-03-13-01/pass4/OrderBookV6.md b/audit/2026-03-13-01/pass4/OrderBookV6.md deleted file mode 100644 index 4de5a86944..0000000000 --- a/audit/2026-03-13-01/pass4/OrderBookV6.md +++ /dev/null @@ -1,273 +0,0 @@ -# Pass 4: Code Quality -- OrderBookV6.sol - -**Agent:** A08 -**File:** `src/concrete/ob/OrderBookV6.sol` (1055 lines) - -## Evidence of Thorough Reading - -### Structure Summary - -- **License:** `LicenseRef-DCL-1.0` (line 1), copyright 2020 Rain Open Source Software Ltd (line 2) -- **Pragma:** `solidity =0.8.25` (line 3) -- **Imports:** 22 import statements across lines 5-65, importing from `openzeppelin-contracts`, `rain.interpreter.interface`, `rain.solmem`, `rain.metadata`, `rain.math.float`, `rain.tofu.erc20-decimals`, `rain.raindex.interface`, and local relative paths (`../../lib/`, `../../abstract/`) -- **File-scope errors:** 17 errors (lines 69-125) -- **File-scope constants:** 8 constants (lines 129-150) -- **File-scope struct:** `OrderIOCalculationV4` (line 181) -- **File-scope type aliases:** `Output18Amount` (line 192), `Input18Amount` (line 194) -- **Contract:** `OrderBookV6` inherits `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender` -- **Using directives:** `LibUint256Array for uint256[]`, `SafeERC20 for IERC20`, `LibOrder for OrderV4`, `LibUint256Array for uint256`, `LibDecimalFloat for Float`, `LibBytes32Array for bytes32` -- **Storage:** `sOrders` (line 215), `sVaultBalances` (line 222) -- **Functions:** 22 functions + 1 modifier covering vault management, order lifecycle, order taking, clearing, and token transfer - -### All Imports Verified - -| Import | Line | Used? | -|--------|------|-------| -| `Math` | 5 | NO -- never referenced outside import | -| `Multicall` | 6 | Yes (inheritance) | -| `IERC20` | 7 | Yes (token transfers) | -| `SafeERC20` | 8 | Yes (using directive) | -| `ReentrancyGuard` | 9 | Yes (inheritance) | -| `IERC20Metadata` | 10 | NO -- never referenced outside import | -| `LibContext` | 12 | Yes (line 762) | -| `LibBytecode` | 13 | NO -- never referenced outside import | -| `SourceIndexV2` | 15 | Yes (constants) | -| `StateNamespace` | 16 | Yes (struct, usage) | -| `IInterpreterV4` | 17 | NO -- not directly referenced (used transitively via evaluable) | -| `StackItem` | 18 | Yes (eval calls) | -| `EvalV4` | 19 | Yes (eval calls) | -| `LibUint256Array` | 21 | Questionable -- `using` directives exist but no actual method calls found | -| `LibUint256Matrix` | 22 | NO -- never referenced outside import | -| `IInterpreterStoreV3` | 23 | NO -- never referenced outside import | -| `LibNamespace` | 24 | Yes (line 777, 941) | -| `LibMeta` | 25 | Yes (line 367) | -| `IMetaV1_2` | 26 | Yes (inheritance) | -| `LibOrderBook` | 27 | Yes (doPost calls) | -| `LibDecimalFloat` | 28 | Yes (using directive, static calls) | -| `LibTOFUTokenDecimals` | 29 | Yes (decimals resolution) | -| `TOFUOutcome` | 29 | Yes (outcome checks) | -| `ITOFUTokenDecimals` | 30 | Yes (error selector) | -| `IRaindexV6` (+ types) | 32-48 | Yes (inheritance, type usage) | -| `EvaluableV4` | 43 | NO -- explicitly suppressed by `forge-lint: disable-next-line(unused-import)` | -| `IRaindexV6OrderTaker` | 49 | Yes (callback, line 582) | -| `LibOrder` | 50 | Yes (using directive) | -| Constants from LibOrderBook | 51-60 | Yes (context column indices) | -| `OrderBookV6FlashLender` | 61 | Yes (inheritance) | -| `LibBytes32Array` | 62 | Yes (using directive, static calls) | -| `LibBytes32Matrix` | 63 | Yes (matrixFrom calls) | -| `LibFormatDecimalFloat` | 65 | NO -- never referenced outside import | - -### All Errors Cross-Referenced for Usage - -| Error | Line | Used in Contract? | -|-------|------|-------------------| -| `ReentrancyGuardReentrantCall()` | 69 | NO -- duplicates OZ's own error | -| `NotOrderOwner(address)` | 73 | Yes (line 389) | -| `TokenMismatch()` | 76 | Yes (lines 482, 613) | -| `TokenSelfTrade()` | 79 | Yes (line 408) | -| `TokenDecimalsMismatch()` | 83 | NO | -| `MinimumIO(Float, Float)` | 88 | Yes (line 564) | -| `SameOwner()` | 91 | Yes (line 605) | -| `UnsupportedCalculateInputs(uint256)` | 95 | NO | -| `UnsupportedCalculateOutputs(uint256)` | 98 | Yes (line 789) | -| `NegativeInput()` | 102 | NO | -| `NegativeOutput()` | 105 | NO | -| `NegativeVaultBalance(Float)` | 109 | Yes (lines 846, 878) | -| `NegativeVaultBalanceChange(Float)` | 113 | Yes (lines 828, 859) | -| `NegativePull()` | 116 | Yes (line 1009) | -| `NegativePush()` | 119 | Yes (line 1032) | -| `NegativeBounty()` | 122 | Yes (line 659) | -| `ClearZeroAmount()` | 125 | Yes (line 686) | - -### All Constants Cross-Referenced for Usage - -| Constant | Line | Used? | -|----------|------|-------| -| `ORDER_LIVE` | 129 | Yes (lines 250, 361, 392, 416, 488) | -| `ORDER_DEAD` | 134 | Yes (lines 353, 394, 626, 630) | -| `CALCULATE_ORDER_ENTRYPOINT` | 137 | Yes (line 779) | -| `HANDLE_IO_ENTRYPOINT` | 140 | Yes (line 943) | -| `CALCULATE_ORDER_MIN_OUTPUTS` | 143 | Yes (line 788) | -| `CALCULATE_ORDER_MAX_OUTPUTS` | 145 | NO | -| `HANDLE_IO_MIN_OUTPUTS` | 148 | NO | -| `HANDLE_IO_MAX_OUTPUTS` | 150 | NO | - ---- - -## Findings - -### A08-P4-1 (LOW): Six unused imports inflate bytecode and coupling - -**Lines:** 5, 10, 13, 22, 23, 65 - -The following imports are brought into the file but never used in the contract body: - -1. **`Math`** (line 5) -- OpenZeppelin's `Math` library is imported but never called. No `Math.` method invocations exist in the file. -2. **`IERC20Metadata`** (line 10) -- Imported but never referenced. Token decimals are resolved via `LibTOFUTokenDecimals`, not `IERC20Metadata.decimals()`. -3. **`LibBytecode`** (line 13) -- Imported but never called. Bytecode validation is not performed in this contract. -4. **`LibUint256Matrix`** (line 22) -- Imported but never referenced. The contract uses `LibBytes32Matrix` instead. -5. **`IInterpreterStoreV3`** (line 23) -- Imported but never directly referenced. The store is accessed via `order.evaluable.store` which is already typed. -6. **`LibFormatDecimalFloat`** (line 65) -- Imported but never called. No formatting is done in this contract. - -Each unused import adds to compilation coupling and cognitive overhead. If any of these libraries contain constructor logic or state, they could also inflate deployed bytecode. - ---- - -### A08-P4-2 (LOW): Five dead errors never thrown - -**Lines:** 69, 83, 95, 102, 105 - -Five error declarations are never used in any `revert` statement in this file or its parent contracts: - -1. **`ReentrancyGuardReentrantCall()`** (line 69) -- Duplicates OpenZeppelin's `ReentrancyGuard.ReentrancyGuardReentrantCall`. OZ's version is the one actually thrown by the inherited `nonReentrant` modifier. This local duplicate serves no purpose and creates selector collision risk if the signature ever diverged. -2. **`TokenDecimalsMismatch()`** (line 83) -- Vestigial from a prior version. Token decimal mismatches are now handled by the TOFU mechanism. -3. **`UnsupportedCalculateInputs(uint256)`** (line 95) -- Declared but never thrown. Only `UnsupportedCalculateOutputs` is checked (line 788). -4. **`NegativeInput()`** (line 102) -- Never thrown. `NegativeVaultBalanceChange` is used instead. -5. **`NegativeOutput()`** (line 105) -- Never thrown. `NegativeVaultBalanceChange` is used instead. - -Dead errors inflate the ABI, confuse integrators (who may expect these errors could be thrown), and are imported by test files (e.g., `test/concrete/ob/OrderBookV6.addOrder.t.sol` imports `UnsupportedCalculateInputs`). - ---- - -### A08-P4-3 (LOW): Two dead type aliases `Output18Amount` and `Input18Amount` - -**Lines:** 192-194 - -```solidity -type Output18Amount is uint256; -type Input18Amount is uint256; -``` - -These user-defined value types are declared at file scope but never used anywhere in the contract or the broader `src/` tree. They are remnants of a pre-Float era when the contract used 18-decimal fixed-point math. Dead types add confusion about the contract's data model -- a reader might assume vault amounts flow through these types when they actually use `Float`. - -Previously identified in Pass 1 (A08-4) and Pass 2 (A08-16). - ---- - -### A08-P4-4 (LOW): Three dead constants never referenced - -**Lines:** 145, 148, 150 - -```solidity -uint16 constant CALCULATE_ORDER_MAX_OUTPUTS = 2; -uint256 constant HANDLE_IO_MIN_OUTPUTS = 0; -uint16 constant HANDLE_IO_MAX_OUTPUTS = 0; -``` - -These constants are declared but never used anywhere in the contract or the broader codebase: - -- `CALCULATE_ORDER_MAX_OUTPUTS` -- only `CALCULATE_ORDER_MIN_OUTPUTS` is checked (line 788). -- `HANDLE_IO_MIN_OUTPUTS` and `HANDLE_IO_MAX_OUTPUTS` -- the handle IO entrypoint stack length is never validated. - -Additionally, there is a type inconsistency: the `MIN_OUTPUTS` constants are `uint256` while the `MAX_OUTPUTS` constants are `uint16`. This mixed typing across paired constants is a style inconsistency that adds confusion. - ---- - -### A08-P4-5 (LOW): Duplicate import from same file `../../lib/LibOrderBook.sol` - -**Lines:** 27, 51-60 - -`LibOrderBook.sol` is imported twice: - -```solidity -import {LibOrderBook} from "../../lib/LibOrderBook.sol"; // line 27 -... -import { - CALLING_CONTEXT_COLUMNS, - CONTEXT_CALLING_CONTEXT_COLUMN, - ... -} from "../../lib/LibOrderBook.sol"; // lines 51-60 -``` - -These should be consolidated into a single import statement. The Solidity compiler handles this correctly, but split imports from the same file are a style inconsistency and reduce readability. - ---- - -### A08-P4-6 (LOW): Stale comment references `_recordVaultIO` (underscore prefix) - -**Line:** 765 - -```solidity -// The state changes produced here are handled in _recordVaultIO so -``` - -The function is named `recordVaultIO` (no underscore). This is the same class of stale reference identified for `_calculateOrderIO` in Pass 3 (A08-P3-1). The underscore naming convention was removed from these functions but comments were not updated. - ---- - -### A08-P4-7 (INFO): Stale comment references `IOrderBookV1` interface - -**Line:** 218 - -```solidity -/// This gives 1:1 parity with the `IOrderBookV1` interface but keeping the -``` - -The contract is `OrderBookV6` implementing `IRaindexV6`. The reference to `IOrderBookV1` is outdated -- the vault balance mapping structure may trace its lineage to V1, but the comment should reference the current interface or be made version-agnostic. - ---- - -### A08-P4-8 (INFO): `using LibUint256Array` directives appear unused - -**Lines:** 199, 202 - -```solidity -using LibUint256Array for uint256[]; -using LibUint256Array for uint256; -``` - -No `uint256[]` or `uint256` extension method from `LibUint256Array` is called anywhere in the contract body. The contract uses `LibBytes32Array` and `LibBytes32Matrix` for all array operations. `StackItem` is `bytes32`, not `uint256`, so the eval return values also don't benefit from these `using` directives. - -If these directives attach methods that are truly never called, they are dead code. However, `using` directives do not affect bytecode unless the methods are actually invoked, so this is purely a readability concern. - ---- - -### A08-P4-9 (INFO): Isolated blank line between import groups is inconsistent - -**Line:** 64-65 - -```solidity -import {LibBytes32Matrix} from "rain.solmem/lib/LibBytes32Matrix.sol"; - -import {LibFormatDecimalFloat} from "rain.math.float/lib/format/LibFormatDecimalFloat.sol"; -``` - -There is a blank line separating the `LibFormatDecimalFloat` import from the rest of the imports. Other import groups are separated only between conceptual blocks (OZ, rain.*, local). This single isolated import on line 65 (which is also unused per A08-P4-1) stands out as inconsistent. - ---- - -### A08-P4-10 (INFO): Constant type inconsistency between paired MIN/MAX constants - -**Lines:** 143-150 - -The `MIN_OUTPUTS` constants use `uint256` while their paired `MAX_OUTPUTS` constants use `uint16`: - -```solidity -uint256 constant CALCULATE_ORDER_MIN_OUTPUTS = 2; -uint16 constant CALCULATE_ORDER_MAX_OUTPUTS = 2; - -uint256 constant HANDLE_IO_MIN_OUTPUTS = 0; -uint16 constant HANDLE_IO_MAX_OUTPUTS = 0; -``` - -Paired constants representing the same concept (output count bounds) should use the same type. The `uint16` type likely originates from a prior version's function signature that accepted a `uint16` max outputs parameter. Since the MAX constants are unused (A08-P4-4), this is moot if they are removed. - ---- - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| A08-P4-1 | LOW | 6 unused imports (`Math`, `IERC20Metadata`, `LibBytecode`, `LibUint256Matrix`, `IInterpreterStoreV3`, `LibFormatDecimalFloat`) | -| A08-P4-2 | LOW | 5 dead errors never thrown (`ReentrancyGuardReentrantCall`, `TokenDecimalsMismatch`, `UnsupportedCalculateInputs`, `NegativeInput`, `NegativeOutput`) | -| A08-P4-3 | LOW | 2 dead type aliases (`Output18Amount`, `Input18Amount`) | -| A08-P4-4 | LOW | 3 dead constants never referenced (`CALCULATE_ORDER_MAX_OUTPUTS`, `HANDLE_IO_MIN_OUTPUTS`, `HANDLE_IO_MAX_OUTPUTS`) | -| A08-P4-5 | LOW | Duplicate import from `../../lib/LibOrderBook.sol` (lines 27 and 51-60) | -| A08-P4-6 | LOW | Stale comment references `_recordVaultIO` instead of `recordVaultIO` | -| A08-P4-7 | INFO | Stale comment references `IOrderBookV1` | -| A08-P4-8 | INFO | `using LibUint256Array` directives appear unused | -| A08-P4-9 | INFO | Isolated blank line before unused `LibFormatDecimalFloat` import | -| A08-P4-10 | INFO | Constant type inconsistency between paired MIN/MAX constants | - -**LOW findings:** 6 -**INFO findings:** 4 diff --git a/audit/2026-03-13-01/pass4/OrderBookV6ArbCommon.md b/audit/2026-03-13-01/pass4/OrderBookV6ArbCommon.md deleted file mode 100644 index 48892bae5a..0000000000 --- a/audit/2026-03-13-01/pass4/OrderBookV6ArbCommon.md +++ /dev/null @@ -1,99 +0,0 @@ -# Pass 4: Code Quality -- OrderBookV6ArbCommon.sol - -**Agent:** A01 -**File:** `src/abstract/OrderBookV6ArbCommon.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6ArbCommon` (abstract, line 34) - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| struct | `OrderBookV6ArbConfig` | 21-25 | -| error | `WrongTask()` | 28 | -| constant | `BEFORE_ARB_SOURCE_INDEX` | 32 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `constructor(OrderBookV6ArbConfig)` | internal (abstract) | 41-48 | - -### Modifier - -| Name | Line | -|------|------| -| `onlyValidTask(TaskV2)` | 50-55 | - -### Events - -| Name | Line | -|------|------| -| `Construct(address, OrderBookV6ArbConfig)` | 37 | - -### Imports (lines 5-14) - -| Symbol | Source | Used Beyond Import? | -|--------|--------|---------------------| -| `EvaluableV4` | `rain.interpreter.interface/.../IInterpreterCallerV4.sol` | Yes (line 35, `using LibEvaluable for EvaluableV4`) | -| `SignedContextV1` | same | No direct use in this file; re-exported via line 16 of `OrderBookV6ArbOrderTaker.sol` | -| `IInterpreterV4` | `rain.interpreter.interface/.../IInterpreterV4.sol` | No | -| `SourceIndexV2` | same | Yes (line 32) | -| `DEFAULT_STATE_NAMESPACE` | same | No | -| `IRaindexV6` | `rain.raindex.interface/.../IRaindexV6.sol` | No | -| `TaskV2` | same | Yes (modifier parameter) | -| `LibContext` | `rain.interpreter.interface/.../LibContext.sol` | No | -| `LibNamespace` | `rain.interpreter.interface/.../LibNamespace.sol` | No | -| `LibEvaluable` | `rain.interpreter.interface/.../LibEvaluable.sol` | Yes (line 35) | - -## Findings - -### A01-P4-1 [LOW] Multiple unused imports - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** The following imports are brought in but never used within the contract body: -- `IInterpreterV4` (line 7) -- `DEFAULT_STATE_NAMESPACE` (line 9) -- `IRaindexV6` (line 11) -- `LibContext` (line 12) -- `LibNamespace` (line 13) -- `SignedContextV1` (line 5) -- only re-exported by downstream files, not used here - -These were likely leftover from a prior version of the contract that had a `_beforeArb` method (which was refactored into `LibOrderBookArb`). Unused imports inflate compiled metadata, slow down compilation, and obscure the true dependency surface. - -**Recommendation:** Remove all imports that are not consumed by any declaration or expression in the file. Downstream files that need `SignedContextV1`, `IInterpreterV4`, etc. should import them directly. - -### A01-P4-2 [INFO] `BEFORE_ARB_SOURCE_INDEX` defined at file scope but unused within the contract - -The constant `BEFORE_ARB_SOURCE_INDEX` (line 32) is defined at file scope and is not referenced by any code in `OrderBookV6ArbCommon` itself. It is duplicated in `OrderBookV6ArbOrderTaker.sol` (line 29). This was flagged in pass 1 (A01-1) and pass 3 (A01-P3-3). From a code quality perspective, it would be cleaner to define this constant in exactly one location and import it where needed. - -### A01-P4-3 [INFO] `using LibEvaluable for EvaluableV4` declared but unused - -Line 35 declares `using LibEvaluable for EvaluableV4` but no method from `LibEvaluable` is ever called on an `EvaluableV4` value within this contract. The `using` directive is dead code. - -### A01-P4-4 [INFO] Style: pragma range `^0.8.19` vs concrete `0.8.25` in foundry.toml - -The abstract contracts use `pragma solidity ^0.8.19` while concrete contracts use `=0.8.25`. This is a reasonable pattern (abstracts are more reusable), but the pragma floor of `0.8.19` predates several important compiler fixes. The foundry config sets `solc = "0.8.25"` so in practice these always compile with 0.8.25. Informational only. - -### A01-P4-5 [INFO] No bare `src/` import paths - -All import paths use either remapped dependency names (e.g. `rain.interpreter.interface/...`) or relative paths (`./...`). No bare `src/` paths were found. This is correct for git submodule compatibility. - -### A01-P4-6 [INFO] No commented-out code - -No commented-out code found. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A01-P4-1 | LOW | Multiple unused imports | -| A01-P4-2 | INFO | `BEFORE_ARB_SOURCE_INDEX` defined but unused in contract | -| A01-P4-3 | INFO | `using LibEvaluable` declared but unused | -| A01-P4-4 | INFO | Pragma range vs concrete solc version | -| A01-P4-5 | INFO | No bare `src/` import paths (good) | -| A01-P4-6 | INFO | No commented-out code (good) | diff --git a/audit/2026-03-13-01/pass4/OrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass4/OrderBookV6ArbOrderTaker.md deleted file mode 100644 index cef9e65e3d..0000000000 --- a/audit/2026-03-13-01/pass4/OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,116 +0,0 @@ -# Pass 4: Code Quality -- OrderBookV6ArbOrderTaker.sol - -**Agent:** A02 -**File:** `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6ArbOrderTaker` (abstract, line 31) -- Inherits: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| error | `NonZeroBeforeArbInputs(uint256)` | 25 | -| constant | `BEFORE_ARB_SOURCE_INDEX` | 29 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `constructor(OrderBookV6ArbConfig)` | internal (abstract) | 40 | -| `supportsInterface(bytes4)` | public view virtual | 43-46 | -| `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` | external payable | 49-75 | -| `onTakeOrders2(...)` | public virtual | 78 | - -### Imports (lines 5-22, 18 import statements) - -| Symbol | Source | Used Beyond Import? | -|--------|--------|---------------------| -| `ERC165`, `IERC165` | openzeppelin | Yes (inheritance, override) | -| `ReentrancyGuard` | openzeppelin | Yes (inheritance) | -| `IERC20`, `SafeERC20` | openzeppelin | Yes (line 38, 63, 66) | -| `Address` | openzeppelin | **No** | -| `SourceIndexV2` | rain.interpreter.interface | Yes (line 29) | -| `LibNamespace` | rain.interpreter.interface | **No** | -| `IRaindexV6` | rain.raindex.interface | Yes (line 49, 57) | -| `IRaindexV6ArbOrderTaker`, `TaskV2` | rain.raindex.interface | Yes (inheritance, line 49) | -| `IInterpreterV4`, `DEFAULT_STATE_NAMESPACE` | rain.interpreter.interface | **No** | -| `IInterpreterStoreV3` | rain.interpreter.interface | **No** | -| `TakeOrdersConfigV5`, `Float` | rain.raindex.interface | Yes (lines 49, 64) | -| `OrderBookV6ArbConfig`, `EvaluableV4`, `OrderBookV6ArbCommon`, `SignedContextV1` | `./OrderBookV6ArbCommon.sol` | `OrderBookV6ArbConfig` and `OrderBookV6ArbCommon`: Yes. `EvaluableV4`, `SignedContextV1`: **No** | -| `LibContext` | rain.interpreter.interface | **No** | -| `LibBytecode` | rain.interpreter.interface | **No** | -| `LibOrderBook` | `../lib/LibOrderBook.sol` | **No** | -| `LibOrderBookArb`, `NonZeroBeforeArbStack`, `BadLender` | `../lib/LibOrderBookArb.sol` | `LibOrderBookArb`: Yes (line 68). `NonZeroBeforeArbStack`, `BadLender`: **No** | -| `IRaindexV6OrderTaker` | rain.raindex.interface | Yes (inheritance, line 44) | -| `LibTOFUTokenDecimals` | rain.tofu.erc20-decimals | Yes (lines 71, 73) | - -## Findings - -### A02-P4-1 [LOW] 10 unused imports inflate dependency surface - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** The following imported symbols are never referenced in the contract body: -1. `Address` (line 8) -2. `LibNamespace` (line 10) -3. `IInterpreterV4` (line 13) -4. `DEFAULT_STATE_NAMESPACE` (line 13) -5. `IInterpreterStoreV3` (line 14) -6. `EvaluableV4` (line 16) -- re-exported from ArbCommon but not used here -7. `SignedContextV1` (line 16) -- same -8. `LibContext` (line 17) -9. `LibBytecode` (line 18) -10. `LibOrderBook` (line 19) - -And two error symbols imported but never emitted: -11. `NonZeroBeforeArbStack` (line 20) -12. `BadLender` (line 20) - -These are remnants of the old `_beforeArb` logic that was extracted into `LibOrderBookArb`. The large number of dead imports obscures the actual dependency graph and can mislead auditors into thinking these symbols are relevant. - -**Recommendation:** Remove all unused imports. If any are kept for re-export purposes, add an explicit comment explaining why. - -### A02-P4-2 [LOW] Duplicate constant `BEFORE_ARB_SOURCE_INDEX` - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** `BEFORE_ARB_SOURCE_INDEX` is defined at line 29 with the exact same value (`SourceIndexV2.wrap(0)`) as in `OrderBookV6ArbCommon.sol` line 32. Having two file-scope constants with the same name and value creates ambiguity about which one is canonical. Neither is used in this file (it is consumed inside `LibOrderBookArb`). - -**Recommendation:** Define the constant in exactly one location (either `OrderBookV6ArbCommon.sol` or `LibOrderBookArb.sol`) and import it where needed. - -### A02-P4-3 [LOW] Dead error `NonZeroBeforeArbInputs` - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** The error `NonZeroBeforeArbInputs(uint256 inputs)` at line 25 is declared but never used in this contract or any other file in the repository. This was flagged in pass 1 (A02-2), pass 2 (A02-P2-5), and pass 3 (A02-P3-4). It is dead code. - -**Recommendation:** Remove it. - -### A02-P4-4 [INFO] Suppressed return values on line 65 - -Line 65: `(totalTakerInput, totalTakerOutput);` is a statement-expression that intentionally suppresses "unused variable" warnings for the return values of `takeOrders4`. This pattern is used consistently in this codebase (also in FlashBorrower line 104). While functional, a brief comment explaining the suppression would aid readability. - -### A02-P4-5 [INFO] No bare `src/` import paths - -All import paths use remapped names or relative paths. No bare `src/` paths. Correct for submodule usage. - -### A02-P4-6 [INFO] No commented-out code - -No commented-out code found in the contract. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A02-P4-1 | LOW | 10 unused imports inflate dependency surface | -| A02-P4-2 | LOW | Duplicate constant `BEFORE_ARB_SOURCE_INDEX` | -| A02-P4-3 | LOW | Dead error `NonZeroBeforeArbInputs` | -| A02-P4-4 | INFO | Suppressed return values pattern | -| A02-P4-5 | INFO | No bare `src/` import paths (good) | -| A02-P4-6 | INFO | No commented-out code (good) | diff --git a/audit/2026-03-13-01/pass4/OrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass4/OrderBookV6FlashBorrower.md deleted file mode 100644 index caf73b7e76..0000000000 --- a/audit/2026-03-13-01/pass4/OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,114 +0,0 @@ -# Pass 4: Code Quality -- OrderBookV6FlashBorrower.sol - -**Agent:** A03 -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashBorrower` (abstract, line 62) -- Inherits: `IERC3156FlashBorrower`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| error | `BadInitiator(address)` | 24 | -| error | `FlashLoanFailed()` | 27 | -| error | `SwapFailed()` | 30 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `constructor(OrderBookV6ArbConfig)` | internal (abstract) | 66 | -| `supportsInterface(bytes4)` | public view virtual | 69-71 | -| `_exchange(TakeOrdersConfigV5, bytes)` | internal virtual | 82 | -| `onFlashLoan(address, address, uint256, uint256, bytes)` | external | 85-107 | -| `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` | external payable | 130-165 | - -### Imports (lines 5-20, 16 import statements) - -| Symbol | Source | Used Beyond Import? | -|--------|--------|---------------------| -| `ERC165`, `IERC165` | openzeppelin | Yes (inheritance, override) | -| `SafeERC20` | openzeppelin | Yes (line 64) | -| `Address` | openzeppelin | Yes (line 63, `using Address for address`) | -| `IERC20` | openzeppelin | Yes (lines 158, 162) | -| `ReentrancyGuard` | openzeppelin | Yes (inheritance) | -| `LibBytecode` | rain.interpreter.interface | **No** | -| `ON_FLASH_LOAN_CALLBACK_SUCCESS` | rain.raindex.interface | Yes (line 106) | -| `IRaindexV6`, `TakeOrdersConfigV5`, `TaskV2`, `Float` | rain.raindex.interface | Yes | -| `IERC3156FlashBorrower` | rain.raindex.interface | Yes (inheritance) | -| `IInterpreterStoreV3` | rain.interpreter.interface | **No** | -| `OrderBookV6ArbConfig`, `OrderBookV6ArbCommon` | `./OrderBookV6ArbCommon.sol` | Yes | -| `EvaluableV4`, `SignedContextV1` | rain.interpreter.interface | **No** | -| `LibOrderBook` | `../lib/LibOrderBook.sol` | **No** | -| `LibOrderBookArb`, `NonZeroBeforeArbStack`, `BadLender` | `../lib/LibOrderBookArb.sol` | `LibOrderBookArb`: Yes (line 164). `NonZeroBeforeArbStack`, `BadLender`: **No** | -| `LibTOFUTokenDecimals` | rain.tofu.erc20-decimals | Yes (lines 148-149) | -| `LibDecimalFloat` | rain.math.float | Yes (line 153) | - -## Findings - -### A03-P4-1 [LOW] 7 unused imports - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** The following symbols are imported but never used in the contract body: -1. `LibBytecode` (line 10) -2. `IInterpreterStoreV3` (line 14) -3. `EvaluableV4` (line 16) -4. `SignedContextV1` (line 16) -5. `LibOrderBook` (line 17) -6. `NonZeroBeforeArbStack` (line 18) -7. `BadLender` (line 18) - -Same root cause as A01-P4-1 and A02-P4-1: these are remnants of a prior architecture where `_beforeArb` logic lived in the abstract contracts. - -**Recommendation:** Remove all unused imports. - -### A03-P4-2 [LOW] Dead error `SwapFailed` - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** The error `SwapFailed()` at line 30 is declared but never used in this contract or anywhere in the repository. This was flagged in pass 1 (A03-1), pass 2 (A03-P2-4), and pass 3. It is dead code that should be removed. - -**Recommendation:** Remove the error declaration. - -### A03-P4-3 [LOW] Stale NatSpec: `@title OrderBookV5FlashBorrower` - -**Severity:** LOW -**Confidence:** HIGH - -**Description:** Line 32 reads `/// @title OrderBookV5FlashBorrower` but the contract is `OrderBookV6FlashBorrower`. The `V5` in the title is stale from a prior version. Similarly, line 128 references `GenericPoolOrderBookV5FlashBorrower` which should be `GenericPoolOrderBookV6FlashBorrower`. - -**Recommendation:** Update line 32 to `/// @title OrderBookV6FlashBorrower` and line 128 to reference `GenericPoolOrderBookV6FlashBorrower`. - -### A03-P4-4 [INFO] NatSpec references outdated interface methods - -Line 124 references `IOrderBookV5.takeOrders3` but the actual method called is `IRaindexV6.takeOrders4` (line 103). This is stale documentation from a prior version migration. - -### A03-P4-5 [INFO] `using Address for address` is used - -Unlike `OrderBookV6ArbOrderTaker.sol` which imports `Address` without using it, `OrderBookV6FlashBorrower` does use it (line 63 `using Address for address`). However, the `Address` library is not actually called anywhere visible in this file. The `using` directive makes `Address` methods available on `address` types, but no `.functionCall()` or `.sendValue()` calls appear. This may be dead code, or it may be needed indirectly through `SafeERC20`. Informational only. - -### A03-P4-6 [INFO] No bare `src/` import paths - -All import paths use remapped names or relative paths. Correct for submodule usage. - -### A03-P4-7 [INFO] No commented-out code - -No commented-out code found. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A03-P4-1 | LOW | 7 unused imports | -| A03-P4-2 | LOW | Dead error `SwapFailed` | -| A03-P4-3 | LOW | Stale NatSpec: `@title OrderBookV5FlashBorrower` | -| A03-P4-4 | INFO | NatSpec references outdated interface methods | -| A03-P4-5 | INFO | `using Address for address` potentially unnecessary | -| A03-P4-6 | INFO | No bare `src/` import paths (good) | -| A03-P4-7 | INFO | No commented-out code (good) | diff --git a/audit/2026-03-13-01/pass4/OrderBookV6FlashLender.md b/audit/2026-03-13-01/pass4/OrderBookV6FlashLender.md deleted file mode 100644 index dd0cc35199..0000000000 --- a/audit/2026-03-13-01/pass4/OrderBookV6FlashLender.md +++ /dev/null @@ -1,82 +0,0 @@ -# Pass 4: Code Quality -- OrderBookV6FlashLender.sol - -**Agent:** A04 -**File:** `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashLender` (abstract, line 29) -- Inherits: `IERC3156FlashLender`, `ERC165` - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| error | `FlashLenderCallbackFailed(bytes32)` | 18 | -| constant | `FLASH_FEE` | 23 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `supportsInterface(bytes4)` | public view virtual | 33-35 | -| `flashLoan(IERC3156FlashBorrower, address, uint256, bytes)` | external | 38-67 | -| `flashFee(address, uint256)` | external pure | 70-72 | -| `maxFlashLoan(address)` | external view | 78-80 | - -### Imports (lines 5-13, 5 import statements) - -| Symbol | Source | Used Beyond Import? | -|--------|--------|---------------------| -| `ERC165`, `IERC165` | openzeppelin | Yes (inheritance, override) | -| `IERC20` | openzeppelin | Yes (lines 43, 64, 79) | -| `SafeERC20` | openzeppelin | Yes (line 30) | -| `IERC3156FlashBorrower`, `ON_FLASH_LOAN_CALLBACK_SUCCESS` | rain.raindex.interface | Yes (lines 38, 46) | -| `IERC3156FlashLender` | rain.raindex.interface | Yes (inheritance) | - -## Findings - -### A04-P4-1 [INFO] Clean import hygiene - -This is the cleanest of the four abstract contracts. All 5 import statements bring in symbols that are actually used. No dead imports. - -### A04-P4-2 [INFO] Style consistency: pragma `^0.8.19` - -Matches the other abstract contracts. Consistent within the abstract layer. - -### A04-P4-3 [INFO] NatSpec comment about "Orderbook" casing - -Line 22 uses `Orderbook` (lowercase b) and line 75 also uses `Orderbook`. The contract type is consistently `OrderBook` (capital B) everywhere else. This is a minor doc inconsistency. Flagged in prior passes. - -### A04-P4-4 [INFO] Well-placed slither disable annotation - -Line 63 has a `//slither-disable-next-line arbitrary-send-erc20` with a thorough multi-line comment (lines 50-62) explaining exactly why the slither finding is a false positive. This is good practice. - -### A04-P4-5 [INFO] No bare `src/` import paths - -All import paths use remapped dependency names. Correct for submodule usage. - -### A04-P4-6 [INFO] No commented-out code - -No commented-out code found. - -### A04-P4-7 [INFO] No dead code - -All errors, constants, and functions are used. `FLASH_FEE` is referenced at lines 45 and 64. `FlashLenderCallbackFailed` is referenced at line 47. - -### A04-P4-8 [INFO] No leaky abstractions or tight coupling - -The contract depends only on the ERC-3156 interfaces and OpenZeppelin utilities. It does not reference the orderbook-specific types (`TakeOrdersConfigV5`, `TaskV2`, etc.), keeping a clean separation of concerns. The `maxFlashLoan` implementation correctly delegates to `balanceOf(address(this))`, allowing any concrete contract to accumulate tokens as it sees fit. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A04-P4-1 | INFO | Clean import hygiene (good) | -| A04-P4-2 | INFO | Style consistency on pragma (good) | -| A04-P4-3 | INFO | Minor "Orderbook" vs "OrderBook" casing in NatSpec | -| A04-P4-4 | INFO | Well-placed slither disable annotation (good) | -| A04-P4-5 | INFO | No bare `src/` import paths (good) | -| A04-P4-6 | INFO | No commented-out code (good) | -| A04-P4-7 | INFO | No dead code (good) | -| A04-P4-8 | INFO | No leaky abstractions (good) | diff --git a/audit/2026-03-13-01/pass4/OrderBookV6SubParser.md b/audit/2026-03-13-01/pass4/OrderBookV6SubParser.md deleted file mode 100644 index e0ee14efc8..0000000000 --- a/audit/2026-03-13-01/pass4/OrderBookV6SubParser.md +++ /dev/null @@ -1,52 +0,0 @@ -# Pass 4: Code Quality -- OrderBookV6SubParser.sol - -**Agent:** A09 -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` (307 lines) - -## Evidence of Thorough Reading - -- Contract `OrderBookV6SubParser` extends `BaseRainterpreterSubParser` (line 71) -- `using LibUint256Matrix for uint256[][]` (line 72) -- `describedByMetaV1()` returns `DESCRIBED_BY_META_HASH` from generated pointers (line 75-77) -- Three `virtual override` functions: `subParserParseMeta`, `subParserWordParsers`, `subParserOperandHandlers` (lines 80-92) -- `buildLiteralParserFunctionPointers()` returns empty bytes (lines 95-97) -- `buildOperandHandlerFunctionPointers()` builds handler arrays for 7 context columns + 2 extension (deposit/withdraw), allocating `CONTEXT_COLUMNS + 2 + 1 + 1` (line 105) -- `buildSubParserWordParsers()` builds parser arrays mirroring the operand handlers structure (lines 186-306) -- Two inline assembly blocks both annotated `"memory-safe"` for type-punning function pointer arrays to `uint256[][]` (lines 179-181, 301-303) -- Imports `SUB_PARSER_WORD_PARSERS_LENGTH` from `LibOrderBookSubParser.sol` but never references it in any expression or statement in the contract body - -## Findings - -### P4-A09-01 (LOW): Unused Import `BadDynamicLength` - -**Line:** 12 -**Details:** `BadDynamicLength` is imported from `rain.interpreter/error/ErrOpList.sol` but never referenced anywhere in the contract body. No function throws it, no expression uses it. This is dead code that inflates the import list. - -### P4-A09-02 (LOW): Unused Import `LibExternOpContextSender` - -**Line:** 13 -**Details:** `LibExternOpContextSender` is imported from `rain.interpreter/lib/extern/reference/op/LibExternOpContextSender.sol` but is never used in the contract. No function calls or references it. - -### P4-A09-03 (LOW): Unused Import `SUB_PARSER_WORD_PARSERS_LENGTH` - -**Line:** 18 -**Details:** `SUB_PARSER_WORD_PARSERS_LENGTH` is imported from `LibOrderBookSubParser.sol` but never used in the contract body. It is only listed in the import block. - -### P4-A09-04 (INFO): Magic Number `CONTEXT_COLUMNS + 2 + 1 + 1` - -**Lines:** 105, 194 -**Details:** The expression `CONTEXT_COLUMNS + 2 + 1 + 1` appears in two places with inline comments explaining the `+2` (signers and signed context start), `+1` (deposit context), and `+1` (withdraw context). While the comments are adequate, this could be extracted to a named constant for consistency and to avoid potential divergence between the two usages. The same magic expression also appears in `LibOrderBookSubParser.authoringMetaV2()` (line 373). - -### P4-A09-05 (INFO): Style Consistency of Assembly Annotations - -Both assembly blocks in this file use `("memory-safe")`, which is consistent. This is noted positively; no issue. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| P4-A09-01 | LOW | Unused import `BadDynamicLength` | -| P4-A09-02 | LOW | Unused import `LibExternOpContextSender` | -| P4-A09-03 | LOW | Unused import `SUB_PARSER_WORD_PARSERS_LENGTH` | -| P4-A09-04 | INFO | Repeated magic expression `CONTEXT_COLUMNS + 2 + 1 + 1` | -| P4-A09-05 | INFO | Assembly annotation style is consistent (positive) | diff --git a/audit/2026-03-13-01/pass4/RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass4/RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index cc9c03bbf0..0000000000 --- a/audit/2026-03-13-01/pass4/RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,157 +0,0 @@ -# Pass 4: Code Quality -- RouteProcessorOrderBookV6ArbOrderTaker.sol - -**Agent:** A07 -**File:** `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` -**Date:** 2026-03-13 - -## Evidence of Thorough Reading - -### Contract Structure -- **License:** `LicenseRef-DCL-1.0` (line 1), copyright 2020 Rain Open Source Software Ltd (line 2) -- **Pragma:** `=0.8.25` (line 3) -- pinned, consistent with all concrete contracts -- **Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (line 14), inherits `OrderBookV6ArbOrderTaker` -- **State:** `iRouteProcessor` (line 18) -- `IRouteProcessor public immutable` -- **Using declarations:** `SafeERC20 for IERC20` (line 15), `Address for address` (line 16) -- **Constructor:** lines 20-23, decodes `config.implementationData` as `(address routeProcessor)`, sets `iRouteProcessor` -- **`onTakeOrders2`:** lines 26-49, public virtual override, calls super, approves route processor, decodes route, converts Float amounts to fixed decimal, calls `processRoute`, revokes approval -- **`fallback()`:** line 52, external, non-payable, empty body - -### Imports (lines 5-12) -| Import | Source | Used in this file? | -|---|---|---| -| `IRouteProcessor` | `sushixswap-v2/src/interfaces/IRouteProcessor.sol` | Yes (line 18, 34, 44, 47) | -| `IERC20` | `openzeppelin-contracts/contracts/token/ERC20/IERC20.sol` | Yes (lines 34, 47) | -| `SafeERC20` | `openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol` | Yes (line 15) | -| `Address` | `openzeppelin-contracts/contracts/utils/Address.sol` | **NO** -- declared as `using` but never called | -| `OrderBookV6ArbOrderTaker` | `../../abstract/OrderBookV6ArbOrderTaker.sol` | Yes (line 14 -- inheritance, line 33 -- super call) | -| `OrderBookV6ArbConfig` | `../../abstract/OrderBookV6ArbOrderTaker.sol` | Yes (line 20 -- constructor parameter) | -| `Float` | `../../abstract/OrderBookV6ArbOrderTaker.sol` | Yes (lines 29, 30 -- function parameters) | -| `LibDecimalFloat` | `rain.math.float/lib/LibDecimalFloat.sol` | Yes (lines 37, 40) | -| `IERC20Metadata` | `openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol` | Yes (lines 37, 40) | - -### Line-by-line observations -- Line 16: `using Address for address;` -- declared but the `Address` library methods (`.functionCall`, `.functionCallWithValue`, `.sendValue`, `.isContract`) are never called anywhere in the contract. This contract calls `iRouteProcessor.processRoute(...)` directly via the interface, not via `Address.functionCallWithValue`. -- Line 21: `(address routeProcessor) = abi.decode(config.implementationData, (address));` -- unnecessary parentheses around `address routeProcessor` (valid syntax but unusual; `address routeProcessor = abi.decode(...)` is more conventional). -- Line 33: `super.onTakeOrders2(...)` -- calls parent no-op (same as A05 sibling). -- Line 38: `(losslessInputAmount);` -- suppresses unused variable warning. Deliberate discard of the lossy flag for input. -- Line 48: `(amountOut);` -- suppresses unused variable warning for route processor return value. - ---- - -## Code Quality Review - -### 1. Style Consistency - -**Pragma:** `=0.8.25`, consistent with all concrete contracts. - -**Import style:** Direct imports from original sources (`openzeppelin-contracts/`, `sushixswap-v2/`, `rain.math.float/`) plus relative imports for local abstracts (`../../abstract/`). Consistent with `GenericPoolOrderBookV6ArbOrderTaker` sibling. - -**Variable naming:** `inputToken`, `outputToken`, `inputAmountSent`, `totalOutputAmount`, `route`, `inputTokenAmount`, `outputTokenAmount`, `amountOut` -- clear and descriptive. - -**Naming convention:** `iRouteProcessor` uses the project's `i` prefix convention for immutable state variables, consistent with `iTaskHash` in the parent. - -### 2. Leaky Abstractions - -No leaky abstractions detected. - -### 3. Commented-Out Code - -No commented-out code in this file. - -### 4. Build Warnings - -No expected build warnings. Unused variables are suppressed with the `(varName);` pattern. - -However, the unused `Address` import and `using Address for address` declaration may trigger a compiler warning in some configurations (Solidity does not warn on unused `using` declarations, but some linters do). - -### 5. Dependency Consistency - -**`sushixswap-v2` import path:** Line 5 imports `IRouteProcessor` from `sushixswap-v2/src/interfaces/IRouteProcessor.sol`. This path relies on Foundry's automatic `lib/` discovery since there is no explicit remapping for `sushixswap-v2` in `foundry.toml`. All other external dependencies (`openzeppelin-contracts`, `rain.interpreter.interface`, `rain.raindex.interface`, `rain.math.float`, etc.) have explicit remappings. The inconsistency means this import would break if the submodule were moved or if the project switched to a different dependency resolution strategy. - -No bare `src/` imports (all local imports use relative `../../` paths). - -### 6. Dead Code - -**Unused import and using declaration:** - -- **Line 8:** `Address` is imported from `openzeppelin-contracts/contracts/utils/Address.sol` -- **Line 16:** `using Address for address;` is declared - -Neither `Address.functionCall`, `Address.functionCallWithValue`, `Address.sendValue`, nor any other `Address` library method is called anywhere in this contract. The sibling `GenericPoolOrderBookV6ArbOrderTaker` uses `pool.functionCallWithValue(...)` which justifies its `Address` import. This contract instead calls `iRouteProcessor.processRoute(...)` directly via the typed interface, making the `Address` library entirely unnecessary. - ---- - -## Findings - -### A07-P4-1 [LOW] Unused import `Address` and unused `using Address for address` declaration - -**Location:** Lines 8, 16 - -**Description:** -`Address` from OpenZeppelin is imported (line 8) and declared as a using-for directive (line 16), but no `Address` library method is ever called in this contract. The sibling `GenericPoolOrderBookV6ArbOrderTaker` calls `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` which requires the `Address` library. This contract instead calls `iRouteProcessor.processRoute(...)` through the typed `IRouteProcessor` interface, so `Address` is dead code. - -This likely originated from copying the sibling contract's boilerplate when creating the route processor variant, without removing the now-unnecessary dependency. - -**Recommendation:** Remove both the import and the using declaration: -```solidity -// DELETE line 8: import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; -// DELETE line 16: using Address for address; -``` - -### A07-P4-2 [LOW] No explicit remapping for `sushixswap-v2` dependency - -**Location:** Line 5 - -**Description:** -The import `sushixswap-v2/src/interfaces/IRouteProcessor.sol` relies on Foundry's automatic `lib/` directory discovery. Every other external dependency in `foundry.toml` has an explicit remapping entry: -- `openzeppelin-contracts/=lib/rain.raindex.interface/lib/...` -- `rain.interpreter.interface/=lib/rain.raindex.interface/lib/...` -- `rain.math.float/=lib/rain.raindex.interface/lib/...` -- etc. - -But `sushixswap-v2` has no remapping in `foundry.toml`. This inconsistency means: -1. The dependency resolution is implicit and could break if the lib directory structure changes. -2. The import path includes `src/` (i.e., `sushixswap-v2/src/interfaces/...`), which is slightly different from the project's convention of remapping to point into the `src/` directory so imports omit it (e.g., `rain.math.float/lib/LibDecimalFloat.sol` not `rain.math.float/src/lib/LibDecimalFloat.sol`). - -**Recommendation:** Add a remapping to `foundry.toml`: -```toml -"sushixswap-v2/=lib/sushixswap-v2/" -``` -Or, if the convention is to remap into `src/`: -```toml -"sushixswap-v2/=lib/sushixswap-v2/src/" -``` -and update the import to: -```solidity -import {IRouteProcessor} from "sushixswap-v2/interfaces/IRouteProcessor.sol"; -``` - -### A07-P4-3 [INFO] Redundant `super.onTakeOrders2` call to no-op parent - -**Location:** Line 33 - -**Description:** -Same pattern as A05-P4-1. The `super.onTakeOrders2(...)` call delegates to the parent which has an empty body. This is a defensive pattern that is correct but currently a no-op. Consistent with sibling contract. No fix recommended. - -### A07-P4-4 [INFO] Unnecessary parentheses in constructor variable declaration - -**Location:** Line 21 - -**Description:** -```solidity -(address routeProcessor) = abi.decode(config.implementationData, (address)); -``` -The parentheses around `address routeProcessor` on the left side of the assignment are unnecessary. The conventional style for a single return value is: -```solidity -address routeProcessor = abi.decode(config.implementationData, (address)); -``` -The parenthesized form is typically used for tuple destructuring of multiple return values. Using it for a single value is not wrong but is unconventional and mildly misleading (suggests multiple return values). This is a minor style nit. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A07-P4-1 | LOW | Unused import `Address` and unused `using Address for address` declaration | -| A07-P4-2 | LOW | No explicit remapping for `sushixswap-v2` dependency | -| A07-P4-3 | INFO | Redundant `super.onTakeOrders2` call to no-op parent | -| A07-P4-4 | INFO | Unnecessary parentheses in constructor variable declaration | diff --git a/audit/2026-03-13-01/pass5/A05-GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass5/A05-GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 5f9bad2f83..0000000000 --- a/audit/2026-03-13-01/pass5/A05-GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,76 +0,0 @@ -# Pass 5: Correctness -- GenericPoolOrderBookV6ArbOrderTaker.sol - -**Agent:** A05 - -**File:** `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` (39 lines) - -## Evidence of Thorough Reading - -- **Imports (lines 1-9):** IERC20, SafeERC20, Address from OpenZeppelin; OrderBookV6ArbOrderTaker, OrderBookV6ArbConfig, Float from abstract parent. -- **Contract declaration (line 11):** Inherits `OrderBookV6ArbOrderTaker`. -- **Using directives (lines 12-13):** `SafeERC20 for IERC20`, `Address for address`. -- **Constructor (line 15):** Passes config to parent. -- **`onTakeOrders2` override (lines 18-35):** Calls super, decodes `takeOrdersData` into `(spender, pool, encodedFunctionCall)`, approves spender for max, calls pool with full ETH balance, zeros approval. -- **fallback (line 38):** `fallback() external {}` with comment "Allow receiving gas." - -## Verification Results - -### 1. NatSpec / Comment vs Implementation - -#### FINDING A05-P5-01: Misleading "Allow receiving gas" comment on non-payable fallback [LOW] - -**Location:** Line 37-38 - -```solidity -/// Allow receiving gas. -fallback() external {} -``` - -The `fallback()` is NOT marked `payable`. In Solidity 0.8.25, a non-payable `fallback()` will revert on any call that includes `msg.value > 0`. There is also no `receive()` function. The contract therefore CANNOT receive ETH/gas through the fallback. - -The contract CAN receive ETH via the `arb5` entrypoint (which is `payable` in the parent), but the fallback itself does not "allow receiving gas" as claimed. The fallback's actual purpose is to accept arbitrary calldata from pool callbacks (without value) without reverting. - -**Impact:** Misleading developer documentation. If an external pool attempts to refund ETH to this contract via a call, it will revert. - -**Recommendation:** Either make the fallback `payable` to match the comment, or update the comment to describe what the fallback actually does: - -```solidity -/// Accept arbitrary calldata from pool callbacks without reverting. -fallback() external {} -``` - -### 2. Function Behavior Verification - -**`onTakeOrders2`:** -- `super.onTakeOrders2(...)` calls the parent's no-op implementation. Correct. -- `abi.decode(takeOrdersData, (address, address, bytes))` decodes spender, pool, and encoded call. Matches the GenericPool pattern described in the FlashBorrower NatSpec. -- `forceApprove(spender, type(uint256).max)` then `forceApprove(spender, 0)`: approve-use-revoke pattern. Correct. -- `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)`: Forwards all ETH balance to pool. Correct. -- `(returnData);` silences the unused variable warning. Comment explains why: `takeOrders` does not support return data. Accurate. - -### 3. Test Name vs Test Behavior - -**`testGenericPoolTakeOrdersSender`** (sender.t.sol): Calls `arb5` with a valid task and empty expression. Tests the basic happy path through the sender flow. Name matches behavior. - -**`testGenericPoolTakeOrdersWrongExpression`** (expression.t.sol): Fuzzes evaluable parameters that differ from the configured task, expects `WrongTask` revert. Name matches behavior. - -**`testGenericPoolTakeOrdersExpression`** (expression.t.sol): Tests with matching expression, mocks interpreter eval, verifies eval is called and KV store set is called when kvs are non-empty. Name matches behavior. - -### 4. Error Conditions - -No custom errors defined in this file. Errors are inherited from parent: -- `NoOrders` if `takeOrders.orders.length == 0` (in parent `arb5`). -- `WrongTask` if task hash doesn't match (in `onlyValidTask` modifier). -- OZ `Address.functionCallWithValue` reverts if pool call fails. - -All triggered correctly. - -### 5. Constructor - -Passes `config` directly to parent. No implementation-specific data decoded. Correct for GenericPool (no additional config needed). - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A05-P5-01 | LOW | Misleading "Allow receiving gas" comment on non-payable fallback | diff --git a/audit/2026-03-13-01/pass5/A06-GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass5/A06-GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index 8bdd821af3..0000000000 --- a/audit/2026-03-13-01/pass5/A06-GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,99 +0,0 @@ -# Pass 5: Correctness -- GenericPoolOrderBookV6FlashBorrower.sol - -**Agent:** A06 - -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` (49 lines) - -## Evidence of Thorough Reading - -- **Imports (lines 1-15):** IERC3156FlashLender, IERC3156FlashBorrower; OrderBookV6FlashBorrower with re-exports of SafeERC20, IERC20, Address, TakeOrdersConfigV5, OrderBookV6ArbConfig. -- **NatSpec (lines 17-26):** Title, description of GenericPool exchange pattern (spender, pool, callData). -- **Contract declaration (line 27):** Inherits `OrderBookV6FlashBorrower`. -- **Using directives (lines 28-29):** `SafeERC20 for IERC20`, `Address for address`. -- **Constructor (line 31):** Passes config to parent. -- **`_exchange` override (lines 33-45):** Decodes exchangeData into (spender, pool, encodedFunctionCall), determines borrowedToken from order outputs, approves spender, calls pool with ETH balance, zeros approval. -- **fallback (line 48):** `fallback() external {}` with comment "Allow receiving gas." - -## Verification Results - -### 1. NatSpec / Comment vs Implementation - -#### FINDING A06-P5-01: Misleading "Allow receiving gas" comment on non-payable fallback [LOW] - -**Location:** Line 47-48 - -```solidity -/// Allow receiving gas. -fallback() external {} -``` - -Same issue as A05-P5-01. The `fallback()` is NOT `payable` and there is no `receive()` function. The contract cannot receive ETH through the fallback. ETH enters only via the `payable` `arb4` entrypoint. - -**Impact:** Misleading developer documentation. If a pool tries to refund ETH back to this contract, the call reverts. - -**Recommendation:** Either make the fallback `payable` or correct the comment. - -#### FINDING A06-P5-02: Stale NatSpec references to V5 in abstract parent [INFO] - -**Location:** `src/abstract/OrderBookV6FlashBorrower.sol` lines 32, 124, 128 - -The abstract parent `OrderBookV6FlashBorrower.sol` (which A06 inherits) contains stale NatSpec: -- Line 32: `@title OrderBookV5FlashBorrower` -- should be `OrderBookV6FlashBorrower` -- Line 33: "specifialized" -- typo for "specialized" -- Line 124: `@param takeOrders As per IOrderBookV5.takeOrders3` -- should reference V6/current interface -- Line 128: `GenericPoolOrderBookV5FlashBorrower` -- should be `GenericPoolOrderBookV6FlashBorrower` - -These are in the abstract parent, not the concrete file itself, but directly affect the inherited documentation of A06. - -**Impact:** Confusing for developers reading the inherited NatSpec. - -### 2. Function Behavior Verification - -**`_exchange`:** -- `abi.decode(exchangeData, (address, address, bytes))`: Decodes spender, pool, encoded function call. Matches NatSpec description. -- `borrowedToken = takeOrders.orders[0].order.validOutputs[...].token`: Correct -- the flash-borrowed token is the order's output (= taker's input). The flash loan borrows this token; `_exchange` must swap it into the order's input token. -- `forceApprove(spender, type(uint256).max)` / `forceApprove(spender, 0)`: Approve-use-revoke pattern. Correct. -- `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)`: Forwards all ETH to pool. Correct. -- `(returnData);`: Silences unused warning. Comment: "as 3156 does not support it." Accurate. - -### 3. Test Name vs Test Behavior - -**`testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender`** (sender.t.sol): Calls `arb4` with valid config, empty expression, exchange data encoding `(iRefundoor, iRefundoor, "")`. Tests basic happy path. Name matches behavior. - -**Note:** No expression test exists for FlashBorrower (unlike ArbOrderTaker which has expression.t.sol). The task validation is tested indirectly through the `onlyValidTask` modifier in the parent, which is the same for both. - -### 4. Error Conditions - -No custom errors defined in this concrete file. Inherited from parent/library: -- `BadInitiator(address)` in `onFlashLoan` if `initiator != address(this)`. -- `FlashLoanFailed()` if `flashLoan` returns false. -- `NoOrders` if `takeOrders.orders.length == 0`. -- `WrongTask` via `onlyValidTask` modifier. - -All triggered correctly in the abstract parent. - -### 5. `_exchange` Token Identification - -The `_exchange` function correctly identifies `borrowedToken` as `validOutputs[outputIOIndex].token`, which is the order's output token (= the token the flash loan provides). This token is approved for the spender so the pool can pull it during the swap. Correct. - -### 6. Flash Loan Flow Integrity - -The flash loan flow in `arb4` (parent): -1. Borrows `ordersOutputToken` from orderbook. -2. `_exchange` swaps borrowed token for `ordersInputToken` via external pool. -3. `onFlashLoan` takes orders using `ordersInputToken`, receiving `ordersOutputToken` back. -4. `ordersOutputToken` repays the flash loan. -5. `finalizeArb` sweeps remaining tokens and gas to `msg.sender`. - -This is logically sound. - -### 7. Import of unused interface - -Line 5 imports `IERC3156FlashLender` but it is not used anywhere in this file. This is a minor cleanliness issue. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A06-P5-01 | LOW | Misleading "Allow receiving gas" comment on non-payable fallback | -| A06-P5-02 | INFO | Stale NatSpec references to V5 in abstract parent | diff --git a/audit/2026-03-13-01/pass5/A07-RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass5/A07-RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index efbc43a4d7..0000000000 --- a/audit/2026-03-13-01/pass5/A07-RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,140 +0,0 @@ -# Pass 5: Correctness -- RouteProcessorOrderBookV6ArbOrderTaker.sol - -**Agent:** A07 - -**File:** `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` (53 lines) - -## Evidence of Thorough Reading - -- **Imports (lines 1-12):** IRouteProcessor from sushixswap-v2; IERC20, SafeERC20, Address from OpenZeppelin; OrderBookV6ArbOrderTaker, OrderBookV6ArbConfig, Float from abstract parent; LibDecimalFloat from rain.math.float; IERC20Metadata from OpenZeppelin. -- **Contract declaration (line 14):** Inherits `OrderBookV6ArbOrderTaker`. -- **Using directives (lines 15-16):** `SafeERC20 for IERC20`, `Address for address`. -- **Immutable state (line 18):** `IRouteProcessor public immutable iRouteProcessor`. -- **Constructor (lines 20-23):** Decodes `routeProcessor` address from `config.implementationData`, assigns to immutable. -- **`onTakeOrders2` override (lines 25-49):** Calls super, approves route processor, decodes route from `takeOrdersData`, converts `inputAmountSent` to fixed decimal (lossy, discards lossless flag), converts `totalOutputAmount` to fixed decimal (lossy, increments if lossy), calls `processRoute`, zeros approval. -- **fallback (line 52):** `fallback() external {}` with comment "Allow receiving gas." - -## Verification Results - -### 1. Lossy Conversion Logic -- Correctness Analysis - -#### Input Amount Conversion (lines 36-38) - -```solidity -(uint256 inputTokenAmount, bool losslessInputAmount) = - LibDecimalFloat.toFixedDecimalLossy(inputAmountSent, IERC20Metadata(inputToken).decimals()); -(losslessInputAmount); -``` - -`inputAmountSent` is the amount of `inputToken` the arb contract received from `takeOrders4`. Converting lossily means the fixed-decimal `inputTokenAmount` may be truncated (rounded down). The `losslessInputAmount` flag is silently discarded. - -**Effect:** If lossy, the contract passes slightly fewer tokens to the route processor than it actually holds. The remaining dust stays in the arb contract and is swept to `msg.sender` by `finalizeArb`. This is economically suboptimal (less input = potentially less output from the swap) but not dangerous. The route processor will only pull the approved amount or what it needs, so no funds are at risk. - -**Verdict:** Acceptable design choice. Rounding down input is the safe direction -- the contract never tries to send more than it has. - -#### Output Amount Conversion (lines 39-43) - -```solidity -(uint256 outputTokenAmount, bool lossless) = - LibDecimalFloat.toFixedDecimalLossy(totalOutputAmount, IERC20Metadata(outputToken).decimals()); -if (!lossless) { - outputTokenAmount++; -} -``` - -`totalOutputAmount` is the total amount of `outputToken` the arb contract must return to the orderbook. This is used as `amountOutMin` in `processRoute`. Rounding UP on lossy conversion is CORRECT: the arb must receive at least enough output to satisfy the orderbook. If the float-to-fixed conversion truncates, adding 1 ensures the minimum output requirement is met. - -**Verdict:** Correct. Conservative rounding in the right direction. - -### 2. NatSpec / Comment vs Implementation - -#### FINDING A07-P5-01: Misleading "Allow receiving gas" comment on non-payable fallback [LOW] - -**Location:** Line 51-52 - -```solidity -/// Allow receiving gas. -fallback() external {} -``` - -Same issue as A05-P5-01 and A06-P5-01. The `fallback()` is NOT `payable` and there is no `receive()` function. The contract cannot receive ETH through the fallback. - -**Impact:** Misleading developer documentation. - -**Recommendation:** Either make the fallback `payable` or correct the comment. - -### 3. `processRoute` Parameter Mapping - -The call to `iRouteProcessor.processRoute`: - -```solidity -iRouteProcessor.processRoute( - inputToken, // tokenIn - inputTokenAmount, // amountIn - outputToken, // tokenOut - outputTokenAmount, // amountOutMin - address(this), // to (receive output back to this contract) - route // route data -); -``` - -Verified against `IRouteProcessor` interface: -```solidity -function processRoute( - address tokenIn, - uint256 amountIn, - address tokenOut, - uint256 amountOutMin, - address to, - bytes memory route -) external payable returns (uint256 amountOut); -``` - -All parameters map correctly: -- `tokenIn` = `inputToken` (the token the arb received from taking orders) -- `amountIn` = `inputTokenAmount` (lossy conversion of float amount, rounded down = safe) -- `tokenOut` = `outputToken` (the token the arb needs to return) -- `amountOutMin` = `outputTokenAmount` (lossy conversion rounded up = conservative) -- `to` = `address(this)` (output goes back to arb contract for `finalizeArb` sweep) -- `route` = decoded from `takeOrdersData` - -**Verdict:** Correct parameter mapping. - -### 4. Function Behavior Verification - -**Constructor:** -- Decodes `routeProcessor` from `config.implementationData`. No zero-address validation, but misconfiguration would simply fail on first use. Acceptable for an immutable deployed once. - -**`onTakeOrders2`:** -- `super.onTakeOrders2(...)`: Calls parent's no-op. Correct. -- `forceApprove(address(iRouteProcessor), type(uint256).max)` / `forceApprove(address(iRouteProcessor), 0)`: Approve-use-revoke pattern. Correct. -- `route = abi.decode(takeOrdersData, (bytes))`: Decodes route bytes. Correct. -- `(amountOut);`: Silences unused return value warning. Acceptable -- the route processor's output amount is not used; the orderbook enforces minimums separately. - -### 5. Test Name vs Test Behavior - -**`testRouteProcessorTakeOrdersSender`** (sender.t.sol): Calls `arb5` with valid config, empty expression, route data `bytes("0x00")`. Tests basic happy path. Name matches behavior. - -**`testRouteProcessorTakeOrdersWrongExpression`** (expression.t.sol): Fuzzes evaluable that differs from configured task, expects `WrongTask` revert. Name matches behavior. - -**`testRouteProcessorTakeOrdersExpression`** (expression.t.sol): Tests with matching expression, mocks interpreter eval, verifies eval and KV store interactions. Name matches behavior. - -### 6. Error Conditions - -No custom errors defined in this file. Inherited from parent: -- `NoOrders` if `takeOrders.orders.length == 0` (in parent `arb5`). -- `WrongTask` via `onlyValidTask` modifier. -- `NegativeFixedDecimalConversion` if float amounts are negative (from `LibDecimalFloat`). -- Route processor call failures bubble up via OZ `Address` or direct revert. - -All triggered correctly. - -### 7. IERC20Metadata.decimals() External Call - -Lines 37 and 40 call `IERC20Metadata(inputToken).decimals()` and `IERC20Metadata(outputToken).decimals()`. These are external calls to the token contracts during the callback. If a token does not implement `decimals()`, this will revert. However, the parent contract `arb5` also uses `LibTOFUTokenDecimals.safeDecimalsForToken` for the same tokens in `finalizeArb`, so tokens without `decimals()` would fail there too. The use of a different decimals-fetching mechanism (`IERC20Metadata` vs `LibTOFUTokenDecimals`) is notable but both should return the same value for standard tokens. - -## Summary - -| ID | Severity | Title | -|----|----------|-------| -| A07-P5-01 | LOW | Misleading "Allow receiving gas" comment on non-payable fallback | diff --git a/audit/2026-03-13-01/pass5/Deploy.md b/audit/2026-03-13-01/pass5/Deploy.md deleted file mode 100644 index e801be7c57..0000000000 --- a/audit/2026-03-13-01/pass5/Deploy.md +++ /dev/null @@ -1,145 +0,0 @@ -# Pass 5: Correctness -- Deploy.sol - -**Agent:** A15 -**File:** `script/Deploy.sol` - -## Evidence of Thorough Reading - -**Contract name:** `Deploy` (inherits `Script` from forge-std), lines 46-176. - -**Line-by-line verification inventory:** - -| Element | Lines | Verified | -|---|---|---| -| `DEPLOYMENT_SUITE_ALL = keccak256("all")` | 24 | String matches constant name suffix | -| `DEPLOYMENT_SUITE_RAINDEX = keccak256("raindex")` | 25 | String matches constant name suffix | -| `DEPLOYMENT_SUITE_SUBPARSER = keccak256("subparser")` | 26 | String matches constant name suffix | -| `DEPLOYMENT_SUITE_ROUTE_PROCESSOR = keccak256("route-processor")` | 27 | String matches constant name suffix | -| `DEPLOYMENT_SUITE_ARB = keccak256("arb")` | 28 | String matches constant name suffix | -| `ROUTE_PROCESSOR_4_CREATION_CODE` | 38-39 | Hex literal present, constructor args decoded below | -| `ROUTE_PROCESSOR_4_BYTECODE_HASH` | 41-42 | Compared against `extcodehash` at runtime | -| `BadRouteProcessor(bytes32 expected, bytes32 actual)` | 44 | Error signature matches usage at line 134 | -| `sDepCodeHashes` | 50 | Used as pass-through to `LibRainDeploy.deployAndBroadcast` | -| `deployRouter()` | 52-59 | Assembly verified (see below) | -| `run()` | 61-175 | Suite branching verified (see below) | - -**Assembly verification (`deployRouter()`, line 55-57):** -- `create(0, add(routeProcessor4Code, 0x20), mload(routeProcessor4Code))` is the standard pattern for deploying from a `bytes memory` variable. -- `value = 0`: no ETH sent with deployment. Correct for RouteProcessor4 which does not require constructor value. -- `offset = add(routeProcessor4Code, 0x20)`: skips the 32-byte ABI length prefix to point at actual bytecode. Correct. -- `size = mload(routeProcessor4Code)`: reads the length from the first 32 bytes of the memory pointer. Correct. -- `"memory-safe"` annotation: the block only reads memory and writes to a stack variable. Correct. - -**Constructor args verification (trailing bytes of `ROUTE_PROCESSOR_4_CREATION_CODE`):** -The last 96 bytes (3 words) of the hex literal decode as ABI-encoded constructor arguments for `constructor(address _bentoBox, address[] memory _privilegedUsers)`: -- Word 0: `0x0...0` = `address(0)` -- bentoBox parameter (no bento). Matches comment on line 36. -- Word 1: `0x0...40` = 64 -- byte offset to the dynamic array data. Correct ABI encoding. -- Word 2: `0x0...0` = 0 -- array length (empty privileged users array). Matches comment on line 37 ("no owner addresses"). - -**DEPLOYMENT_SUITE_* constant/string consistency:** -All five constants use `keccak256("...")` where the string inside the hash exactly matches the lowercase, hyphenated suffix of the constant name (e.g., `DEPLOYMENT_SUITE_ROUTE_PROCESSOR` hashes `"route-processor"`, not `"route_processor"`). The default `suiteString` at line 64 is `"all"`, which matches `DEPLOYMENT_SUITE_ALL`. Verified correct. - -**Suite branching logic (line-by-line flow analysis):** - -| Suite value | Raindex block (L70) | Subparser block (L94) | Route processor deploy (L122) | Bytecode check (L129) | Arb block (L137) | -|---|---|---|---|---|---| -| `"all"` | YES | YES | YES (if env not set) | YES | YES | -| `"raindex"` | YES | NO | NO | YES (BUG) | NO | -| `"subparser"` | NO | YES | NO | YES (BUG) | NO | -| `"route-processor"` | NO | NO | YES | YES | NO | -| `"arb"` | NO | NO | NO | YES | YES | - -**`DEPLOYMENT_SUITE_ALL` completeness check:** -When `suite == "all"`, every gated block's condition includes `suite == DEPLOYMENT_SUITE_ALL`: -- Line 70: `suite == DEPLOYMENT_SUITE_RAINDEX || suite == DEPLOYMENT_SUITE_ALL` -- YES -- Line 94: `suite == DEPLOYMENT_SUITE_SUBPARSER || suite == DEPLOYMENT_SUITE_ALL` -- YES -- Line 122-123: `suite == DEPLOYMENT_SUITE_ROUTE_PROCESSOR || (suite == DEPLOYMENT_SUITE_ALL && routeProcessor == address(0))` -- YES (conditionally) -- Line 137: `suite == DEPLOYMENT_SUITE_ARB || suite == DEPLOYMENT_SUITE_ALL` -- YES - -All four deployment blocks are entered. The `all` suite deploys: OrderBookV6, OrderBookV6SubParser, RouteProcessor4 (if not pre-deployed), GenericPoolOrderBookV6ArbOrderTaker, RouteProcessorOrderBookV6ArbOrderTaker, and GenericPoolOrderBookV6FlashBorrower. This is all contracts. Verified correct. - -**`BadRouteProcessor` trigger condition verification:** -- Line 129-131: `extcodehash(routeProcessor)` is computed via assembly. -- Line 133: compared against `ROUTE_PROCESSOR_4_BYTECODE_HASH`. -- Line 134: reverts with `BadRouteProcessor(ROUTE_PROCESSOR_4_BYTECODE_HASH, routeProcessor4BytecodeHash)` -- first arg is expected, second is actual. Matches the error signature at line 44. Correct. - -**`ROUTE_PROCESSOR_4_BYTECODE_HASH` vs `ROUTE_PROCESSOR_4_CREATION_CODE` consistency:** -`ROUTE_PROCESSOR_4_BYTECODE_HASH` is the `extcodehash` (keccak256 of runtime bytecode), not the hash of the creation code. The runtime bytecode is produced by executing the creation code, so the hash cannot be verified statically from the hex literal alone. The only verification is at runtime (lines 129-135) or by deploying in a test and checking. No test currently does this (as noted in Pass 2). The hash value `0xeb3745a79c6ba48e8767b9c355b8e7b79f9d6edeca004e4bb91be4de515a7eeb` is a plausible keccak256 output. Without WebFetch access, I cannot cross-reference against the etherscan deployment, but the provenance comment on the creation code references verifiable sources. - -## Findings - -### A15-P5-1 [HIGH] Unconditional route processor bytecode check blocks `raindex`, `subparser`, and `route-processor` suites (confirms A15-1) - -**Location:** Lines 90-92, 129-135 - -This finding confirms and extends Pass 1 finding A15-1. The `extcodehash` check at lines 129-135 runs unconditionally for all suite values. Additionally, the `vm.envAddress("DEPLOY_RAINDEX_ADDRESS")` call at line 91 also runs unconditionally when `raindex == address(0)` (which is true for all suites except `raindex` and `all`). - -The combined effect is: - -1. **`raindex` suite:** Line 70 fires, sets `raindex`. Line 90 check is false (skips env read). But lines 129-135 still run unconditionally. If `DEPLOY_ROUTE_PROCESSOR_4_ADDRESS` is not set, `routeProcessor` is `address(0)`, and `extcodehash(address(0))` returns the empty account hash (`0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`), which does not equal `ROUTE_PROCESSOR_4_BYTECODE_HASH`. The script reverts with `BadRouteProcessor`. The `raindex` suite has no dependency on the route processor. - -2. **`subparser` suite:** Line 70 is false, so `raindex` stays `address(0)`. Line 90 forces `vm.envAddress("DEPLOY_RAINDEX_ADDRESS")` which reverts if unset. Even if set, the unconditional bytecode check still applies. - -3. **`route-processor` suite:** Line 70 is false. Line 90 forces `vm.envAddress("DEPLOY_RAINDEX_ADDRESS")` which reverts if unset. The route-processor suite deploys a route processor but has no dependency on `raindex`. - -The route processor bytecode check (lines 129-135) and the `raindex` fallback read (lines 90-92) should both be gated to only execute when the relevant suite requires them: -- The bytecode check should run only when `suite == DEPLOYMENT_SUITE_ROUTE_PROCESSOR || suite == DEPLOYMENT_SUITE_ARB || suite == DEPLOYMENT_SUITE_ALL`. -- The `raindex` fallback read should run only when `suite == DEPLOYMENT_SUITE_SUBPARSER || suite == DEPLOYMENT_SUITE_ARB || suite == DEPLOYMENT_SUITE_ALL`. - -### A15-P5-2 [MEDIUM] `vm.envAddress("DEPLOY_RAINDEX_ADDRESS")` reverts unconditionally for `route-processor` suite - -**Location:** Lines 90-92 - -When running the `route-processor` suite: -- Line 70: `suite == DEPLOYMENT_SUITE_RAINDEX || suite == DEPLOYMENT_SUITE_ALL` is false. `raindex` stays `address(0)`. -- Line 90: `raindex == address(0)` is true. -- Line 91: `vm.envAddress("DEPLOY_RAINDEX_ADDRESS")` reverts if the env var is not set. - -The `route-processor` suite only deploys the route processor contract (lines 122-128) and has no use for `raindex`. Yet the script forces the caller to provide `DEPLOY_RAINDEX_ADDRESS`. This is a correctness bug: the env var requirement does not match the suite's actual dependencies. - -The fix is to move line 90-92 inside a condition that only executes when `raindex` is actually needed: -```solidity -if (suite == DEPLOYMENT_SUITE_SUBPARSER || suite == DEPLOYMENT_SUITE_ARB || suite == DEPLOYMENT_SUITE_ALL) { - if (raindex == address(0)) { - raindex = vm.envAddress("DEPLOY_RAINDEX_ADDRESS"); - } -} -``` - -### A15-P5-3 [LOW] No `require` / revert on `create` returning `address(0)` in `deployRouter()` (confirms A15-2) - -**Location:** Lines 55-58 - -This confirms Pass 1 finding A15-2. The `create` opcode returns `address(0)` on failure. `deployRouter()` returns this zero address without checking. While the downstream `extcodehash` check (line 133) would catch this, the revert error would be `BadRouteProcessor` -- misleading since the actual issue is a failed deployment, not a wrong route processor. - -An explicit check would provide a clearer error: -```solidity -assembly ("memory-safe") { - routeProcessor4 := create(0, add(routeProcessor4Code, 0x20), mload(routeProcessor4Code)) -} -require(routeProcessor4 != address(0), "RouteProcessor4 deployment failed"); -``` - -### A15-P5-4 [LOW] No mechanism to reject unknown suite values - -**Location:** Lines 61-175 - -If a caller sets `DEPLOYMENT_SUITE` to an unrecognized value (e.g., `"foo"`), the script does not revert with an explicit error. Instead, it silently skips all gated blocks and then reverts at the unconditional `extcodehash` check (line 133) with `BadRouteProcessor` -- a misleading error that does not indicate the real problem (unknown suite). - -Compare with `lib/rain.interpreter/script/Deploy.sol` which uses an `else { revert UnknownDeploymentSuite(suite); }` pattern for unrecognized suite values. - -Adding a final `else` clause or an explicit check at the end of the suite branching would provide a clear error message. - -### A15-P5-5 [INFO] `ROUTE_PROCESSOR_4_BYTECODE_HASH` cannot be statically verified against `ROUTE_PROCESSOR_4_CREATION_CODE` - -**Location:** Lines 38-42 - -The `ROUTE_PROCESSOR_4_BYTECODE_HASH` is the `keccak256` of the contract's runtime bytecode (what `extcodehash` returns), not the hash of the creation code. The runtime bytecode is a subset of the creation code (extracted during constructor execution) and cannot be derived without executing the constructor. Therefore, the consistency of these two constants cannot be verified by static analysis alone. - -The script verifies this at runtime (lines 129-135), but there is no automated test that deploys the creation code and asserts the resulting `extcodehash` matches. This was also flagged in Pass 2 (A15-P2-2). The correctness of the hash value depends on the external provenance described in the comments (lines 30-37). - -### A15-P5-6 [INFO] Constructor args in creation code encode `msg.sender` as owner via Ownable, not via constructor parameter - -**Location:** Lines 36-37, 38-39 - -The comment on line 37 says "no owner addresses" which refers to the `address[] _privilegedUsers` constructor parameter being empty. This is accurate but could be misread as "the contract has no owner." In fact, RouteProcessor4 inherits Ownable and sets `msg.sender` as owner in the constructor. When deployed via `deployRouter()`, the owner will be the deployer address (the `Deploy` script contract during `vm.broadcast`, effectively the deployer EOA). This is expected behavior and not a bug, but the comment's phrasing is slightly ambiguous. diff --git a/audit/2026-03-13-01/pass5/LibOrder.md b/audit/2026-03-13-01/pass5/LibOrder.md deleted file mode 100644 index d0b958a9ac..0000000000 --- a/audit/2026-03-13-01/pass5/LibOrder.md +++ /dev/null @@ -1,41 +0,0 @@ -# Pass 5: Correctness — LibOrder.sol - -**Agent:** A10 -**File:** `src/lib/LibOrder.sol` (19 lines) - -## Evidence of Thorough Reading - -- Read all 19 lines in full -- Verified SPDX license identifier: `LicenseRef-DCL-1.0` (line 1) -- Verified pragma: `^0.8.18` (line 3) -- Verified single import: `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5) -- Verified library name: `LibOrder` (line 10) -- Verified single function: `hash(OrderV4 memory order)` (line 16) - -## Correctness Verification - -### `hash` Function (lines 11-18) - -**NatSpec Claims:** -1. "Hashes `OrderV4` in a secure and deterministic way" -- Verified. Uses `keccak256(abi.encode(order))` which is deterministic for the same input. -2. "Uses abi.encode rather than abi.encodePacked to guard against potential collisions where many inputs encode to the same output bytes" -- Verified. `abi.encode` is used (not `abi.encodePacked`). This is the correct choice for struct hashing because `abi.encodePacked` with dynamic types can produce collisions. -3. `@param order The order to hash.` -- Correct, the parameter is `OrderV4 memory order`. -4. `@return The hash of order.` -- Correct, returns `bytes32` from `keccak256`. - -**Implementation:** `return keccak256(abi.encode(order));` -- This is a standard, safe hashing pattern. `abi.encode` for a `memory` struct will recursively encode all nested fields including dynamic arrays (`validInputs`, `validOutputs`), producing a collision-resistant hash. - -### Library Title NatSpec (lines 7-9) - -"Consistent handling of `OrderV4` for where it matters w.r.t. determinism and security." -- Accurate. The library provides exactly one function that ensures consistent hashing. - -## Findings - -No findings. This is a minimal, correct library. - -## Summary - -| ID | Severity | Description | -|---|---|---| -| (none) | -- | -- | - -The library is trivially correct. The single `hash` function matches its NatSpec exactly. Using `abi.encode` over `abi.encodePacked` is the right choice for struct hashing. diff --git a/audit/2026-03-13-01/pass5/LibOrderBook.md b/audit/2026-03-13-01/pass5/LibOrderBook.md deleted file mode 100644 index 1cb503b758..0000000000 --- a/audit/2026-03-13-01/pass5/LibOrderBook.md +++ /dev/null @@ -1,141 +0,0 @@ -# Pass 5: Correctness — LibOrderBook.sol - -**Agent:** A11 -**File:** `src/lib/LibOrderBook.sol` (125 lines) - -## Evidence of Thorough Reading - -- Read all 125 lines in full -- Verified all imports (lines 5-19): `CONTEXT_BASE_*` from `LibContext.sol`, `TaskV2`, `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4`, `LibNamespace`, `FullyQualifiedNamespace`, `LibContext` -- Verified all 35 file-level constants (lines 21-94) -- Verified `LibOrderBook` library with single function `doPost` (lines 96-125) -- Cross-referenced constant values against their usage in `OrderBookV6.sol` (lines 713-760), `OrderBookV6SubParser.sol`, and `LibOrderBookSubParser.sol` - -## Correctness Verification - -### File-Level Constants - -#### Context Column Layout - -| Constant | Value | Verified Against | -|---|---|---| -| `CALLING_CONTEXT_COLUMNS` | 4 | `OrderBookV6.calculateOrderIO` allocates `new bytes32[][](4)` | -| `CONTEXT_COLUMNS` | `CALLING_CONTEXT_COLUMNS + 1` = 5 | Base column (0) + 4 calling columns | -| `CONTEXT_CALLING_CONTEXT_COLUMN` | 1 | Used as `callingContext[1 - 1]` in OBV6 | -| `CONTEXT_CALCULATIONS_COLUMN` | 2 | Filled in `_recordVaultIO` | -| `CONTEXT_VAULT_INPUTS_COLUMN` | 3 | `callingContext[3 - 1]` in OBV6 | -| `CONTEXT_VAULT_OUTPUTS_COLUMN` | 4 | `callingContext[4 - 1]` in OBV6 | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` | 5 | Appended by `LibContext.build` | -| `CONTEXT_SIGNED_CONTEXT_START_COLUMN` | 6 | Appended by `LibContext.build` | - -All column indices are sequentially correct and consistent with the `LibContext.build` prepend behavior (base at 0, caller-provided at 1..N, signed context appended after). - -#### Calling Context Rows - -| Constant | Value | Verified | -|---|---|---| -| `CONTEXT_CALLING_CONTEXT_ROWS` | 3 | `arrayFrom(orderHash, owner, counterparty)` = 3 elements | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` | 0 | First arg to `arrayFrom` | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` | 1 | Second arg | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` | 2 | Third arg | - -#### Deposit Context Rows (lines 43-46) - -| Constant | Value | Actual Position in `deposit4` Context | -|---|---|---| -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` | 0 | `arrayFrom` arg 1: `token` | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` | 1 | `arrayFrom` arg 2: `vaultId` | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` | 2 | `arrayFrom` arg 3: `beforeBalance` | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` | 3 | `arrayFrom` arg 4: `afterBalance` | - -Verified against `OrderBookV6.deposit4` lines 279-286. Note: deposit context also has a 5th element (decimals at row 4) that has no named constant. This is intentional -- decimals are not exposed to sub-parser expressions. - -#### Withdraw Context Rows (lines 48-52) - -| Constant | Value | Actual Position in `withdraw4` Context | -|---|---|---| -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` | 0 | `arrayFrom` arg 1: `token` | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` | 1 | `arrayFrom` arg 2: `vaultId` | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` | 2 | `arrayFrom` arg 3: `beforeBalance` | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` | 3 | `arrayFrom` arg 4: `afterBalance` | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` | 4 | `arrayFrom` arg 5: `targetAmount` | - -Verified against `OrderBookV6.withdraw4` lines 316-323. Withdraw context also has a 6th element (decimals at row 5) with no named constant, same as deposit. - -#### Calculations Rows - -| Constant | Value | Verified | -|---|---|---| -| `CONTEXT_CALCULATIONS_ROWS` | 2 | max-output and io-ratio | -| `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` | 0 | Stack position `0x40` in assembly | -| `CONTEXT_CALCULATIONS_ROW_IO_RATIO` | 1 | Stack position `0x20` in assembly | - -#### Vault IO Rows - -| Constant | Value | Verified Against | -|---|---|---| -| `CONTEXT_VAULT_IO_TOKEN` | 0 | `arrayFrom` arg 1 in OBV6 | -| `CONTEXT_VAULT_IO_TOKEN_DECIMALS` | 1 | `arrayFrom` arg 2 | -| `CONTEXT_VAULT_IO_VAULT_ID` | 2 | `arrayFrom` arg 3 | -| `CONTEXT_VAULT_IO_BALANCE_BEFORE` | 3 | `arrayFrom` arg 4 | -| `CONTEXT_VAULT_IO_BALANCE_DIFF` | 4 | `arrayFrom` arg 5 (initially 0, filled later) | -| `CONTEXT_VAULT_IO_ROWS` | 5 | 5 elements in the array | - -#### Signed Context - -| Constant | Value | Purpose | -|---|---|---| -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` | 5 | Column for signer addresses | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` | 1 | Single row type (indexed by operand) | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW` | 0 | The single signer row | -| `CONTEXT_SIGNED_CONTEXT_START_COLUMN` | 6 | First column of signed data | -| `CONTEXT_SIGNED_CONTEXT_START_ROWS` | 1 | Single row type (indexed by operand) | -| `CONTEXT_SIGNED_CONTEXT_START_ROW` | 0 | The single signed context row | - -### NatSpec on Constants - -- Line 23: "calculuate" is a typo for "calculate" -- cosmetic only. -- Lines 80-83: NatSpec on `CONTEXT_VAULT_IO_BALANCE_DIFF` says "subtraced" -- should be "subtracted". Cosmetic typo. -- The `@dev` comments accurately describe the semantics: balance diff is always positive, must be added to input balances and subtracted from output balances. - -### `doPost` Function (lines 97-124) - -**What it claims to do:** No NatSpec (undocumented internal function). - -**What it does:** -1. Wraps `msg.sender` into a `StateNamespace` (line 98) -2. Qualifies the namespace with `address(this)` (line 99) -3. Iterates over `post` tasks (line 103) -4. Skips tasks with empty bytecode (line 105) -5. Evaluates each task via `eval4` with: - - The provided context merged with the task's signed context via `LibContext.build` (line 113) - - Source index 0 (line 112) - - No inputs (line 114) - - No state overlay (line 115) -6. Writes KV pairs to the store if any (lines 119-121) -7. Discards the stack (line 118) - -**Caller expectations verified:** -- `OrderBookV6.deposit4/withdraw4/addOrder4/removeOrder3/entask2`: All pass appropriate context and post tasks. The namespace = `msg.sender` means the expression state is scoped to the caller (depositor/withdrawer/order owner). -- `LibOrderBookArb.finalizeArb`: Passes arb context (input/output/gas balances). When called from arb contracts, `msg.sender` is the arb initiator, which is correct for scoping arb task state to the person who triggered the arb. - -## Findings - -### P5-A11-01 (INFO): Typos in NatSpec Comments - -**Severity:** INFO -**File:** `src/lib/LibOrderBook.sol`, lines 23 and 83 - -**Details:** -- Line 23: "calculuate" should be "calculate" -- Line 83: "subtraced" should be "subtracted" - -**Impact:** Documentation-only. No functional impact. - -## Summary - -| ID | Severity | Description | -|---|---|---| -| P5-A11-01 | INFO | Typos in NatSpec: "calculuate" and "subtraced" | - -All 35 constants have been verified against their usage sites in the orderbook, sub-parser, and arb contracts. Every column index, row index, and row count is consistent with the actual context arrays constructed at runtime. The `doPost` function correctly evaluates post tasks in the caller's namespace. diff --git a/audit/2026-03-13-01/pass5/LibOrderBookArb.md b/audit/2026-03-13-01/pass5/LibOrderBookArb.md deleted file mode 100644 index 689211c466..0000000000 --- a/audit/2026-03-13-01/pass5/LibOrderBookArb.md +++ /dev/null @@ -1,99 +0,0 @@ -# Pass 5: Correctness — LibOrderBookArb.sol - -**Agent:** A12 -**File:** `src/lib/LibOrderBookArb.sol` (77 lines) - -## Evidence of Thorough Reading - -- Read all 77 lines in full -- Verified all imports (lines 5-11): `TaskV2`, `IERC20`, `LibOrderBook`, `Address`, `SafeERC20`, `IERC20Metadata`, `LibDecimalFloat`, `Float` -- Verified error declarations (lines 14-18): `NonZeroBeforeArbStack`, `BadLender` -- Verified library declaration with `using SafeERC20 for IERC20` (lines 20-21) -- Verified the single function `finalizeArb` (lines 23-76) -- Cross-referenced against both callers: `OrderBookV6ArbOrderTaker.arb5` (line 68) and `OrderBookV6FlashBorrower.arb4` (line 164) - -## Correctness Verification - -### Error Declarations - -- `NonZeroBeforeArbStack()` (line 14): NatSpec says "Thrown when the stack is not empty after the access control dispatch." This error is defined here but used in `OrderBookV6ArbCommon` (the base contract for both arb contracts). The name and documentation match: it's for when the before-arb eval returns a non-empty stack. Correct. -- `BadLender(address badLender)` (line 17-18): NatSpec says "Thrown when the lender is not the trusted `OrderBook`." This error is also imported by the flash borrower. The parameter name `badLender` and documentation match. Correct. - -### `finalizeArb` Function (lines 23-76) - -**Parameters:** -- `task`: The post-arb task to evaluate -- `ordersInputToken`: The token that was input to the orders (i.e., what the taker sent to fill orders) -- `inputDecimals`: Decimals for the input token -- `ordersOutputToken`: The token that was output from the orders (i.e., what the taker received) -- `outputDecimals`: Decimals for the output token - -**Step-by-step verification:** - -1. **Context array creation** (lines 30-31): Creates a 1-column context with 3 rows. This will become column 1 (after `LibContext.build` prepends base at column 0 in `doPost`). - -2. **Input token handling** (lines 34-42): - - Gets balance of `ordersInputToken` held by `address(this)` (the arb contract) - - If balance > 0, transfers all to `msg.sender` (the arb initiator) - - Converts to float and stores in `col[0]` - - NatSpec comment "Send all unspent input tokens to the sender" is accurate - -3. **Output token handling** (lines 44-54): - - Gets balance of `ordersOutputToken` held by `address(this)` - - If balance > 0, transfers all to `msg.sender` - - Converts to float and stores in `col[1]` - - NatSpec comment "Send all unspent output tokens to the sender" is accurate - -4. **Native gas handling** (lines 56-69): - - Gets ETH balance of `address(this)` - - Sends all to `msg.sender` via `Address.sendValue` - - Converts to float with 18 decimals and stores in `col[2]` - - NatSpec comment explains why sending all balance is correct (contract should be empty between uses) - - The cast `int256(gasBalance)` is safe because there isn't enough ETH in existence to overflow int256 - -5. **Post task execution** (lines 71-75): - - Sets `context[0] = col` (the 3-row column) - - Wraps task in a 1-element array - - Calls `LibOrderBook.doPost(context, post)` - -**Caller verification:** - -`OrderBookV6ArbOrderTaker.arb5` (lines 60-74): -- Sets `ordersInputToken` from `takeOrders.orders[0].order.validInputs[takeOrders.orders[0].inputIOIndex].token` -- Sets `ordersOutputToken` from `takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token` -- These are from the perspective of the ORDER (input = what the order receives, output = what the order sends) -- From the TAKER's perspective: the taker sends `ordersInputToken` and receives `ordersOutputToken` -- After `takeOrders4`, the arb contract may have leftover `ordersInputToken` (if the taker overpaid) and `ordersOutputToken` (profit) -- `finalizeArb` correctly sweeps both to the sender - -`OrderBookV6FlashBorrower.arb4` (lines 130-165): -- Same token extraction logic -- Flash borrows `ordersOutputToken` (what the orders will send out, which the flash borrower needs to sell on external liq) -- After exchange + takeOrders + flash loan repayment, leftover tokens are swept by `finalizeArb` -- Correct behavior - -### Float Conversion - -- `LibDecimalFloat.fromFixedDecimalLossyPacked(inputBalance, inputDecimals)` -- uses the "lossy" variant, discarding the `lossless` return value. This is acceptable because the context column is informational for the post-arb task, not used for accounting. -- `LibDecimalFloat.packLossless(int256(gasBalance), -18)` -- uses lossless for ETH (18 decimals is standard). This will revert if the value can't be represented losslessly, which is acceptable. - -### Unused Import - -`IERC20Metadata` is imported (line 10) but never used in the library. This was noted in previous passes. - -## Findings - -No new findings at LOW or above. The function correctly: -1. Sweeps all remaining tokens and ETH to the arb initiator -2. Provides swept amounts as context to the post-arb task -3. Delegates to `LibOrderBook.doPost` for task evaluation - -The context layout (input balance at row 0, output balance at row 1, gas balance at row 2) is self-consistent and matches the expectations of callers. - -## Summary - -| ID | Severity | Description | -|---|---|---| -| (none) | -- | -- | - -`finalizeArb` behavior matches its callers' expectations precisely. Both `OrderBookV6ArbOrderTaker.arb5` and `OrderBookV6FlashBorrower.arb4` call it after their respective order-taking strategies, and it correctly sweeps residual balances and runs the post-arb task. diff --git a/audit/2026-03-13-01/pass5/LibOrderBookDeploy.md b/audit/2026-03-13-01/pass5/LibOrderBookDeploy.md deleted file mode 100644 index d061233a90..0000000000 --- a/audit/2026-03-13-01/pass5/LibOrderBookDeploy.md +++ /dev/null @@ -1,61 +0,0 @@ -# Pass 5: Correctness — LibOrderBookDeploy.sol - -**Agent:** A14 -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` (53 lines) - -## Evidence of Thorough Reading - -- Read all 53 lines in full -- Verified import of `Vm` from `forge-std/Vm.sol` (line 5) -- Verified imports from generated pointer files (lines 7-16): `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` for both `OrderBookV6` and `OrderBookV6SubParser` -- Verified 4 library constants (lines 27-39) -- Verified `etchOrderBook(Vm vm)` function (lines 45-52) - -## Correctness Verification - -### Library Constants - -| Constant | Source | NatSpec Claim | Verified | -|---|---|---|---| -| `ORDERBOOK_DEPLOYED_ADDRESS` | `ORDERBOOK_ADDR` from `OrderBookV6.pointers.sol` | "The address of the `OrderBookV6` contract when deployed with the rain standard zoltu deployer" | Consistent with import alias | -| `ORDERBOOK_DEPLOYED_CODEHASH` | `ORDERBOOK_HASH` from `OrderBookV6.pointers.sol` | "The code hash of the `OrderBookV6` contract when deployed with the rain standard zoltu deployer" | Consistent with import alias | -| `SUB_PARSER_DEPLOYED_ADDRESS` | `SUB_PARSER_ADDR` from `OrderBookV6SubParser.pointers.sol` | "The address of the `OrderBookV6SubParser` contract when deployed with the rain standard zoltu deployer" | Consistent with import alias | -| `SUB_PARSER_DEPLOYED_CODEHASH` | `SUB_PARSER_HASH` from `OrderBookV6SubParser.pointers.sol` | "The code hash of the `OrderBookV6SubParser` contract when deployed with the rain standard zoltu deployer" | Consistent with import alias | - -### `etchOrderBook` Function (lines 45-52) - -**NatSpec claim (lines 41-43):** "Etches the runtime bytecode of the orderbook and sub parser at their expected deterministic addresses. Skips any contract whose codehash already matches." - -**Implementation verification:** - -1. **Orderbook etch (lines 46-48):** - - Condition: `ORDERBOOK_DEPLOYED_CODEHASH != ORDERBOOK_DEPLOYED_ADDRESS.codehash` - - Action: `vm.etch(ORDERBOOK_DEPLOYED_ADDRESS, ORDERBOOK_RUNTIME_CODE)` - - Skips if codehash already matches -- NatSpec accurate - - Uses `.codehash` which returns `keccak256(code)` for deployed contracts, or `0` for empty accounts. This means if the address has no code (is an EOA or doesn't exist), the condition will be `hash != 0` which is true (assuming the hash is non-zero), so it will etch. Correct behavior for test setup. - -2. **SubParser etch (lines 49-51):** - - Same pattern. Correct. - -**Context:** This library uses `Vm` from forge-std, so it's only usable in Foundry test/script contexts. The `@title` NatSpec (lines 18-23) accurately describes the library's purpose: idempotent deployments against precommitted addresses. - -### Import Aliasing - -The imports use clear aliasing: -- `BYTECODE_HASH as ORDERBOOK_HASH` / `SUB_PARSER_HASH` -- `DEPLOYED_ADDRESS as ORDERBOOK_ADDR` / `SUB_PARSER_ADDR` -- `RUNTIME_CODE as ORDERBOOK_RUNTIME_CODE` / `SUB_PARSER_RUNTIME_CODE` - -Since both generated files export the same symbol names (`BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE`), the aliasing is necessary and correctly disambiguates between the two contracts. - -## Findings - -No findings. All NatSpec matches implementation. The idempotent etch pattern is correct and the codehash comparison is the right way to skip already-etched contracts. - -## Summary - -| ID | Severity | Description | -|---|---|---| -| (none) | -- | -- | - -The library correctly provides idempotent test-time deployment helpers for OrderBookV6 and its sub-parser. Constants are directly sourced from generated pointer files, and the etch function's skip-if-matching behavior is accurately documented. diff --git a/audit/2026-03-13-01/pass5/LibOrderBookSubParser.md b/audit/2026-03-13-01/pass5/LibOrderBookSubParser.md deleted file mode 100644 index 9b39f45b3e..0000000000 --- a/audit/2026-03-13-01/pass5/LibOrderBookSubParser.md +++ /dev/null @@ -1,128 +0,0 @@ -# Pass 5: Correctness — LibOrderBookSubParser.sol - -**Agent:** A13 -**File:** `src/lib/LibOrderBookSubParser.sol` (599 lines) - -## Evidence of Thorough Reading - -- Read all 599 lines in full -- Verified all imports (lines 1-46): `AuthoringMetaV2`, `OperandV2`, `LibUint256Matrix`, `LibSubParse`, and all 38 `CONTEXT_*` constants from `LibOrderBook.sol` -- Verified all 21 word constants (lines 51-80): `WORD_ORDER_CLEARER` through `WORD_WITHDRAW_TARGET_AMOUNT` -- Verified all 13 deposit/withdraw word index constants (lines 82-95) -- Verified `SUB_PARSER_WORD_PARSERS_LENGTH = 2` and `EXTERN_PARSE_META_BUILD_DEPTH = 1` (lines 48-49) -- Verified all 20 sub-parser functions (lines 101-366) -- Verified the `authoringMetaV2()` function (lines 369-598) - -## Correctness Verification - -### Word-to-Context Mapping (Sub-Parser Functions) - -Every sub-parser function maps a word to a specific `(column, row)` in the context grid via `LibSubParse.subParserContext`. Verified each: - -| Function | Word | Column | Row | Correct? | -|---|---|---|---|---| -| `subParserSender` | order-clearer / depositor / withdrawer | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROW_SENDER` (0) | Yes | -| `subParserCallingContract` | orderbook | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROW_CALLING_CONTRACT` (1) | Yes | -| `subParserOrderHash` | order-hash | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_ORDER_HASH` (0) | Yes | -| `subParserOrderOwner` | order-owner | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_ORDER_OWNER` (1) | Yes | -| `subParserOrderCounterparty` | order-counterparty | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_ORDER_COUNTERPARTY` (2) | Yes | -| `subParserMaxOutput` | calculated-max-output | `CONTEXT_CALCULATIONS_COLUMN` (2) | `..ROW_MAX_OUTPUT` (0) | Yes | -| `subParserIORatio` | calculated-io-ratio | `CONTEXT_CALCULATIONS_COLUMN` (2) | `..ROW_IO_RATIO` (1) | Yes | -| `subParserInputToken` | input-token | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_TOKEN` (0) | Yes | -| `subParserInputTokenDecimals` | input-token-decimals | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `..TOKEN_DECIMALS` (1) | Yes | -| `subParserInputVaultId` | input-vault-id | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `..VAULT_ID` (2) | Yes | -| `subParserInputBalanceBefore` | input-vault-before | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `..BALANCE_BEFORE` (3) | Yes | -| `subParserInputBalanceDiff` | input-vault-increase | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `..BALANCE_DIFF` (4) | Yes | -| `subParserOutputToken` | output-token | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_TOKEN` (0) | Yes | -| `subParserOutputTokenDecimals` | output-token-decimals | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `..TOKEN_DECIMALS` (1) | Yes | -| `subParserOutputVaultId` | output-vault-id | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `..VAULT_ID` (2) | Yes | -| `subParserOutputBalanceBefore` | output-vault-before | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `..BALANCE_BEFORE` (3) | Yes | -| `subParserOutputBalanceDiff` | output-vault-decrease | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `..BALANCE_DIFF` (4) | Yes | -| `subParserSigners` | signer | `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` (5) | operand-derived | Yes | -| `subParserSignedContext` | signed-context | `CONTEXT_SIGNED_CONTEXT_START_COLUMN + (operand & 0xFF)` | `(operand >> 8) & 0xFF` | Yes | - -#### Deposit Sub-Parser Functions - -| Function | Word | Column | Row | -|---|---|---|---| -| `subParserDepositToken` | deposit-token | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_DEPOSIT_TOKEN` (0) | -| `subParserDepositVaultId` | deposit-vault-id | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_DEPOSIT_VAULT_ID` (1) | -| `subParserDepositVaultBalanceBefore` | deposit-vault-before | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_DEPOSIT_VAULT_BEFORE` (2) | -| `subParserDepositVaultBalanceAfter` | deposit-vault-after | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_DEPOSIT_VAULT_AFTER` (3) | - -Cross-referenced with `OrderBookV6.deposit4` context construction: -- `arrayFrom(token, vaultId, beforeBalance, afterBalance, decimals)` at context column index 0 (pre-build), which becomes column 1 after `LibContext.build`. Rows match. - -#### Withdraw Sub-Parser Functions - -| Function | Word | Column | Row | -|---|---|---|---| -| `subParserWithdrawToken` | withdraw-token | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_WITHDRAW_TOKEN` (0) | -| `subParserWithdrawVaultId` | withdraw-vault-id | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_WITHDRAW_VAULT_ID` (1) | -| `subParserWithdrawVaultBalanceBefore` | withdraw-vault-before | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_WITHDRAW_VAULT_BEFORE` (2) | -| `subParserWithdrawVaultBalanceAfter` | withdraw-vault-after | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_WITHDRAW_VAULT_AFTER` (3) | -| `subParserWithdrawTargetAmount` | withdraw-target-amount | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `..ROW_WITHDRAW_TARGET_AMOUNT` (4) | - -Cross-referenced with `OrderBookV6.withdraw4` context construction: -- `arrayFrom(token, vaultId, beforeBalance, afterBalance, targetAmount, decimals)` at context column index 0 (pre-build), which becomes column 1 after `LibContext.build`. Rows match. - -### `authoringMetaV2` Function (lines 369-598) - -**Array size:** `CONTEXT_COLUMNS + 2 + 1 + 1 = 9` -- matches `buildSubParserWordParsers` and `buildOperandHandlerFunctionPointers` in `OrderBookV6SubParser.sol`. - -**Meta indexing for deposit section (lines 518-546):** -- `depositMeta[0]` = WORD_DEPOSITOR -- matches `DEPOSIT_WORD_DEPOSITOR = 0` -- `depositMeta[CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN + 1]` = `depositMeta[1]` = WORD_DEPOSIT_TOKEN -- matches `DEPOSIT_WORD_TOKEN = 1` -- `depositMeta[CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID + 1]` = `depositMeta[2]` = WORD_DEPOSIT_VAULT_ID -- matches `DEPOSIT_WORD_VAULT_ID = 2` -- `depositMeta[CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE + 1]` = `depositMeta[3]` = WORD_DEPOSIT_VAULT_BEFORE -- matches `DEPOSIT_WORD_VAULT_BEFORE = 3` -- `depositMeta[CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER + 1]` = `depositMeta[4]` = WORD_DEPOSIT_VAULT_AFTER -- matches `DEPOSIT_WORD_VAULT_AFTER = 4` - -All indices are numerically correct. However, the `+1` offset pattern relies on the numerical coincidence that `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_*` constants (0-3) are one less than the corresponding `DEPOSIT_WORD_*` constants (1-4). - -**Meta indexing for withdraw section (lines 549-583):** -- Uses `WITHDRAW_WORD_*` constants directly. All match correctly. - -**Authoring meta word bytes:** -- `WORD_ORDER_CLEARER` = "order-clearer" for sender -- matches semantics -- `WORD_ORDERBOOK` = "orderbook" for calling contract -- matches -- `WORD_ORDER_HASH`, `WORD_ORDER_OWNER`, `WORD_ORDER_COUNTERPARTY` -- all match -- `WORD_CALCULATED_MAX_OUTPUT`, `WORD_CALCULATED_IO_RATIO` -- match -- Input/output vault words -- all match -- "signer" and "signed-context" -- match - -**Assembly block (lines 588-594):** Standard `memory-safe` cast from `AuthoringMetaV2[][]` to `uint256[][]`, flatten, cast back. This is the same pattern used in `OrderBookV6SubParser.sol`. Note: the first assembly block at line 588 is NOT marked `memory-safe` (unlike the ones in `OrderBookV6SubParser.sol`), but this is in a pure function and the cast is semantically safe. - -### `subParserSignedContext` Operand Parsing (lines 357-366) - -The function extracts column from `operand & 0xFF` and row from `(operand >> 8) & 0xFF`. This matches the `handleOperandDoublePerByteNoDefault` handler assigned in `OrderBookV6SubParser.buildOperandHandlerFunctionPointers()`. The double-per-byte operand packs two bytes: low byte = column offset, high byte = row. Correct. - -### `subParserSigners` Operand Parsing (lines 251-258) - -Uses `uint256(OperandV2.unwrap(operand))` as the row in the signers column. This matches `handleOperandSingleFullNoDefault` which allows a single operand value. Correct. - -## Findings - -### P5-A13-01 (INFO): Inconsistent Indexing Style in `authoringMetaV2` Deposit Section - -**Severity:** INFO -**File:** `src/lib/LibOrderBookSubParser.sol`, lines 524-541 - -**Details:** The deposit meta section uses `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_* + 1` to index `depositMeta`, while the withdraw meta section uses `WITHDRAW_WORD_*` constants directly. The deposit section could equivalently use `DEPOSIT_WORD_TOKEN`, `DEPOSIT_WORD_VAULT_ID`, `DEPOSIT_WORD_VAULT_BEFORE`, `DEPOSIT_WORD_VAULT_AFTER` for clarity and consistency. The `+1` offset works only because the numerical relationship between `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_*` (0-3) and `DEPOSIT_WORD_*` (1-4) is exactly +1. If either set changed independently, this would silently produce wrong meta entries. - -**Impact:** Maintainability concern. No current correctness issue since the values are correct. Previous passes (P3, P4) did not flag this specific inconsistency. - -### P5-A13-02 (INFO): Missing `memory-safe` Annotation on Assembly Block - -**Severity:** INFO -**File:** `src/lib/LibOrderBookSubParser.sol`, line 588 - -**Details:** The `assembly` block at line 588 is not annotated with `("memory-safe")`, unlike the equivalent blocks in `OrderBookV6SubParser.sol` (lines 179-181, 300-303). The cast is semantically safe (same layout pointer reinterpretation) and occurs in a `pure` function, so this has no practical impact on the optimizer. However, consistency with the rest of the codebase would be improved by adding the annotation. - -## Summary - -| ID | Severity | Description | -|---|---|---| -| P5-A13-01 | INFO | Inconsistent indexing style in `authoringMetaV2` deposit section vs withdraw section | -| P5-A13-02 | INFO | Missing `memory-safe` annotation on assembly block at line 588 | - -All 20 sub-parser functions correctly map words to their intended context (column, row) positions. The `authoringMetaV2` function produces correct metadata for all words across all context columns. The deposit/withdraw sub-parser functions correctly reference the context rows that match the actual context arrays constructed in `OrderBookV6.deposit4` and `OrderBookV6.withdraw4`. diff --git a/audit/2026-03-13-01/pass5/OrderBookV6.md b/audit/2026-03-13-01/pass5/OrderBookV6.md deleted file mode 100644 index 1a786db909..0000000000 --- a/audit/2026-03-13-01/pass5/OrderBookV6.md +++ /dev/null @@ -1,236 +0,0 @@ -# Pass 5: Correctness -- OrderBookV6.sol - -**Agent:** A08 -**Date:** 2026-03-13 -**File:** `src/concrete/ob/OrderBookV6.sol` (~1055 lines) - -## Evidence of Thorough Reading - -The following items were individually verified: - -- **All imports** (lines 1-63): Math, Multicall, IERC20, SafeERC20, ReentrancyGuard, IERC20Metadata, LibContext, LibBytecode, SourceIndexV2, StateNamespace, IInterpreterV4, StackItem, EvalV4, LibUint256Array, LibUint256Matrix, IInterpreterStoreV3, LibNamespace, LibMeta, IMetaV1_2, LibOrderBook, LibDecimalFloat, LibTOFUTokenDecimals/TOFUOutcome, ITOFUTokenDecimals, IRaindexV6 and all sub-types, IRaindexV6OrderTaker, LibOrder, context constants, OrderBookV6FlashLender, LibBytes32Array, LibBytes32Matrix, LibFormatDecimalFloat. -- **All error declarations** (lines 69-125): ReentrancyGuardReentrantCall, NotOrderOwner, TokenMismatch, TokenSelfTrade, TokenDecimalsMismatch, MinimumIO, SameOwner, UnsupportedCalculateInputs, UnsupportedCalculateOutputs, NegativeInput, NegativeOutput, NegativeVaultBalance, NegativeVaultBalanceChange, NegativePull, NegativePush, NegativeBounty, ClearZeroAmount. -- **All constants** (lines 127-150): ORDER_LIVE, ORDER_DEAD, CALCULATE_ORDER_ENTRYPOINT, HANDLE_IO_ENTRYPOINT, CALCULATE_ORDER_MIN_OUTPUTS, CALCULATE_ORDER_MAX_OUTPUTS, HANDLE_IO_MIN_OUTPUTS, HANDLE_IO_MAX_OUTPUTS. -- **All state variables** (lines 215-223): sOrders mapping, sVaultBalances mapping. -- **All functions**: vaultBalance2, _vaultBalance, orderExists, entask2, deposit4, withdraw4, addOrder4, removeOrder3, checkTokenSelfTrade, quote2, takeOrders4, clear3, calculateOrderIO, increaseVaultBalance, decreaseVaultBalance, recordVaultIO, handleIO, calculateClearStateChange, calculateClearStateAlice, pullTokens, pushTokens, _nonZeroVaultId, nonZeroVaultId modifier. -- **Struct** OrderIOCalculationV4 (lines 181-190) and type aliases Output18Amount / Input18Amount (lines 192-194). -- **Contract inheritance**: IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, OrderBookV6FlashLender. - -## Verification Results - -### Constants - -| Constant | Value | Correct? | -|---|---|---| -| CALCULATE_ORDER_ENTRYPOINT | SourceIndexV2.wrap(0) | Yes -- source 0 is calculate order | -| HANDLE_IO_ENTRYPOINT | SourceIndexV2.wrap(1) | Yes -- source 1 is handle IO | -| CALCULATE_ORDER_MIN_OUTPUTS | 2 | Yes -- maxOutput and IORatio | -| CALCULATE_ORDER_MAX_OUTPUTS | 2 | Yes -- matches min | -| HANDLE_IO_MIN_OUTPUTS | 0 | Yes -- handle IO has no outputs | -| HANDLE_IO_MAX_OUTPUTS | 0 | Yes -- matches min | -| ORDER_LIVE | 1 | Yes -- non-default, non-boolean | -| ORDER_DEAD | 0 | Yes -- default mapping value | - -### Algorithm Verification: calculateClearStateAlice - -The algorithm computes: -1. `aliceInput = aliceOutputMax * aliceIORatio` (Alice demands this much input for her output) -2. `aliceOutput = aliceOutputMax` -3. If `aliceInput > bobOutputMax`, cap: `aliceInput = bobOutputMax`, `aliceOutput = aliceInput / aliceIORatio` - -This is correct. When Alice wants more than Bob can provide, Alice's input is capped to Bob's max output, and Alice's output is reduced proportionally to maintain her ratio. - -The symmetric call `calculateClearStateAlice(bob, alice)` correctly computes Bob's side. - -### Algorithm Verification: Bounty Math in clear3 - -``` -aliceBounty = aliceOutput - bobInput -bobBounty = bobOutput - aliceInput -``` - -Alice outputs tokens that go to: Bob's input + clearer bounty. So `aliceOutput >= bobInput` must hold. Similarly for Bob. The negative bounty check correctly guards this invariant. Bounty tokens are deposited to the clearer's vault under the correct output token for each respective order. - -### Algorithm Verification: takeOrders4 IO Math - -With `IOIsInput == true`: -- `takerInput = min(orderOutputMax, remainingTakerIO)` -- taker receives order's output, capped -- `takerOutput = IORatio * takerInput` -- taker sends order's input amount - -With `IOIsInput == false`: -- `orderMaxInput = IORatio * orderOutputMax` -- max the order can take in -- `takerOutput = min(orderMaxInput, remainingTakerIO)` -- taker sends capped amount -- `takerInput = takerOutput / IORatio` -- taker receives, rounded down (favors order) - -The call `recordVaultIO(takerOutput, takerInput, ...)` passes (order input, order output) which matches the signature `recordVaultIO(Float input, Float output, ...)`. **Correct.** - -The token flow: -- `pushTokens(msg.sender, orderOutputToken, totalTakerInput)` -- sends order output token to taker -- `pullTokens(msg.sender, orderInputToken, totalTakerOutput)` -- pulls order input token from taker - -**Correct** -- taker receives `orderOutputToken` and sends `orderInputToken`. - -### recordVaultIO Parameter Order at All Call Sites - -| Call Site | Arg 1 (input) | Arg 2 (output) | Correct? | -|---|---|---|---| -| takeOrders4 L538 | takerOutput (=order input) | takerInput (=order output) | Yes | -| clear3 L648 (alice) | clearStateChange.aliceInput | clearStateChange.aliceOutput | Yes | -| clear3 L649 (bob) | clearStateChange.bobInput | clearStateChange.bobOutput | Yes | - -### Error Conditions - -| Error | Trigger | Matches Name? | -|---|---|---| -| NotOrderOwner | removeOrder3 when msg.sender != order.owner | Yes | -| TokenMismatch | takeOrders4/clear3 token pair mismatch | Yes | -| TokenSelfTrade | order input token == output token | Yes | -| SameOwner | clear3 alice.owner == bob.owner | Yes | -| UnsupportedCalculateOutputs | stack length < 2 | Yes | -| NegativeVaultBalance | balance goes negative after op | Yes | -| NegativeVaultBalanceChange | negative amount passed to increase/decrease | Yes | -| NegativePull | negative amount in pullTokens | Yes | -| NegativePush | negative amount in pushTokens | Yes | -| NegativeBounty | bounty < 0 in clear3 | Yes | -| ClearZeroAmount | both outputs zero after clear | Yes | -| MinimumIO | totalTakerIO < config.minimumIO | Yes | -| ZeroDepositAmount | deposit amount not > 0 | Yes (via interface) | -| ZeroWithdrawTargetAmount | withdraw target not > 0 | Yes (via interface) | -| ZeroMaximumIO | maximumIO not > 0 | Yes (via interface) | -| NoOrders | takeOrders4 with 0 orders | Yes (via interface) | -| OrderNoInputs | addOrder4 with 0 inputs | Yes (via interface) | -| OrderNoOutputs | addOrder4 with 0 outputs | Yes (via interface) | - -### Interface Conformance: IRaindexV6 - -All functions declared in `IRaindexV6` are implemented with matching signatures: -- `vaultBalance2` -- implemented -- `orderExists` -- implemented -- `entask2` -- implemented -- `deposit4` -- implemented -- `withdraw4` -- implemented -- `addOrder4` -- implemented -- `removeOrder3` -- implemented -- `quote2` -- implemented -- `takeOrders4` -- implemented -- `clear3` -- implemented - -### Interface Conformance: IMetaV1_2 - -The contract declares `is IMetaV1_2`. `MetaV1_2` is an event-only interface. The `AddOrder4` function emits `MetaV1_2(...)` when meta is present. No function implementation needed. - -### Interface Conformance: ERC-165 - -`supportsInterface` is implemented in `OrderBookV6FlashLender` (registers `IERC3156FlashLender`). The contract inherits `ERC165` via `OrderBookV6FlashLender`. Note: `IRaindexV6` interface ID is NOT explicitly registered in `supportsInterface`. This may be intentional (not all projects register every interface) but is a gap. - -### Interface Conformance: ERC-3156 - -- `flashLoan` -- implemented in `OrderBookV6FlashLender`, returns true, checks callback result -- `flashFee` -- returns `FLASH_FEE` (0), correct -- `maxFlashLoan` -- returns token balance of contract, correct - -### Test Spot-Check - -| Test File | Test Name | Verified Behavior | -|---|---|---| -| clear.zeroAmount.t.sol | testClearZeroAmount | Both orders return 0/0, expects ClearZeroAmount revert. Correct. | -| clear.sameToken.t.sol | testClearSameToken | Same token for input/output, expects TokenSelfTrade. Correct. | -| clear.badStack.t.sol | testClearOrderBadStackEmptyStack | Empty stack (0 outputs), expects UnsupportedCalculateOutputs(0). Correct. | -| clear.badStack.t.sol | testClearOrderBadStackOneStack | 1 output, expects UnsupportedCalculateOutputs(1). Correct. | -| clear.handleIO.revert.t.sol | testClearOrderHandleIO0-5 | Various ensure conditions in handleIO, verifies revert propagation. Correct. | -| takeOrder.noop.t.sol | testTakeOrderNoopZeroOrders | Empty orders array, expects NoOrders. Correct. | -| takeOrder.sameToken.t.sol | testTakeOrderSameToken | Same input/output token, expects TokenSelfTrade. Correct. | - -## Findings - -### INFORMATIONAL -- I01: Dead Type Aliases Output18Amount and Input18Amount - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 192-194 - -`type Output18Amount is uint256;` and `type Input18Amount is uint256;` are declared but never used anywhere in the codebase. These appear to be remnants from a previous version that used 18-decimal fixed point math. They are now completely dead code since the V6 implementation uses `Float` throughout. - -**Impact:** None (dead code only). - -### INFORMATIONAL -- I02: Stale NatSpec References to 18-Decimal Fixed Point in OrderIOCalculationV4 - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 152-180 - -The NatSpec for `OrderIOCalculationV4` extensively references "18 fixed point decimal", `1e18`, and "RESCALED ACCORDING TO TOKEN DECIMALS to an 18 fixed point decimal number". These descriptions are outdated. The V6 implementation uses Rain floating point (`Float`) internally. The expression returns `Float` values directly, and there is no rescaling to 18-decimal fixed point. Token decimals are only used at the boundary when converting Float to/from absolute token amounts via `pullTokens`/`pushTokens`. - -Similarly, `calculateOrderIO` NatSpec (line 690-691) says "Both are always treated as 18 decimal fixed point values and then rescaled" which is inaccurate. - -**Impact:** Documentation-only. Could confuse developers/auditors reviewing the code. - -### INFORMATIONAL -- I03: recordVaultIO NatSpec is Inaccurate - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 886-891 - -Three issues: -1. The NatSpec says "dispatch the handle IO entrypoint if it exists" but `recordVaultIO` does NOT dispatch handle IO. That is done by the separate `handleIO` function. -2. The NatSpec references `_calculateOrderIO` (line 887) but the actual function is named `calculateOrderIO` (no underscore prefix). -3. The `@param orderIOCalculation` description (line 891) is truncated: "The order IO calculation produced by" -- sentence ends without completing. - -**Impact:** Documentation-only. - -### INFORMATIONAL -- I04: Stale Comment Reference to _recordVaultIO - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 765 - -The comment says "The state changes produced here are handled in _recordVaultIO" but the function is named `recordVaultIO` (no underscore). - -**Impact:** Documentation-only. - -### INFORMATIONAL -- I05: Unused Error Declarations - -**Location:** `src/concrete/ob/OrderBookV6.sol` - -The following errors are declared but never used in `OrderBookV6.sol`: -- `TokenDecimalsMismatch` (line 83) -- `UnsupportedCalculateInputs` (line 95) -- `NegativeInput` (line 102) -- `NegativeOutput` (line 105) - -These may be used by other contracts or test utilities but are dead code within the main contract. - -**Impact:** None (dead code only). Gas cost for deployment is unaffected since errors are not stored in bytecode unless reverted. - -### INFORMATIONAL -- I06: Interface Errors OrderNoSources and OrderNoHandleIO Declared But Not Checked - -**Location:** `IRaindexV6` interface declares `OrderNoSources` and `OrderNoHandleIO` errors, but `OrderBookV6.addOrder4` does not check for these conditions. - -The interface specification says: -- "MUST revert with `OrderNoSources` if the order has no associated calculation" -- "MUST revert with `OrderNoHandleIO` if the order has no handle IO entrypoint" - -The implementation does not validate bytecode source count. An order with no sources or no handle IO source will succeed on `addOrder4` but fail at clear/take time when the interpreter is called. This is a deliberate design choice (fail-late) but technically deviates from the MUST requirement in the interface NatSpec. - -**Impact:** Low. Orders without proper sources will still fail when evaluated. The interface NatSpec is aspirational rather than prescriptive here, as the V6 design philosophy defers validation to runtime. - -### INFORMATIONAL -- I07: ERC-165 Does Not Register IRaindexV6 Interface - -**Location:** `src/abstract/OrderBookV6FlashLender.sol` line 33-34, `src/concrete/ob/OrderBookV6.sol` line 198 - -The `supportsInterface` only registers `IERC3156FlashLender`. The primary `IRaindexV6` interface is not registered. Tools or contracts querying ERC-165 for `IRaindexV6` support will get `false`. - -**Impact:** Low. May affect discoverability by tools but does not affect core functionality. - -### INFORMATIONAL -- I08: HANDLE_IO_MAX_OUTPUTS NatSpec Typo - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 150 - -The comment says "Handle IO has no outputs as it only response to vault movements" -- should be "responds" not "response". - -**Impact:** None (typo in comment). - -## Summary - -No HIGH or MEDIUM severity findings. The contract logic is correct: -- `calculateClearStateAlice` math is sound -- `recordVaultIO` parameter order is correct at all call sites -- Error conditions match their names -- Token flow in `takeOrders4` and `clear3` is correctly oriented -- Bounty calculation and distribution uses correct token addresses -- Stack reading order matches interpreter convention -- `ClearZeroAmount` placement after `handleIO` is intentional and correct - -All findings are INFORMATIONAL severity, predominantly involving stale NatSpec/comments from the migration to floating point math and minor dead code. diff --git a/audit/2026-03-13-01/pass5/OrderBookV6ArbCommon.md b/audit/2026-03-13-01/pass5/OrderBookV6ArbCommon.md deleted file mode 100644 index fa7ca4cc84..0000000000 --- a/audit/2026-03-13-01/pass5/OrderBookV6ArbCommon.md +++ /dev/null @@ -1,120 +0,0 @@ -# Pass 5: Correctness -- OrderBookV6ArbCommon.sol - -**Agent:** A01 -**File:** `src/abstract/OrderBookV6ArbCommon.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6ArbCommon` (abstract, line 34) - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| struct | `OrderBookV6ArbConfig` | 21-25 | -| error | `WrongTask()` | 28 | -| constant | `BEFORE_ARB_SOURCE_INDEX` | 32 | - -### Functions / Modifiers - -| Name | Kind | Line | -|------|------|------| -| `constructor(OrderBookV6ArbConfig)` | constructor | 41-48 | -| `onlyValidTask(TaskV2)` | modifier | 50-55 | - -### Events - -| Name | Line | -|------|------| -| `Construct(address, OrderBookV6ArbConfig)` | 37 | - -### State Variables - -| Name | Kind | Line | -|------|------|------| -| `iTaskHash` | `bytes32 public immutable` | 39 | - -## Correctness Verification - -### 1. `OrderBookV6ArbConfig` struct (lines 21-25) - -**NatSpec claims:** -- `@param orderBook` -- "The `OrderBook` contract to arb against." -- `@param tasks` -- "The tasks to use as post for each arb." (Note: param name says `tasks` plural but actual field is `task` singular) -- `@param implementationData` -- "The constructor data for the specific implementation of the arb contract." - -**Verification:** The struct contains `address orderBook`, `TaskV2 task`, and `bytes implementationData`. The `orderBook` field is not used within this contract (it is consumed by concrete implementations). The `task` field is hashed and stored. The `implementationData` field is consumed by concrete implementations. - -**Finding:** The NatSpec says `@param tasks` (plural) but the field is `TaskV2 task` (singular). This is a doc mismatch. - -### 2. `WrongTask` error (line 28) - -**NatSpec claim:** "Thrown when the task does not match the expected hash." - -**Verification:** Used in the `onlyValidTask` modifier at line 51. The modifier reverts with `WrongTask()` when `iTaskHash != bytes32(0) && iTaskHash != keccak256(abi.encode(task))`. This correctly throws when a non-zero task hash was set at construction and the provided task doesn't match. - -**Tests:** `GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` (line 50) and `RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` (line 42) both `vm.expectRevert(abi.encodeWithSelector(WrongTask.selector))` with mismatched evaluables. The test names (`testGenericPoolTakeOrdersWrongExpression`, `testRouteProcessorTakeOrdersWrongExpression`) describe the behavior they test. Verified: the tests provide an evaluable that differs from the one used at construction, and correctly expect `WrongTask`. - -**Verdict:** Error name, documentation, and implementation all match. Tests confirm the behavior. - -### 3. `BEFORE_ARB_SOURCE_INDEX` constant (line 32) - -**NatSpec claim:** "'Before arb' is evaluated before the flash loan is taken. Ostensibly allows for some kind of access control to the arb." - -**Verification:** The constant is set to `SourceIndexV2.wrap(0)`. It is not used within this contract. It is duplicated in `OrderBookV6ArbOrderTaker.sol` (line 29). Previously flagged across passes 1-4. - -**Verdict:** The doc mentions "flash loan" specifically, but this contract is also inherited by `OrderBookV6ArbOrderTaker` which does not use flash loans. The doc is misleadingly narrow (flagged in pass 3 as A01-P3-3). The constant is unused in this file (flagged in pass 4 as A01-P4-2). - -### 4. `iTaskHash` immutable (line 39) - -**Behavior:** Initialized to `0` by default. In the constructor, if `config.task.evaluable.bytecode.length != 0`, it is set to `keccak256(abi.encode(config.task))`. Otherwise it stays `0`. - -**Verification:** A zero `iTaskHash` means "no task validation" (the `onlyValidTask` modifier skips the check when `iTaskHash == bytes32(0)`). A non-zero `iTaskHash` enforces that the provided task matches what was set at construction. This is correct. - -### 5. `onlyValidTask` modifier (lines 50-55) - -**Logic:** `if (iTaskHash != bytes32(0) && iTaskHash != keccak256(abi.encode(task))) { revert WrongTask(); }` - -**Verification:** When `iTaskHash == 0` (no task configured), ANY task is accepted, including one with non-empty bytecode. This is by design -- it allows permissionless arb bots to provide their own post-arb tasks. When `iTaskHash != 0`, only the exact task configured at construction is accepted. - -**Correctness concern:** The modifier uses `abi.encode(task)` which encodes the entire `TaskV2` struct including `signedContext`. This means the signed context array must also match, not just the evaluable. For a task set at construction with an empty `signedContext`, callers must also provide an empty `signedContext`. This is correct and intentional -- it prevents callers from injecting arbitrary signed context into a fixed task. - -### 6. Constructor (lines 41-48) - -**Verification:** Emits `Construct` event before any external calls. Then conditionally sets `iTaskHash`. No external calls are made. The `Construct` event is tested in `ArbTest.sol` (line 82): `vm.expectEmit(); emit Construct(address(this), config);`. - -**Verdict:** Correct. - -### 7. `Construct` event (line 37) - -**NatSpec:** None beyond the event signature. -**Verification:** Emitted in the constructor with `msg.sender` and the full config. Tested in `ArbTest.sol`. Correct. - -## Findings - -### A01-P5-1 [LOW] NatSpec `@param tasks` does not match field name `task` - -**Severity:** LOW -**Confidence:** HIGH - -**Location:** Line 18 - -The NatSpec reads `@param tasks` (plural) but the struct field is `TaskV2 task` (singular, line 22). This mismatch could confuse developers reading the documentation without looking at the code. It appears to be a leftover from when the struct may have held an array of tasks. - -**Recommendation:** Change line 18 to `@param task The task to use as post for each arb.` - -### A01-P5-2 [INFO] `onlyValidTask` accepts any task when no task hash is configured - -When `iTaskHash == bytes32(0)` (no task bytecode at construction), the `onlyValidTask` modifier passes unconditionally, allowing callers to provide any arbitrary task including one with untrusted bytecode. This is by design for permissionless arb bots, but it is worth noting that an arb contract deployed without a task hash provides no post-arb validation. No fix needed; this is documenting intended behavior. - -### A01-P5-3 [INFO] Constructor emits event before state mutation (good) - -The constructor correctly emits `Construct` before setting `iTaskHash`, following the events-before-external-calls pattern. Since no external calls are made in this constructor, the ordering is informational only, but it is good practice. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A01-P5-1 | LOW | NatSpec `@param tasks` does not match field name `task` | -| A01-P5-2 | INFO | `onlyValidTask` accepts any task when no task hash configured | -| A01-P5-3 | INFO | Constructor event ordering is correct | diff --git a/audit/2026-03-13-01/pass5/OrderBookV6ArbOrderTaker.md b/audit/2026-03-13-01/pass5/OrderBookV6ArbOrderTaker.md deleted file mode 100644 index 5d12d03440..0000000000 --- a/audit/2026-03-13-01/pass5/OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,120 +0,0 @@ -# Pass 5: Correctness -- OrderBookV6ArbOrderTaker.sol - -**Agent:** A02 -**File:** `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6ArbOrderTaker` (abstract, line 31) -- Inherits: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| error | `NonZeroBeforeArbInputs(uint256)` | 25 | -| constant | `BEFORE_ARB_SOURCE_INDEX` | 29 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `constructor(OrderBookV6ArbConfig)` | internal | 40 | -| `supportsInterface(bytes4)` | public view virtual | 43-46 | -| `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` | external payable | 49-75 | -| `onTakeOrders2(address, address, Float, Float, bytes)` | public virtual | 78 | - -## Correctness Verification - -### 1. `supportsInterface` (lines 43-46) -- ERC-165 Conformance - -**Claim:** Supports `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, and `IERC165` interfaces. - -**Implementation:** -```solidity -return (interfaceId == type(IRaindexV6OrderTaker).interfaceId) - || (interfaceId == type(IRaindexV6ArbOrderTaker).interfaceId) || super.supportsInterface(interfaceId); -``` - -**Verification:** `super.supportsInterface` calls `ERC165.supportsInterface` which returns `true` for `type(IERC165).interfaceId`. The three interface IDs are correctly checked. - -**Test:** `OrderBookV6ArbOrderTaker.ierc165.t.sol` (line 23-33) -- creates `ChildOrderBookV6ArbOrderTaker`, asserts `true` for all three supported interfaces, and asserts `false` for a fuzzed `badInterfaceId` (with `vm.assume` excluding the supported ones). Test name `testOrderBookV6ArbOrderTakerIERC165` matches test behavior. - -**Verdict:** Correct. ERC-165 implementation and tests are sound. - -### 2. `arb5` function (lines 49-75) -- Core arb logic - -**NatSpec claim:** `@inheritdoc IRaindexV6ArbOrderTaker` -- "Executes an arbitrage against the given Raindex." - -**Implementation verification, step by step:** - -1. **Line 56-58: Zero orders check.** Reverts with `IRaindexV6.NoOrders()` if `takeOrders.orders.length == 0`. This mimics the orderbook's own check (as the comment states). Verified: `IRaindexV6` defines `error NoOrders()` at line 222 of the interface. - -2. **Lines 60-61: Token extraction.** Extracts `ordersInputToken` and `ordersOutputToken` from the first order. `ordersInputToken = takeOrders.orders[0].order.validInputs[takeOrders.orders[0].inputIOIndex].token` and `ordersOutputToken = takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token`. These are the order's input/output tokens. - -3. **Line 63: Approval.** `forceApprove(ordersInputToken, type(uint256).max)` -- approves the orderbook to pull `ordersInputToken` from this contract. This is needed because in `takeOrders4`, the orderbook pulls the taker's output (which is the order's input) from the taker. - -4. **Line 64: Take orders.** Calls `orderBook.takeOrders4(takeOrders)`. Returns `(Float totalTakerInput, Float totalTakerOutput)`. - -5. **Line 65: Suppress warnings.** `(totalTakerInput, totalTakerOutput);` -- intentionally suppresses unused variable warnings. - -6. **Line 66: Revoke approval.** `forceApprove(ordersInputToken, 0)` -- revokes the approval after taking orders. - -7. **Lines 68-74: Finalize.** Calls `LibOrderBookArb.finalizeArb(task, ordersInputToken, inputDecimals, ordersOutputToken, outputDecimals)` which sweeps all remaining tokens and ETH to `msg.sender` and runs the post-arb task. - -**Test:** `OrderBookV6ArbOrderTaker.context.t.sol` tests the context passed to the post-arb task. It mocks token balances (3e12 for input, 4e12 for output, both 12 decimals) and 5 ETH. The post-arb expression asserts `context<1 0>() == 3`, `context<1 1>() == 4`, `context<1 2>() == 5`. This verifies the decimal conversion in `finalizeArb`: 3e12 with 12 decimals = 3.0, 4e12 with 12 decimals = 4.0, 5e18 wei at 18 decimals = 5.0. Test name matches behavior. - -**Correctness concern -- token assumption:** Lines 60-61 extract tokens from only the first order (`orders[0]`). If a batch of orders has different input/output tokens, only the first order's tokens are used for approval and finalization. The orderbook's `takeOrders4` handles multi-token batches internally, but the approval on line 63 only covers `ordersInputToken` from the first order. If later orders have different input tokens, the approval would be insufficient. However, this is documented behavior in the orderbook design -- all orders in a single `takeOrders` batch are expected to have the same token pair. - -### 3. `onTakeOrders2` (line 78) -- Order taker callback - -**NatSpec claim:** `@inheritdoc IRaindexV6OrderTaker` - -**Implementation:** Empty body `{}`. This callback is invoked by the orderbook during `takeOrders4` if `config.data.length > 0`. The empty implementation means this contract does nothing when receiving tokens during the take-orders flow. - -**Verification:** The `IRaindexV6OrderTaker` interface defines `onTakeOrders2` at line 37. The signature matches. An empty implementation is valid -- the arb order taker doesn't need to do anything special when receiving tokens because `finalizeArb` handles the sweep afterward. - -**Verdict:** Correct. - -### 4. `NonZeroBeforeArbInputs` error (line 25) - -**NatSpec claim:** "Thrown when 'before arb' wants inputs that we don't have." - -**Verification:** This error is NEVER used anywhere in the codebase. It is dead code. Confirmed across passes 1-4 (A02-2, A02-P2-5, A02-P3-4, A02-P4-3). - -**Verdict:** NatSpec describes behavior that does not exist. The error should be removed. - -### 5. `BEFORE_ARB_SOURCE_INDEX` constant (line 29) - -**NatSpec claim:** "'Before arb' is evaluabled before the arb is executed. Ostensibly this is to allow for access control to the arb, the return values are ignored." - -**Verification:** This constant duplicates `OrderBookV6ArbCommon.sol` line 32. Neither is used in this file. The NatSpec contains a typo: "evaluabled" should be "evaluated". Confirmed across passes 1-4. - -**Verdict:** Dead constant with typo in documentation. - -### 6. Modifiers on `arb5` -- `nonReentrant`, `onlyValidTask` - -**`nonReentrant`:** Prevents reentrancy during the arb. This is critical because `arb5` makes external calls (`takeOrders4`, token transfers in `finalizeArb`). - -**`onlyValidTask`:** Validates the task parameter against the stored hash (or allows any task if no hash was set). See A01 analysis. - -**Verdict:** Both modifiers are correctly applied. - -## Findings - -### A02-P5-1 [INFO] `arb5` assumes all orders share the same token pair - -**Location:** Lines 60-61 - -The function extracts `ordersInputToken` and `ordersOutputToken` from `takeOrders.orders[0]` only. If the batch contains orders with different token pairs, the approval (line 63) would only cover the first order's input token, and `finalizeArb` would only sweep those two tokens. This is consistent with the orderbook's design (batches are same-pair), but the function does not validate this assumption. An incorrect batch would fail at the orderbook level, so no funds are at risk, but the error message would be confusing. - -### A02-P5-2 [INFO] Empty `onTakeOrders2` callback is correct for this use case - -The empty callback is intentional -- the arb order taker receives tokens during `takeOrders4` and handles them post-hoc in `finalizeArb`. The function signature correctly matches `IRaindexV6OrderTaker.onTakeOrders2`. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A02-P5-1 | INFO | `arb5` assumes all orders share the same token pair | -| A02-P5-2 | INFO | Empty `onTakeOrders2` callback is correct | diff --git a/audit/2026-03-13-01/pass5/OrderBookV6FlashBorrower.md b/audit/2026-03-13-01/pass5/OrderBookV6FlashBorrower.md deleted file mode 100644 index 478c69b161..0000000000 --- a/audit/2026-03-13-01/pass5/OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,178 +0,0 @@ -# Pass 5: Correctness -- OrderBookV6FlashBorrower.sol - -**Agent:** A03 -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashBorrower` (abstract, line 62) -- Inherits: `IERC3156FlashBorrower`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| error | `BadInitiator(address)` | 24 | -| error | `FlashLoanFailed()` | 27 | -| error | `SwapFailed()` | 30 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `constructor(OrderBookV6ArbConfig)` | internal | 66 | -| `supportsInterface(bytes4)` | public view virtual | 69-71 | -| `_exchange(TakeOrdersConfigV5, bytes)` | internal virtual | 82 | -| `onFlashLoan(address, address, uint256, uint256, bytes)` | external | 85-107 | -| `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` | external payable | 130-165 | - -## Correctness Verification - -### 1. `supportsInterface` (lines 69-71) -- ERC-165 Conformance - -**Implementation:** Returns `true` for `type(IERC3156FlashBorrower).interfaceId` or delegates to `super`. - -**Test:** `OrderBookV6FlashBorrower.ierc165.t.sol` (line 36-44) creates `ChildOrderBookV6FlashBorrower`, asserts `true` for `IERC165` and `IERC3156FlashBorrower`, asserts `false` for fuzzed bad IDs. - -**Verdict:** Correct. ERC-165 conformance verified. - -### 2. `onFlashLoan` (lines 85-107) -- Flash loan callback - -**NatSpec claim:** `@inheritdoc IERC3156FlashBorrower` -- per ERC-3156, must receive a flash loan, perform actions, and return `keccak256("ERC3156FlashBorrower.onFlashLoan")`. - -**Implementation verification:** - -1. **Line 87-89: Initiator check.** `if (initiator != address(this)) { revert BadInitiator(initiator); }` -- verifies the flash loan was initiated by this contract. Correct per ERC-3156 reference implementation. - -2. **Lines 91-92: Decode data.** Decodes `(TakeOrdersConfigV5, bytes)` from the callback data. This was encoded in `arb4` at line 142. - -3. **Line 96: Exchange.** Calls `_exchange(takeOrders, exchangeData)` -- virtual hook for concrete implementations to swap flash-loaned tokens for order input tokens on external markets. - -4. **Line 103: Take orders.** `IRaindexV6(msg.sender).takeOrders4(takeOrders)` -- takes orders on the orderbook. Uses `msg.sender` as the orderbook address. - -5. **Line 106: Return success.** Returns `ON_FLASH_LOAN_CALLBACK_SUCCESS`. - -**Critical finding -- missing lender validation:** The function does NOT validate that `msg.sender` is the trusted orderbook. The imported `BadLender` error (line 18) is never used. This was flagged as A03-1 [MEDIUM] in pass 1 and confirmed in passes 2-4. The concern: any contract can call `onFlashLoan(address(this), ...)` on the flash borrower. While the `initiator` check passes if the caller spoofs `address(this)`, and the `msg.sender` is used as the orderbook for `takeOrders4`, the practical impact is limited because: -- The flash borrower should be empty of tokens between arb calls -- `arb4` is `nonReentrant`, so this can't be called during an active arb -- The attacker would need to send tokens to the borrower first, then call `onFlashLoan`, which would call `takeOrders4` on the attacker's contract - -However, the missing check violates the ERC-3156 security pattern and could enable exploitation if the flash borrower ever holds tokens unexpectedly. - -**Verdict:** Functionally correct in the happy path. Missing lender check is a confirmed medium-severity issue (A03-1). - -### 3. `arb4` (lines 130-165) -- Primary arb function - -**NatSpec claims:** -- Line 110: "Primary function to process arbitrage opportunities." -- Line 111-113: "Firstly the access gate is evaluated..." -- Line 117-119: "Secondly the flash loan is taken and the `_exchange` hook is called..." -- Line 121-122: "Finally the orders are taken and the remaining assets are sent to the sender." -- Line 124: `@param takeOrders As per IOrderBookV5.takeOrders3` -- STALE: should be `IRaindexV6.takeOrders4` - -**Implementation verification:** - -1. **Line 135: Modifiers.** `nonReentrant` and `onlyValidTask(task)` -- correct. - -2. **Lines 137-139: Zero orders check.** Same pattern as `arb5` in ArbOrderTaker. - -3. **Lines 142-146: Setup.** Encodes callback data, extracts token addresses. - -4. **Lines 148-149: Decimals.** Fetches decimals for both tokens via `LibTOFUTokenDecimals.safeDecimalsForToken`. - -5. **Line 153: Flash loan amount.** - ```solidity - uint256 flashLoanAmount = LibDecimalFloat.toFixedDecimalLossless(takeOrders.minimumIO, inputDecimals); - ``` - **CONFIRMED BUG (A03-3):** The flash loan borrows `ordersOutputToken` (line 159), but the amount is converted using `inputDecimals` (decimals of `ordersInputToken`). When `IOIsInput=true`, `minimumIO` represents the minimum taker input, denominated in the taker's input which is `ordersOutputToken`. Converting with `inputDecimals` instead of `outputDecimals` produces the wrong fixed-point value when the two tokens have different decimal precisions. This was flagged as A03-3 [MEDIUM] in pass 1 and has an existing fix file. - -6. **Lines 158-162: Flash loan execution.** Approves `ordersInputToken`, calls `flashLoan`, checks return value, revokes approval. - -7. **Line 164: Finalize.** `LibOrderBookArb.finalizeArb(task, ordersInputToken, inputDecimals, ordersOutputToken, outputDecimals)` sweeps remaining tokens and ETH to caller, runs post-arb task. - -**NatSpec accuracy issues:** -- Line 111-113 says "Firstly the access gate is evaluated" but there is no access gate evaluation in the function body. The access control is now handled by the `onlyValidTask` modifier and the `doPost` call in `finalizeArb`. The NatSpec is stale from when `_beforeArb` existed. -- Line 124 references `IOrderBookV5.takeOrders3` but the actual method is `IRaindexV6.takeOrders4`. -- Line 128 references `GenericPoolOrderBookV5FlashBorrower` but should be `GenericPoolOrderBookV6FlashBorrower`. - -**Test:** `GenericPoolOrderBookV6FlashBorrower.sender.t.sol` tests the happy path with mocked token interactions and `minimumIO = 0`, which avoids exercising the decimal bug. The test uses `FlashLendingMockOrderBook` which is a no-op mock that does not perform real token transfers, so the economic flow is not tested. - -### 4. `_exchange` virtual hook (line 82) - -**NatSpec claim:** "Hook that inheriting contracts MUST implement in order to achieve anything other than raising the ambient temperature of the room." - -**Implementation:** Empty body `{}`. Marked `internal virtual`. - -**Verification:** Concrete implementations like `GenericPoolOrderBookV6FlashBorrower` override this to perform actual swaps. The empty default is harmless but means a contract that forgets to override it will silently do nothing during the exchange step, leading to failed arbs (not a security issue, just an economic one). - -**Verdict:** Correct. The NatSpec's MUST is advisory, not enforced by the compiler (since the function has a default implementation rather than being `abstract`). - -### 5. `BadInitiator` error (line 24) - -**NatSpec claim:** "Thrown when the initiator is not the order book." - -**Verification:** The error is thrown at line 88 when `initiator != address(this)`. The NatSpec says "not the order book" but the check is actually `!= address(this)` (the flash borrower contract itself, not the order book). The initiator in ERC-3156 is the entity that called `flashLoan` on the lender. When `arb4` calls `orderBook.flashLoan(this, ...)`, the lender sets `initiator = msg.sender` which is the flash borrower. So the check verifies that the flash loan was initiated by this contract. - -**Finding:** The NatSpec is inaccurate. The error is thrown when the initiator is not `address(this)` (the flash borrower), not when it is "not the order book." The order book is `msg.sender` in the callback, not the initiator. - -### 6. `FlashLoanFailed` error (line 27) - -**NatSpec claim:** "Thrown when the flash loan fails somehow." - -**Verification:** Used at line 161: `if (!orderBook.flashLoan(...)) { revert FlashLoanFailed(); }`. Correct -- thrown when the flash loan returns `false`. - -**Verdict:** NatSpec matches implementation. - -### 7. `SwapFailed` error (line 30) - -**NatSpec claim:** "Thrown when the swap fails." - -**Verification:** Never used anywhere in the codebase. Dead code. Confirmed across passes 1-4 (A03-P2-4, A03-P4-2). - -**Verdict:** Dead error with accurate NatSpec for behavior that does not exist. - -### 8. NatSpec title (line 32) - -**Claim:** `@title OrderBookV5FlashBorrower` - -**Verification:** Contract name is `OrderBookV6FlashBorrower`. The `V5` in the title is stale. Confirmed in pass 4 (A03-P4-3). - -## Findings - -### A03-P5-1 [LOW] `BadInitiator` NatSpec inaccurately describes the check - -**Severity:** LOW -**Confidence:** HIGH - -**Location:** Line 22-24 - -The NatSpec says "Thrown when the initiator is not the order book" but the actual check (line 87) is `initiator != address(this)`, verifying the initiator is the flash borrower contract itself. The order book is the `msg.sender` in the callback, not the initiator. This misleads readers about what security property the check enforces. - -**Recommendation:** Change line 22 to: `/// Thrown when the initiator is not this contract (the flash borrower).` - -### A03-P5-2 [LOW] NatSpec for `arb4` describes stale "access gate" evaluation - -**Severity:** LOW -**Confidence:** HIGH - -**Location:** Lines 110-122 - -The NatSpec describes three steps: (1) access gate evaluation, (2) flash loan + exchange, (3) take orders + send remaining assets. Step 1 no longer exists in the function body -- there is no `_beforeArb` call. Access control is now via the `onlyValidTask` modifier and the post-arb task in `finalizeArb`. The NatSpec is stale from a prior architecture. - -**Recommendation:** Rewrite the NatSpec to describe the actual steps: (1) validate task, (2) flash loan + exchange + take orders, (3) finalize (sweep tokens/ETH, run post-arb task). - -### A03-P5-3 [INFO] Confirmed prior findings still present - -The following findings from earlier passes remain valid and unaddressed: -- **A03-1 [MEDIUM]**: Missing `msg.sender` (lender) validation in `onFlashLoan`. Fix exists at `.fixes/A03-1.md`. -- **A03-3 [MEDIUM]**: Flash loan amount computed with wrong token decimals (`inputDecimals` instead of `outputDecimals`). Fix exists at `.fixes/A03-3.md`. -- **A03-P4-2 [LOW]**: Dead error `SwapFailed`. -- **A03-P4-3 [LOW]**: Stale NatSpec title `OrderBookV5FlashBorrower`. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A03-P5-1 | LOW | `BadInitiator` NatSpec inaccurately describes the check | -| A03-P5-2 | LOW | NatSpec for `arb4` describes stale "access gate" evaluation | -| A03-P5-3 | INFO | Confirmed prior findings still present (A03-1, A03-3, A03-P4-2, A03-P4-3) | diff --git a/audit/2026-03-13-01/pass5/OrderBookV6FlashLender.md b/audit/2026-03-13-01/pass5/OrderBookV6FlashLender.md deleted file mode 100644 index 3d571e1cf4..0000000000 --- a/audit/2026-03-13-01/pass5/OrderBookV6FlashLender.md +++ /dev/null @@ -1,166 +0,0 @@ -# Pass 5: Correctness -- OrderBookV6FlashLender.sol - -**Agent:** A04 -**File:** `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashLender` (abstract, line 29) -- Inherits: `IERC3156FlashLender`, `ERC165` - -### Types / Errors / Constants - -| Kind | Name | Line | -|------|------|------| -| error | `FlashLenderCallbackFailed(bytes32)` | 18 | -| constant | `FLASH_FEE` | 23 | - -### Functions - -| Function | Visibility | Line | -|----------|-----------|------| -| `supportsInterface(bytes4)` | public view virtual | 33-35 | -| `flashLoan(IERC3156FlashBorrower, address, uint256, bytes)` | external | 38-67 | -| `flashFee(address, uint256)` | external pure | 70-72 | -| `maxFlashLoan(address)` | external view | 78-80 | - -## Correctness Verification - -### 1. `supportsInterface` (lines 33-35) -- ERC-165 Conformance - -**Implementation:** Returns `true` for `type(IERC3156FlashLender).interfaceId` or delegates to `super.supportsInterface` (which covers `IERC165`). - -**Test:** `OrderBookV6FlashLender.ierc165.t.sol` (line 18-27) creates `ChildOrderBookV6FlashLender`, asserts `true` for `IERC165` and `IERC3156FlashLender`, asserts `false` for fuzzed bad IDs. - -**Verdict:** Correct. - -### 2. `FLASH_FEE` constant (line 23) - -**NatSpec claim:** "Flash fee is always 0 for orderbook as there's no entity to take revenue for `Orderbook` and its more important anyway that flashloans happen to connect external liquidity to live orders via arbitrage." - -**Value:** `uint256 constant FLASH_FEE = 0` - -**Verification:** Used at line 45 (`FLASH_FEE` passed as fee parameter to `onFlashLoan`) and line 64 (`amount + FLASH_FEE` in `safeTransferFrom` -- effectively just `amount`). Also returned by `flashFee` at line 71. - -**Test:** `OrderBookV6FlashLender.fee.t.sol` (line 11-13) asserts `iOrderbook.flashFee(token, amount) == 0` for all fuzzed inputs. Test name `testFlashFee` matches behavior. - -**Verdict:** Correct. Constant value matches documentation and is consistently used. - -### 3. `FlashLenderCallbackFailed` error (line 18) - -**NatSpec claim:** "Thrown when the `onFlashLoan` callback returns anything other than ON_FLASH_LOAN_CALLBACK_SUCCESS." - -**Verification:** Used at line 46-48: -```solidity -bytes32 result = receiver.onFlashLoan(msg.sender, token, amount, FLASH_FEE, data); -if (result != ON_FLASH_LOAN_CALLBACK_SUCCESS) { - revert FlashLenderCallbackFailed(result); -} -``` - -**Test:** `OrderBookV6FlashLender.griefRecipient.t.sol` (line 45) tests with `notFlashLoanSuccess` and expects `FlashLenderCallbackFailed(notFlashLoanSuccess)`. Also tested in `OrderBookV6FlashLender.transfers.t.sol` (line 95) when the callback returns `bytes32(0)` (failure case). - -**Verdict:** Error name, NatSpec, implementation, and tests all match. The error parameter correctly captures the actual return value for debugging. - -### 4. `flashLoan` function (lines 38-67) -- ERC-3156 Conformance - -**NatSpec claim:** `@inheritdoc IERC3156FlashLender` -- per ERC-3156: "Initiate a flash loan." - -**Implementation verification against ERC-3156 spec:** - -1. **Line 43: Transfer tokens to receiver.** `IERC20(token).safeTransfer(address(receiver), amount)` -- correct per spec. - -2. **Line 45: Call `onFlashLoan`.** `receiver.onFlashLoan(msg.sender, token, amount, FLASH_FEE, data)` -- correct. The first parameter is `msg.sender` (the initiator), which is whoever called `flashLoan`. Per ERC-3156, the initiator is the `msg.sender` of the `flashLoan` call. - -3. **Lines 46-48: Check callback return.** Verifies `ON_FLASH_LOAN_CALLBACK_SUCCESS`. Correct per spec. - -4. **Line 64: Reclaim tokens.** `IERC20(token).safeTransferFrom(address(receiver), address(this), amount + FLASH_FEE)` -- with `FLASH_FEE = 0`, this is `amount`. Correct per spec: the lender reclaims `amount + fee`. - -5. **Line 66: Return true.** Correct per spec: "True if the flash loan was successful." - -**ERC-3156 compliance analysis:** - -- **Initiator parameter:** The spec says the lender MUST pass `msg.sender` as the initiator to `onFlashLoan`. Implementation does this correctly (line 45). -- **Fee:** The spec says `flashFee` MUST NOT revert for supported tokens. The implementation's `flashFee` never reverts (it is `pure` and returns `0`). Since OrderBook accepts any ERC-20 token, all tokens are "supported." -- **`maxFlashLoan` for unsupported tokens:** ERC-3156 says `maxFlashLoan` MUST return `0` for unsupported tokens. Since all ERC-20 tokens are supported, returning `balanceOf` is correct. For non-ERC20 addresses, `balanceOf` will revert, which is acceptable since those are truly unsupported. -- **Approval model:** ERC-3156 says the receiver MUST approve the lender for `amount + fee` before `onFlashLoan` returns. The implementation relies on this via `safeTransferFrom`. Correct. - -**Reentrancy:** The `flashLoan` function is NOT protected by `nonReentrant`. This is intentional -- the reentrant test file (`OrderBookV6FlashLender.reentrant.t.sol`) explicitly tests that flash borrowers can re-enter the orderbook (deposit, withdraw, addOrder, removeOrder, takeOrders, clear) while the loan is active. The concrete `OrderBookV6` contract uses `nonReentrant` on individual state-mutating functions but not on `flashLoan` itself, allowing controlled re-entry patterns. - -**Test coverage:** -- `OrderBookV6FlashLender.mockSuccess.t.sol` -- tests happy path with mocked receiver returning `ON_FLASH_LOAN_CALLBACK_SUCCESS`. -- `OrderBookV6FlashLender.transfers.t.sol` -- tests real token transfers. Success case (Bob returns tokens) and failure case (Carol withholds tokens, causing `ERC20InsufficientBalance`). Also tests callback failure (Alice returns bad callback value). -- `OrderBookV6FlashLender.griefRecipient.t.sol` -- tests that non-conforming receivers are rejected. -- `OrderBookV6FlashLender.reentrant.t.sol` -- tests re-entry from within flash loan callbacks. - -**Verdict:** Correct ERC-3156 implementation. Tests are comprehensive. - -### 5. `flashFee` function (lines 70-72) - -**NatSpec claim:** `@inheritdoc IERC3156FlashLender` - -**Implementation:** Returns `FLASH_FEE` (0) for any `(address, uint256)` inputs. Parameter names are dropped. - -**ERC-3156 compliance:** The spec says `flashFee` "MUST return the fee charged for a loan of `amount` `token`." Returning 0 for all tokens is correct if all tokens are supported (which they are for OrderBook). The spec also says it "MUST NOT revert" for supported tokens. A `pure` function cannot revert (barring stack overflow), so this is satisfied. - -**Verdict:** Correct. - -### 6. `maxFlashLoan` function (lines 78-80) - -**NatSpec claims (lines 74-76):** -1. "There's no limit to the size of a flash loan from `Orderbook` other than the current tokens deposited in `Orderbook`." -2. "If there is an active debt then loans are disabled so the max becomes `0` until after repayment." - -**Implementation:** `return IERC20(token).balanceOf(address(this));` - -**Verification of claim 1:** Correct -- the maximum is the token balance. - -**Verification of claim 2:** **INCORRECT.** There is no active-debt tracking anywhere in the contract or its concrete implementation (`OrderBookV6`). A `grep` for "debt", "activeDebt", "flashLoanActive" across the entire `src/` tree returns zero results beyond this comment. The function always returns `balanceOf(address(this))` regardless of whether a flash loan is currently in progress. During an active flash loan, the balance would be reduced by the loaned amount (since the lender transferred tokens to the borrower), so `maxFlashLoan` would naturally return a lower value. But it does NOT return `0` -- it returns `currentBalance - loanedAmount`. This is a confirmed NatSpec-vs-implementation mismatch, flagged as A04-1 in pass 1 and A04-P3-1 in pass 3. - -**ERC-3156 compliance:** The spec says `maxFlashLoan` "The amount of `token` that can be borrowed." Returning `balanceOf` is correct -- it's the maximum amount that can actually be lent. The spec also says it MUST return 0 for unsupported tokens. Since all ERC-20s are supported and `balanceOf` returns the actual available amount, this is correct. - -**Test:** `OrderBookV6FlashLender.maxFlashLoan.t.sol` (line 13-18) mocks `balanceOf` to return a fuzzed amount and asserts `maxFlashLoan` returns the same. Test name `testFlashMaxLoan` matches behavior. - -**Verdict:** Implementation is correct for ERC-3156. NatSpec claim about active debt is false. - -## Findings - -### A04-P5-1 [LOW] `maxFlashLoan` NatSpec falsely claims active-debt disabling - -**Severity:** LOW -**Confidence:** HIGH - -**Location:** Lines 74-76 - -The NatSpec states: "If there is an active debt then loans are disabled so the max becomes `0` until after repayment." This behavior does not exist. There is no debt tracking, no flag, and no logic that returns `0` during an outstanding loan. The function unconditionally returns `balanceOf(address(this))`. - -During an active flash loan, the balance is naturally reduced (tokens were sent to the borrower), so `maxFlashLoan` returns a reduced amount but NOT `0`. This means concurrent flash loans of the same token are technically possible (limited only by remaining balance), which may surprise integrators who read the NatSpec. - -This was flagged as A04-1 in pass 1 and A04-P3-1 in pass 3. - -**Recommendation:** Remove the sentence about active debt. The accurate description is: "There's no limit to the size of a flash loan from `OrderBook` other than the current tokens deposited in `OrderBook`." - -### A04-P5-2 [INFO] ERC-3156 conformance is correct - -All three functions (`flashLoan`, `flashFee`, `maxFlashLoan`) conform to the ERC-3156 specification: -- `flashLoan` correctly transfers tokens, calls `onFlashLoan` with proper parameters, validates the return value, and reclaims tokens. -- `flashFee` returns 0 for all tokens without reverting. -- `maxFlashLoan` returns the token balance held by the contract. -- `supportsInterface` correctly reports `IERC3156FlashLender`. - -### A04-P5-3 [INFO] Intentional lack of reentrancy protection on `flashLoan` is correct - -The `flashLoan` function is intentionally not `nonReentrant`. This allows borrowers to re-enter the orderbook during the loan (e.g., to take orders, deposit, withdraw). The concrete `OrderBookV6` protects individual state-mutating functions with `nonReentrant`. The reentrancy test suite (`OrderBookV6FlashLender.reentrant.t.sol`) validates this design by testing re-entry for all major operations. - -### A04-P5-4 [INFO] Test coverage is comprehensive - -The flash lender has 6 test files covering ERC-165 support, fee calculation, max loan amount, mock success, real token transfers (success and failure), grief attempts, and reentrancy. This is good coverage for an abstract contract. - -## Summary Table - -| ID | Severity | Title | -|----|----------|-------| -| A04-P5-1 | LOW | `maxFlashLoan` NatSpec falsely claims active-debt disabling | -| A04-P5-2 | INFO | ERC-3156 conformance is correct | -| A04-P5-3 | INFO | Intentional lack of reentrancy protection on `flashLoan` is correct | -| A04-P5-4 | INFO | Test coverage is comprehensive | diff --git a/audit/2026-03-13-01/pass5/OrderBookV6SubParser.md b/audit/2026-03-13-01/pass5/OrderBookV6SubParser.md deleted file mode 100644 index 56a718e4e6..0000000000 --- a/audit/2026-03-13-01/pass5/OrderBookV6SubParser.md +++ /dev/null @@ -1,81 +0,0 @@ -# Pass 5: Correctness — OrderBookV6SubParser.sol - -**Agent:** A09 -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` (307 lines) - -## Evidence of Thorough Reading - -- Read all 307 lines in full -- Verified all imports (lines 1-68): `LibParseOperand`, `BaseRainterpreterSubParser`, `OperandV2`, `IParserToolingV1`, `LibConvert`, `BadDynamicLength`, `LibExternOpContextSender`, `LibUint256Matrix`, plus all `DEPOSIT_WORD_*`, `WITHDRAW_WORD_*`, and `CONTEXT_*` constants from `LibOrderBookSubParser.sol` and `LibOrderBook.sol`, and generated pointers -- Verified `describedByMetaV1()` returns `DESCRIBED_BY_META_HASH` (line 75-77) -- Verified `subParserParseMeta()`, `subParserWordParsers()`, `subParserOperandHandlers()` return their respective generated pointers (lines 80-92) -- Verified `buildLiteralParserFunctionPointers()` returns empty bytes (lines 95-97) -- Verified `buildOperandHandlerFunctionPointers()` array size = `CONTEXT_COLUMNS + 2 + 1 + 1 = 5 + 4 = 9` columns (line 105) -- Verified `buildSubParserWordParsers()` array size = `CONTEXT_COLUMNS + 2 + 1 + 1 = 9` columns (line 194) -- Cross-checked every handler/parser slot against its context constant index - -## Correctness Verification - -### Constants and Column/Row Mapping in `buildOperandHandlerFunctionPointers` - -| Handler Array | Column Index | Size Constant | Row Indices Verified | -|---|---|---|---| -| `contextBaseHandlers` | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROWS` (2) | `CONTEXT_BASE_ROW_SENDER` (0), `CONTEXT_BASE_ROW_CALLING_CONTRACT` (1) | -| `contextCallingContextHandlers` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROWS` (3) | `..ROW_ORDER_HASH` (0), `..ROW_ORDER_OWNER` (1), `..ROW_ORDER_COUNTERPARTY` (2) | -| `contextCalculationsHandlers` | `CONTEXT_CALCULATIONS_COLUMN` (2) | `CONTEXT_CALCULATIONS_ROWS` (2) | `..ROW_MAX_OUTPUT` (0), `..ROW_IO_RATIO` (1) | -| `contextVaultInputsHandlers` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_ROWS` (5) | TOKEN(0), DECIMALS(1), VAULT_ID(2), BALANCE_BEFORE(3), BALANCE_DIFF(4) | -| `contextVaultOutputsHandlers` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_ROWS` (5) | TOKEN(0), DECIMALS(1), VAULT_ID(2), BALANCE_BEFORE(3), BALANCE_DIFF(4) | -| `contextSignersHandlers` | `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` (5) | `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` (1) | `..SIGNERS_ROW` (0) -> `handleOperandSingleFullNoDefault` | -| `contextSignedContextHandlers` | `CONTEXT_SIGNED_CONTEXT_START_COLUMN` (6) | `CONTEXT_SIGNED_CONTEXT_START_ROWS` (1) | `..START_ROW` (0) -> `handleOperandDoublePerByteNoDefault` | -| `contextDepositContextHandlers` | `CONTEXT_SIGNED_CONTEXT_START_COLUMN + 1` (7) | `DEPOSIT_WORDS_LENGTH` (5) | All 5 deposit word indices verified | -| `contextWithdrawContextHandlers` | `CONTEXT_SIGNED_CONTEXT_START_COLUMN + 2` (8) | `WITHDRAW_WORDS_LENGTH` (6) | All 6 withdraw word indices verified | - -All handler assignments use `LibParseOperand.handleOperandDisallowed` except signers (`handleOperandSingleFullNoDefault`) and signed-context (`handleOperandDoublePerByteNoDefault`). This is correct -- signers need a single operand to select which signer, and signed-context needs two bytes (column and row). - -### Constants and Column/Row Mapping in `buildSubParserWordParsers` - -Verified every parser function assignment matches the corresponding handler: - -| Parser Array Slot | Parser Function | Target Context | -|---|---|---| -| `contextBaseParsers[0]` | `subParserSender` | col 0, row 0 | -| `contextBaseParsers[1]` | `subParserCallingContract` | col 0, row 1 | -| `contextCallingContextParsers[0]` | `subParserOrderHash` | col 1, row 0 | -| `contextCallingContextParsers[1]` | `subParserOrderOwner` | col 1, row 1 | -| `contextCallingContextParsers[2]` | `subParserOrderCounterparty` | col 1, row 2 | -| `contextCalculationsParsers[0]` | `subParserMaxOutput` | col 2, row 0 | -| `contextCalculationsParsers[1]` | `subParserIORatio` | col 2, row 1 | -| Vault inputs [0-4] | subParser{Input*} | col 3, rows 0-4 | -| Vault outputs [0-4] | subParser{Output*} | col 4, rows 0-4 | -| Signers [0] | `subParserSigners` | col 5, operand-derived row | -| Signed context [0] | `subParserSignedContext` | col 6+operand byte, operand-derived row | -| Deposit [0-4] | `subParserSender`, `subParserDeposit{Token,VaultId,VaultBalanceBefore,VaultBalanceAfter}` | col 0/row 0 for depositor, col 1/rows 0-3 for rest | -| Withdraw [0-5] | `subParserSender`, `subParserWithdraw{Token,VaultId,...,TargetAmount}` | col 0/row 0 for withdrawer, col 1/rows 0-4 for rest | - -All parsers and handlers arrays are placed into the outer `parsers`/`handlers` arrays at the same column indices. Verified correct. - -### Memory-Safety of Assembly Blocks - -- Lines 179-181: `assembly ("memory-safe")` casts `handlers` to `handlersUint256`. Since both are `uint256[][]`, this is a safe no-op pointer cast. -- Lines 300-303: Same pattern for `parsers` to `parsersUint256`. - -Both are followed by `LibConvert.unsafeTo16BitBytes(*.flatten())` which is the standard pattern for building function pointer tables. - -## Findings - -### P5-A09-01 (INFO): Unused Imports `BadDynamicLength` and `LibExternOpContextSender` - -**Severity:** INFO -**File:** `src/concrete/parser/OrderBookV6SubParser.sol`, lines 12-13 - -**Details:** `BadDynamicLength` (imported from `rain.interpreter/error/ErrOpList.sol`) and `LibExternOpContextSender` (imported from `rain.interpreter/lib/extern/reference/op/LibExternOpContextSender.sol`) are imported but never referenced in any function or declaration in the contract body. `SUB_PARSER_WORD_PARSERS_LENGTH` was already flagged in pass 4 (P4-A09-03). - -**Impact:** No runtime impact. Compiler may warn but these are dead imports that add noise. - -## Summary - -| ID | Severity | Description | -|---|---|---| -| P5-A09-01 | INFO | Unused imports `BadDynamicLength` and `LibExternOpContextSender` | - -All column/row index mappings between operand handlers and word parsers are internally consistent. The handler types (disallowed, single-full, double-per-byte) match the semantic requirements of each context word. No correctness issues found. diff --git a/audit/2026-03-13-01/triage.md b/audit/2026-03-13-01/triage.md deleted file mode 100644 index 229d967dfd..0000000000 --- a/audit/2026-03-13-01/triage.md +++ /dev/null @@ -1,148 +0,0 @@ -# Triage — audit/2026-03-13-01 - -## Legend -- **PENDING** — not yet triaged -- **FIXED** — code changed -- **DOCUMENTED** — documentation/comments added -- **DISMISSED** — no action needed (with reason) -- **UPSTREAM** — fix belongs in a dependency/submodule - -Where a finding was flagged in multiple passes, the primary finding is listed and duplicates are cross-referenced. Triaging the primary finding applies to all its duplicates. - ---- - -## HIGH - -| # | ID | Pass | File | Title | Status | Notes | -|---|-----|------|------|-------|--------|-------| -| 1 | A03-2 | P1 | OrderBookV6FlashBorrower.sol | Missing ERC20 approval for flash loan repayment token | FIXED | Added approve-call-revoke for ordersOutputToken; end-to-end test in missingApproval.t.sol | -| 2 | A03-P2-3 | P2 | OrderBookV6FlashBorrower.sol | Mock skips token transfers, hiding A03-2 | FIXED | RealisticFlashLendingMockOrderBook does real ERC3156 transfers | -| 3 | A05-1 | P1 | GenericPoolOrderBookV6ArbOrderTaker.sol | Unlimited approval to arbitrary spender with caller-controlled data | DOCUMENTED | By design: approve-call-revoke; contract stateless between ops; added inline comment | -| 4 | A05-P2-1 | P2 | GenericPoolOrderBookV6ArbOrderTaker.sol | `onTakeOrders2` is completely untested | FIXED | End-to-end test in onTakeOrders2.t.sol with realistic mock + exchange | -| 5 | A15-1 | P1 | Deploy.sol | Route processor bytecode hash check runs unconditionally | DISMISSED | Intentional: verifies route processor before deploying arb contracts | -| 6 | A15-P5-1 | P5 | Deploy.sol | Confirms A15-1 | DISMISSED | Dup of A15-1 | - -## MEDIUM - -| # | ID | Pass | File | Title | Status | Notes | -|---|-----|------|------|-------|--------|-------| -| 7 | A03-1 | P1 | OrderBookV6FlashBorrower.sol | Missing msg.sender (lender) validation in onFlashLoan | FIXED | Added iOrderBook immutable + BadLender check; test in lenderValidation.t.sol | -| 8 | A03-3 | P1 | OrderBookV6FlashBorrower.sol | Flash loan amount computed with wrong token decimals | FIXED | Changed inputDecimals → outputDecimals; test in mixedDecimals.t.sol | -| 9 | A05-2 | P1 | GenericPoolOrderBookV6ArbOrderTaker.sol | Arbitrary external call sends entire ETH balance | DOCUMENTED | By design: same as A05-1; contract stateless between ops; balance is normally 0 | -| 10 | A06-1 | P1 | GenericPoolOrderBookV6FlashBorrower.sol | Unlimited approval to arbitrary spender with no validation | DOCUMENTED | Dup of A05-1; approve-call-revoke; added inline comment | -| 11 | A03-P2-1 | P2 | OrderBookV6FlashBorrower.sol | onFlashLoan has zero direct test coverage for error paths | FIXED | BadInitiator tested in badInitiator.t.sol | -| 12 | A03-P2-2 | P2 | OrderBookV6FlashBorrower.sol | FlashLoanFailed error path is never tested | FIXED | Test in flashLoanFailed.t.sol | -| 13 | A03-P2-6 | P2 | OrderBookV6FlashBorrower.sol | WrongTask revert path has no test for flash borrower arb contracts | FIXED | Added wrongTask.t.sol | -| 14 | A05-P2-2 | P2 | GenericPoolOrderBookV6ArbOrderTaker.sol | No test for fallback() behavior | FIXED | Added fallback.t.sol for both arb types | -| 15 | A07-P2-1 | P2 | RouteProcessorOrderBookV6ArbOrderTaker.sol | onTakeOrders2 override has zero test coverage | FIXED | Test in onTakeOrders2.t.sol with MockRouteProcessor | -| 16 | A15-P5-2 | P5 | Deploy.sol | vm.envAddress reverts unconditionally for route-processor suite | DISMISSED | Incorrect: envAddress is in ARB branch (line 135), not route-processor branch | - -## LOW - -| # | ID | Pass | File | Title | Status | Notes | -|---|-----|------|------|-------|--------|-------| -| 17 | A02-1 | P1 | OrderBookV6ArbOrderTaker.sol | onTakeOrders2 callback has no access control | DISMISSED | By design: contract holds no value between ops; NatSpec documents this | -| 18 | A04-2 | P1 | OrderBookV6FlashLender.sol | flashLoan lacks reentrancy guard, nested flash loans | DISMISSED | By design: flash loan callbacks need to call takeOrders; tested in reentrant.t.sol | -| 19 | A05-3 | P1 | GenericPoolOrderBookV6ArbOrderTaker.sol | Non-payable fallback with misleading comment | FIXED | Comment fixed; fallback tested in fallback.t.sol | -| 20 | A06-2 | P1 | GenericPoolOrderBookV6FlashBorrower.sol | fallback accepts arbitrary calls without payable | FIXED | Dup of A05-3; comment fixed, fallback tested | -| 21 | A07-1 | P1 | RouteProcessorOrderBookV6ArbOrderTaker.sol | onTakeOrders2 is public with no access control | DISMISSED | By design: same as A02-1 | -| 22 | A08-1 | P1 | OrderBookV6.sol | flashLoan lacks nonReentrant guard | DISMISSED | By design: same as A04-2 | -| 23 | A15-2 | P1 | Deploy.sol | No explicit revert on failed create in deployRouter() | FIXED | Added require(routeProcessor4 != address(0)) | -| 24 | A01-P2-1 | P2 | OrderBookV6ArbCommon.sol | No test for WrongTask revert through FlashBorrower path | FIXED | Dup of A03-P2-6 | -| 25 | A01-P2-2 | P2 | OrderBookV6ArbCommon.sol | No direct unit test for constructor iTaskHash assignment | FIXED | Test in iTaskHash.t.sol for both non-empty and empty bytecode | -| 26 | A01-P2-3 | P2 | OrderBookV6ArbCommon.sol | No test for onlyValidTask bypass when iTaskHash == 0 | DISMISSED | Implicitly tested: sender tests deploy with empty expression (iTaskHash==0) and pass | -| 27 | A02-P2-1 | P2 | OrderBookV6ArbOrderTaker.sol | No test for arb5 reverting on zero orders | FIXED | Added noOrders.t.sol | -| 28 | A02-P2-2 | P2 | OrderBookV6ArbOrderTaker.sol | No test for reentrancy guard on arb5 | FIXED | Test in reentrancy.t.sol with ReentrantMockOrderBook | -| 29 | A02-P2-3 | P2 | OrderBookV6ArbOrderTaker.sol | onTakeOrders2 has no direct test | FIXED | Test in onTakeOrders2Direct.t.sol | -| 30 | A03-P2-4 | P2 | OrderBookV6FlashBorrower.sol | SwapFailed error declared but never used/tested | FIXED | Removed dead error; Dup: A03-P4-2 | -| 31 | A03-P2-5 | P2 | OrderBookV6FlashBorrower.sol | NoOrders revert path has no test through flash borrower | FIXED | Added FlashBorrower.noOrders.t.sol | -| 32 | A03-P2-7 | P2 | OrderBookV6FlashBorrower.sol | Flash loan amount wrong decimals not caught by tests | FIXED | Dup of A03-3 | -| 33 | A05-P2-3 | P2 | GenericPoolOrderBookV6ArbOrderTaker.sol | Constructor event emission tested only indirectly | DISMISSED | ArbTest constructor uses vm.expectEmit + emit Construct — this IS a test | -| 34 | A07-P2-2 | P2 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No test for onTakeOrders2 called directly by attacker | FIXED | Test in onTakeOrders2Direct.t.sol | -| 35 | A07-P2-3 | P2 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No test for constructor with invalid implementationData | FIXED | Test in invalidConstructor.t.sol | -| 36 | A12-P2-1 | P2 | LibOrderBookArb.sol | NonZeroBeforeArbStack and BadLender errors are dead code | FIXED | Removed both dead errors | -| 37 | A12-P2-2 | P2 | LibOrderBookArb.sol | No test verifies token transfers in finalizeArb | FIXED | Test in finalizeArbTokenTransfers.t.sol | -| 38 | A12-P2-3 | P2 | LibOrderBookArb.sol | No test verifies native gas sent to msg.sender | FIXED | Test in finalizeArbNativeGas.t.sol; made fallback payable + added receive() | -| 39 | A12-P2-4 | P2 | LibOrderBookArb.sol | No test exercises finalizeArb with realistic non-zero balances | FIXED | Covered by finalizeArbTokenTransfers.t.sol (20e18 profit) and finalizeArbNativeGas.t.sol (1 ETH) | -| 40 | A15-P2-1 | P2 | Deploy.sol | No unit test for deployRouter() return value on create failure | DISMISSED | deployRouter() removed; RP4 now deployed via LibRainDeploy.deployAndBroadcast | -| 41 | A15-P2-2 | P2 | Deploy.sol | ROUTE_PROCESSOR_4_BYTECODE_HASH constant never verified | DISMISSED | Inline constant removed; codehash now in generated pointers, verified by LibRouteProcessor4CreationCode test | -| 42 | A15-P2-3 | P2 | Deploy.sol | No test for BadRouteProcessor error path | DISMISSED | BadRouteProcessor error removed; deployAndBroadcast handles failures internally | -| 43 | A15-P2-4 | P2 | Deploy.sol | No test coverage for individual suite isolation | DISMISSED | Deploy.sol is a forge script; suite branches are a simple if/else chain, integration-tested by running them | -| 44 | A06-P2-GAP1 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No test for BadInitiator error path | FIXED | Added badInitiator.t.sol | -| 45 | A06-P2-GAP2 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No test for FlashLoanFailed error path | FIXED | Dup of A03-P2-2; same base class tested | -| 46 | A06-P2-GAP3 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No test for WrongTask on GenericPoolOrderBookV6FlashBorrower | FIXED | Dup of A03-P2-6 | -| 47 | A06-P2-GAP4 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No test for NoOrders revert in arb4 | FIXED | Dup of A03-P2-5 | -| 48 | A06-P2-GAP5 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No test for _exchange failure propagation | FIXED | Added exchangeRevert, approvalRevoked, and ethForwarded tests | -| 49 | A09-P2-GAP1 | P2 | OrderBookV6SubParser.sol | No tests for deposit word parsing (11 words, 0 tests) | DISMISSED | Trivial constant lookups into LibSubParse.subParserContext; compile-time index bounds checking via array assignments; testing requires parallel context fixture for minimal value | -| 50 | A01-P3-1 | P3 | OrderBookV6ArbCommon.sol | Struct @param name mismatch: tasks vs task | FIXED | Dup: A01-P5-1 | -| 51 | A01-P3-2 | P3 | OrderBookV6ArbCommon.sol | Missing documentation on contract, event, state variable, constructor, modifier | FIXED | | -| 52 | A01-P3-3 | P3 | OrderBookV6ArbCommon.sol | BEFORE_ARB_SOURCE_INDEX doc inaccurately scoped to flash loans | FIXED | | -| 53 | A02-P3-1 | P3 | OrderBookV6ArbOrderTaker.sol | Contract-level NatSpec missing | FIXED | | -| 54 | A02-P3-2 | P3 | OrderBookV6ArbOrderTaker.sol | Typo: "evaluabled" in BEFORE_ARB_SOURCE_INDEX doc | FIXED | | -| 55 | A02-P3-3 | P3 | OrderBookV6ArbOrderTaker.sol | onTakeOrders2 empty body contradicts interface MUST requirement | FIXED | Added @dev explaining default no-op | -| 56 | A03-P3-1 | P3 | OrderBookV6FlashBorrower.sol | Stale @title tag: OrderBookV5FlashBorrower | FIXED | Dup: A03-P4-3 | -| 57 | A03-P3-2 | P3 | OrderBookV6FlashBorrower.sol | Stale interface/contract references in arb4 param docs | FIXED | Dup: A03-P5-2 | -| 58 | A03-P3-3 | P3 | OrderBookV6FlashBorrower.sol | Missing @param for orderBook and task in arb4 | FIXED | | -| 59 | A04-P3-1 | P3 | OrderBookV6FlashLender.sol | Misleading NatSpec on maxFlashLoan | FIXED | Dup: A04-P5-1 | -| 60 | A05-P3-1 | P3 | GenericPoolOrderBookV6ArbOrderTaker.sol | Missing contract-level NatSpec | FIXED | | -| 61 | A06-P3-1 | P3 | GenericPoolOrderBookV6FlashBorrower.sol | Misleading fallback comment | FIXED | Dup of A05-3 | -| 62 | A07-P3-1 | P3 | RouteProcessorOrderBookV6ArbOrderTaker.sol | Missing contract-level NatSpec | FIXED | | -| 63 | A07-P3-2 | P3 | RouteProcessorOrderBookV6ArbOrderTaker.sol | Undocumented lossy conversion and silent discard of precision flag | FIXED | | -| 64 | A08-P3-1 | P3 | OrderBookV6.sol | Stale comment in recordVaultIO contradicts code execution order | FIXED | | -| 65 | A11-P3-1 | P3 | LibOrderBook.sol | Missing NatSpec on doPost | FIXED | | -| 66 | A12-P3-1 | P3 | LibOrderBookArb.sol | Missing NatSpec on finalizeArb | FIXED | | -| 67 | A13-P3-1 | P3 | LibOrderBookSubParser.sol | No NatSpec on any of the 28 SubParser functions | FIXED | | -| 68 | A15-P3-1 | P3 | Deploy.sol | @notice references deprecated "mumbai" testnet | FIXED | | -| 69 | A15-P3-2 | P3 | Deploy.sol | deployRouter() has no documentation | FIXED | | -| 70 | A15-P3-3 | P3 | Deploy.sol | run() has no documentation | FIXED | | -| 71 | A15-P3-4 | P3 | Deploy.sol | Five DEPLOYMENT_SUITE_* constants have no documentation | FIXED | | -| 72 | P3-A09-01 | P3 | OrderBookV6SubParser.sol | buildSubParserWordParsers() has no NatSpec | FIXED | | -| 73 | A01-P4-1 | P4 | OrderBookV6ArbCommon.sol | Multiple unused imports | FIXED | Removed 4 unused imports | -| 74 | A02-P4-1 | P4 | OrderBookV6ArbOrderTaker.sol | 10 unused imports | FIXED | Removed 10 unused imports | -| 75 | A02-P4-2 | P4 | OrderBookV6ArbOrderTaker.sol | Duplicate constant BEFORE_ARB_SOURCE_INDEX | FIXED | Removed duplicate, kept in ArbCommon | -| 76 | A02-P4-3 | P4 | OrderBookV6ArbOrderTaker.sol | Dead error NonZeroBeforeArbInputs | FIXED | Related: A12-P2-1 | -| 77 | A03-P4-1 | P4 | OrderBookV6FlashBorrower.sol | 7 unused imports | FIXED | Removed 8 unused imports + unused using statement | -| 78 | A03-P4-2 | P4 | OrderBookV6FlashBorrower.sol | Dead error SwapFailed | FIXED | Removed dead error | -| 79 | A03-P4-3 | P4 | OrderBookV6FlashBorrower.sol | Stale NatSpec @title OrderBookV5FlashBorrower | FIXED | Dup of A03-P3-1 | -| 80 | A06-P4-1 | P4 | GenericPoolOrderBookV6FlashBorrower.sol | Unused import IERC3156FlashLender | FIXED | Removed | -| 81 | A06-P4-2 | P4 | GenericPoolOrderBookV6FlashBorrower.sol | Unused import IERC3156FlashBorrower | FIXED | Removed | -| 82 | A07-P4-1 | P4 | RouteProcessorOrderBookV6ArbOrderTaker.sol | Unused import Address | FIXED | Removed import + unused using statement | -| 83 | A07-P4-2 | P4 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No explicit remapping for sushixswap-v2 | DISMISSED | Resolved via libs=['lib'] fallback; explicit remapping unnecessary | -| 84 | A15-P4-1 | P4 | Deploy.sol | Unused import OrderBookV6 | FIXED | Removed; EvaluableV4/TaskV2/SignedContextV1 now from canonical sources | -| 85 | A15-P4-2 | P4 | Deploy.sol | Imports through concrete contract rather than canonical source | FIXED | Now imports from interface packages directly | -| 86 | A15-P4-3 | P4 | Deploy.sol | Inconsistent address() cast on raindex variable | DISMISSED | Cast required: TOFU_DECIMALS_DEPLOYMENT is a contract type, others are address | -| 87 | A15-P4-4 | P4 | Deploy.sol | Missing "memory-safe" annotation on second assembly block | FIXED | Added to both assembly blocks | -| 88 | A15-P4-5 | P4 | Deploy.sol | Repeated TaskV2/EvaluableV4 zero-value boilerplate | DISMISSED | Deploy script only; extracting a helper adds complexity for no runtime benefit | -| 89 | A01-P5-1 | P5 | OrderBookV6ArbCommon.sol | NatSpec @param tasks does not match field name task | FIXED | Dup of A01-P3-1 | -| 90 | A03-P5-1 | P5 | OrderBookV6FlashBorrower.sol | BadInitiator NatSpec inaccurately describes the check | FIXED | NatSpec now says "this contract" not "the order book" | -| 91 | A03-P5-2 | P5 | OrderBookV6FlashBorrower.sol | NatSpec for arb4 describes stale "access gate" evaluation | FIXED | Dup of A03-P3-2 | -| 92 | A04-P5-1 | P5 | OrderBookV6FlashLender.sol | maxFlashLoan NatSpec falsely claims active-debt disabling | FIXED | Dup of A04-P3-1 | -| 93 | A05-P5-01 | P5 | GenericPoolOrderBookV6ArbOrderTaker.sol | Misleading "Allow receiving gas" comment on non-payable fallback | FIXED | Dup of A05-3; comment updated | -| 94 | A06-P5-01 | P5 | GenericPoolOrderBookV6FlashBorrower.sol | Misleading "Allow receiving gas" comment on non-payable fallback | FIXED | Dup of A05-3; comment updated | -| 95 | A07-P5-01 | P5 | RouteProcessorOrderBookV6ArbOrderTaker.sol | Misleading "Allow receiving gas" comment on non-payable fallback | FIXED | Dup of A05-3; comment updated | -| 96 | A15-P5-3 | P5 | Deploy.sol | No require/revert on create returning address(0) (confirms A15-2) | FIXED | Dup of A15-2 | -| 97 | A15-P5-4 | P5 | Deploy.sol | No mechanism to reject unknown suite values | DISMISSED | Already handled: line 175 has revert("Unknown deployment suite") | - -## INFO - -| # | ID | Pass | File | Title | Status | Notes | -|---|-----|------|------|-------|--------|-------| -| 98 | A04-P3-2 | P3 | OrderBookV6FlashLender.sol | flashFee drops parameter names | DISMISSED | Idiomatic Solidity for unused params | -| 99 | A04-P3-3 | P3 | OrderBookV6FlashLender.sol | No @param/@return on maxFlashLoan | DISMISSED | Has @inheritdoc | -| 100 | A05-P3-3 | P3 | GenericPoolOrderBookV6ArbOrderTaker.sol | No impl-specific param docs on onTakeOrders2 | DISMISSED | Has @inheritdoc + contract notice | -| 101 | A06-P3-3 | P3 | GenericPoolOrderBookV6FlashBorrower.sol | Interface references stale V5 name | UPSTREAM | External dependency (rain.raindex.interface) | -| 102 | A07-P3-4 | P3 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No NatSpec on iRouteProcessor | FIXED | | -| 103 | A08-P3-3 | P3 | OrderBookV6.sol | Contract-level NatSpec minimal (internal functions) | FIXED | Added @dev to 9 internal functions | -| 104 | A11-P3-4 | P3 | LibOrderBook.sol | No docs on deposit/withdraw/signed context constants | FIXED | Added group @dev comments | -| 105 | A13-P3-3 | P3 | LibOrderBookSubParser.sol | Missing @notice on LibOrderBookSubParser | FIXED | | -| 106 | A15-P3-7 | P3 | Deploy.sol | sDepCodeHashes state var no docs | FIXED | | -| 107 | A15-P3-8 | P3 | README.md | README missing deploy info | FIXED | Added Deployment section | -| 108 | CR-1 | CR | LibOrderBookArb.sol | sendValue called without zero-balance guard | FIXED | Added if (gasBalance > 0) guard | -| 109 | CR-2 | CR | LibOrderBookSubParser.sol | NatSpec word names don't match canonical parser keywords | DISMISSED | WORD_* constants ARE the canonical keywords; naming convention is consistent | -| 110 | CR-3 | CR | README.md | Deploy example missing ETH_RPC_URL / --rpc-url | FIXED | Added --rpc-url to example | -| 111 | CR-4 | CR | OrderBookV6SubParser.sol / LibOrderBookSubParser.sol | Repeated magic expression CONTEXT_COLUMNS + 2 + 1 + 1 should be named constant | FIXED | Extracted CONTEXT_COLUMNS_EXTENDED constant in LibOrderBook.sol | -| 112 | CR-5 | CR | OrderBookV6FlashBorrower.sol | Lender validation runs after forceApprove calls | FIXED | Added badLenderApproval test: malicious orderbook triggers BadLender, approvals atomically reverted | -| 113 | CR-6 | CR | OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol | Missing post-execution balance assertions in testArb5RealTokenTransfers | FIXED | Added balance assertions to all three real-token-transfer tests | -| 114 | CR-7 | CR | OrderBookV6FlashBorrower.lenderValidation.t.sol | Unused RealisticFlashLendingMockOrderBook instance | FIXED | Removed unused import and instance | -| 115 | CR-8 | CR | OrderBookV6FlashBorrower.missingApproval.t.sol | Filename doesn't match test purpose | FIXED | Renamed to realTokenTransfers.t.sol | -| 116 | CR-9 | CR | RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol | Missing state verification assertions | FIXED | Added balance assertions for all participants | diff --git a/audit/2026-03-14-01/pass0/process.md b/audit/2026-03-14-01/pass0/process.md deleted file mode 100644 index a19559b00d..0000000000 --- a/audit/2026-03-14-01/pass0/process.md +++ /dev/null @@ -1,36 +0,0 @@ -# Pass 0: Process Review - -**Date:** 2026-03-14 -**Files reviewed:** CLAUDE.md, AGENTS.md, ~/.claude/CLAUDE.md, ~/.claude/skills/audit/GENERAL_RULES.md - -No changes to process documents since prior audit (2026-03-13-01). All prior findings still apply: - -## A01-1: CLAUDE.md uses `@AGENTS.md` syntax — LOW - -**File:** CLAUDE.md:1 - -The `@` prefix (`@AGENTS.md`) is IDE-specific mention syntax. Under context compression or in environments that don't expand `@` references, the instruction could be interpreted as literal text rather than a file reference. - -## A01-2: No nix shell guidance in AGENTS.md — MEDIUM - -**File:** AGENTS.md - -AGENTS.md lists build commands but doesn't mention the nix development environment. Commands must not be prefixed with `nix develop -c` when already inside a nix shell (`$IN_NIX_SHELL` is set). - -## A01-3: Preflight check omits `forge fmt` — LOW - -**File:** AGENTS.md:29 - -The "Quick preflight" is `npm run lint-format-check:all && rainix-rs-static`, which covers JS/TS and Rust but not Solidity formatting (`forge fmt`). - -## A01-4: Global CLAUDE.md applies audit rules universally — LOW - -**File:** ~/.claude/CLAUDE.md:4 - -"Follow the coding and testing standards in `~/.claude/skills/audit/GENERAL_RULES.md` at all times" applies audit-specific rules to non-audit contexts where they don't apply. - -## A01-5: `ast-grep`/`sg` availability not guaranteed — INFO - -**File:** AGENTS.md:35 - -Agent-Specific Instructions prefer `sg` (ast-grep) but it's a nix-provided tool with no fallback instruction. diff --git a/audit/2026-03-14-01/pass1/Deploy.md b/audit/2026-03-14-01/pass1/Deploy.md deleted file mode 100644 index 20f3f571e0..0000000000 --- a/audit/2026-03-14-01/pass1/Deploy.md +++ /dev/null @@ -1,52 +0,0 @@ -# A15: Deploy.sol - Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `script/Deploy.sol` (143 lines) - -### Contract -- `Deploy is Script` (line 39) - -### Functions -- `run()` - line 46 - -### State variables -- `sDepCodeHashes` - `mapping(string => mapping(address => bytes32))` (line 42) - -### Constants (file-level) -- `DEPLOYMENT_SUITE_RAINDEX` = keccak256("raindex") (line 27) -- `DEPLOYMENT_SUITE_SUBPARSER` = keccak256("subparser") (line 29) -- `DEPLOYMENT_SUITE_ROUTE_PROCESSOR` = keccak256("route-processor") (line 31) -- `DEPLOYMENT_SUITE_ARB` = keccak256("arb") (line 33) - -### Imports -- `Script`, `console2` from forge-std -- `EvaluableV4`, `SignedContextV1` from IInterpreterCallerV4 -- `TaskV2` from IRaindexV6 -- `OrderBookV6SubParser` from concrete/parser -- `GenericPoolOrderBookV6ArbOrderTaker` from concrete/arb -- `RouteProcessorOrderBookV6ArbOrderTaker` from concrete/arb -- `GenericPoolOrderBookV6FlashBorrower` from concrete/arb -- `OrderBookV6ArbConfig` from abstract/OrderBookV6ArbCommon -- `IMetaBoardV1_2` from rain.metadata -- `LibDescribedByMeta` from rain.metadata -- `LibMetaBoardDeploy` from rain.metadata -- `LibDecimalFloatDeploy` from rain.math.float -- `LibTOFUTokenDecimals` from rain.tofu.erc20-decimals -- `IInterpreterStoreV3` from rain.interpreter.interface -- `IInterpreterV4` from rain.interpreter.interface -- `LibRainDeploy` from rain.deploy -- `LibOrderBookDeploy` from src/lib/deploy -- `CREATION_CODE` as ORDERBOOK_CREATION_CODE from OrderBookV6.pointers.sol -- `CREATION_CODE` as SUB_PARSER_CREATION_CODE from OrderBookV6SubParser.pointers.sol -- `ROUTE_PROCESSOR_4_CREATION_CODE` from LibRouteProcessor4CreationCode - -## Findings - -### A15-1: String revert used for unknown deployment suite (LOW) - -**Location:** `script/Deploy.sol`, line 140 - -**Description:** The `run()` function uses `revert("Unknown deployment suite")` with a string message. The project convention (per CLAUDE.md in the interface repos and general codebase style) is to use custom errors exclusively and avoid string reverts. While this is a Foundry deployment script (not production runtime code), it is still Solidity source in the repository and should follow the project's coding standards for consistency and gas efficiency. - -**Impact:** Minimal -- this code only runs in deployment scripts, not on-chain in production. However, it deviates from the project's "all reverts use custom errors" convention. diff --git a/audit/2026-03-14-01/pass1/GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass1/GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 29c812c07c..0000000000 --- a/audit/2026-03-14-01/pass1/GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,50 +0,0 @@ -# A05: GenericPoolOrderBookV6ArbOrderTaker.sol - Pass 1 (Security) - -**File:** `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` - -## Evidence of Thorough Reading - -**Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (concrete, line 14) -- Inherits: `OrderBookV6ArbOrderTaker` - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 18) -- `onTakeOrders2(address inputToken, address outputToken, Float inputAmountSent, Float totalOutputAmount, bytes calldata takeOrdersData)` (line 21): public virtual override -- `receive()` (line 45): external payable -- `fallback()` (line 46): external payable - -**Imports (lines 5-9):** -- `IERC20` from OpenZeppelin -- `SafeERC20` from OpenZeppelin -- `Address` from OpenZeppelin -- `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float` from `../../abstract/OrderBookV6ArbOrderTaker.sol` - -**Using:** -- `SafeERC20 for IERC20` (line 15) -- `Address for address` (line 16) - -## Security Analysis - -### onTakeOrders2 (lines 21-41) -- **Decoding:** line 29-30 decodes `takeOrdersData` as `(address spender, address pool, bytes encodedFunctionCall)`. ABI decode reverts on malformed data. -- **Approval pattern:** lines 35-40: `forceApprove(spender, max)` -> `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -> `forceApprove(spender, 0)`. Correct approve-call-revoke. -- **Arbitrary external call:** line 39 makes an arbitrary call to a caller-controlled `pool` with caller-controlled calldata. This is the core design -- the caller specifies how to interact with external liquidity. -- **ETH forwarding:** line 39 sends `address(this).balance` as `msg.value` to the pool call. Any ETH sent with the `arb5` call or received via `receive()`/`fallback()` is forwarded. -- **No msg.sender validation:** `onTakeOrders2` is `public` with no access control. The IRaindexV6OrderTaker interface says implementations MUST validate `msg.sender`. However, the contract holds no value between operations (documented on line 32-34 in parent and line 43-44 here). During an arb, the `arb5` entry point is `nonReentrant`, so the only way `onTakeOrders2` is called during an active arb is by the orderbook via `takeOrders4`. A direct external call between arbs would find the contract empty. -- **Reentrancy via pool callback:** The `pool.functionCallWithValue` call could re-enter `onTakeOrders2`. Since `arb5` is `nonReentrant`, re-entry to `arb5` is blocked. Re-entry to `onTakeOrders2` during the pool call would re-decode `takeOrdersData` and attempt another approve-call-revoke cycle. The caller controls the pool, so this would be self-inflicted. The contract's token balance at that point is whatever the orderbook sent via the callback, which would be at risk if the pool re-enters. However, since the caller controls both the pool and the calldata, they can only exploit themselves. - -### receive() and fallback() (lines 45-46) -- Both are `external payable` with no logic. Accept ETH and arbitrary calls silently. The comment on line 43-44 explains ETH is swept by `finalizeArb`. - -### constructor (line 18) -- Passes config to parent. No additional initialization. - -## Findings - -No security findings. The contract's design is intentionally permissive because: -- The contract holds no value between arb operations -- `arb5` (the entry point) has `nonReentrant` protection -- The caller who calls `arb5` controls all parameters including `pool`, `spender`, and `encodedFunctionCall` -- `finalizeArb` sends all remaining balances to `msg.sender` (the arb caller) -- Approve-call-revoke pattern with `forceApprove` correctly bounds the approval window -- Custom errors only (inherited from parent contracts, no string reverts in this file) diff --git a/audit/2026-03-14-01/pass1/GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass1/GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index 3bd93c331d..0000000000 --- a/audit/2026-03-14-01/pass1/GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,39 +0,0 @@ -# A06 — GenericPoolOrderBookV6FlashBorrower.sol — Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` (53 lines) - -**Contract:** `GenericPoolOrderBookV6FlashBorrower` (inherits `OrderBookV6FlashBorrower`) - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` — line 30 -- `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData)` — line 33 -- `receive()` — line 51 -- `fallback()` — line 52 - -**Types/Errors/Constants:** None defined in this file. - -**Imports:** -- `Address` from OpenZeppelin (line 5) -- `OrderBookV6FlashBorrower`, `SafeERC20`, `IERC20`, `TakeOrdersConfigV5`, `OrderBookV6ArbConfig` (lines 7-13) - -**Using-for directives:** -- `SafeERC20 for IERC20` (line 27) -- `Address for address` (line 28) - -## Findings - -No security findings identified. - -### Analysis Notes - -The approve-call-revoke pattern on lines 42-46 is correctly implemented: `forceApprove(max)`, call, `forceApprove(0)`. The caller controls `spender` and `pool` via `exchangeData`, but this is safe because: - -1. The contract inherits `nonReentrant` from `OrderBookV6FlashBorrower.arb4`, preventing reentrancy. -2. The contract holds no persistent token balances or ETH between arb operations — `finalizeArb` sweeps all remaining assets to the sender after each arb. -3. The `receive()` and `fallback()` functions are intentionally open to allow ETH to be received during pool interactions. - -The `borrowedToken` derivation on line 37 accesses `takeOrders.orders[0]`, which is safe because the parent `arb4` function already reverts on empty orders (line 136 of `OrderBookV6FlashBorrower.sol`). - -The `functionCallWithValue` on line 45 forwards `address(this).balance` which is appropriate for pools that require ETH alongside the call. diff --git a/audit/2026-03-14-01/pass1/LibOrder.md b/audit/2026-03-14-01/pass1/LibOrder.md deleted file mode 100644 index 0dcb689452..0000000000 --- a/audit/2026-03-14-01/pass1/LibOrder.md +++ /dev/null @@ -1,25 +0,0 @@ -# A10 — LibOrder.sol — Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/lib/LibOrder.sol` (19 lines) - -**Library:** `LibOrder` - -**Functions:** -- `hash(OrderV4 memory order)` — line 16 (internal pure) - -**Types/Errors/Constants:** None defined in this file. - -**Imports:** -- `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` — line 5 - -## Findings - -No security findings identified. - -### Analysis Notes - -The `hash` function correctly uses `abi.encode` rather than `abi.encodePacked`, as noted in the NatSpec comment. This prevents collision attacks where different structs with variable-length fields could produce identical packed encodings. Since `OrderV4` contains dynamic arrays (`validInputs`, `validOutputs`) and a nested struct (`evaluable` with `bytes bytecode`), using `abi.encode` is the correct choice. - -The function is `internal pure` and stateless, with no external call risks or state concerns. diff --git a/audit/2026-03-14-01/pass1/LibOrderBook.md b/audit/2026-03-14-01/pass1/LibOrderBook.md deleted file mode 100644 index fb477600c2..0000000000 --- a/audit/2026-03-14-01/pass1/LibOrderBook.md +++ /dev/null @@ -1,67 +0,0 @@ -# A11: LibOrderBook.sol - Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/lib/LibOrderBook.sol` (139 lines) - -### Library -- `LibOrderBook` (line 108) - -### Functions -- `doPost(bytes32[][] memory context, TaskV2[] memory post)` - line 111 - -### Constants (file-level) -- `CALLING_CONTEXT_COLUMNS` = 4 (line 28) -- `CONTEXT_COLUMNS` = CALLING_CONTEXT_COLUMNS + 1 (line 30) -- `CONTEXT_COLUMNS_EXTENDED` = CONTEXT_COLUMNS + 2 + 1 + 1 (line 34) -- `CONTEXT_CALLING_CONTEXT_COLUMN` = 1 (line 40) -- `CONTEXT_CALLING_CONTEXT_ROWS` = 3 (line 41) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` = 0 (line 43) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` = 1 (line 44) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` = 2 (line 45) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` = 0 (line 49) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` = 1 (line 50) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` = 2 (line 51) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` = 3 (line 52) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` = 0 (line 54) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` = 1 (line 55) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` = 2 (line 56) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` = 3 (line 57) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` = 4 (line 60) -- `CONTEXT_CALCULATIONS_COLUMN` = 2 (line 64) -- `CONTEXT_CALCULATIONS_ROWS` = 2 (line 65) -- `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` = 0 (line 67) -- `CONTEXT_CALCULATIONS_ROW_IO_RATIO` = 1 (line 68) -- `CONTEXT_VAULT_INPUTS_COLUMN` = 3 (line 74) -- `CONTEXT_VAULT_OUTPUTS_COLUMN` = 4 (line 77) -- `CONTEXT_VAULT_IO_TOKEN` = 0 (line 80) -- `CONTEXT_VAULT_IO_TOKEN_DECIMALS` = 1 (line 82) -- `CONTEXT_VAULT_IO_VAULT_ID` = 2 (line 84) -- `CONTEXT_VAULT_IO_BALANCE_BEFORE` = 3 (line 87) -- `CONTEXT_VAULT_IO_BALANCE_DIFF` = 4 (line 92) -- `CONTEXT_VAULT_IO_ROWS` = 5 (line 94) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` = 5 (line 98) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` = 1 (line 99) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW` = 0 (line 100) -- `CONTEXT_SIGNED_CONTEXT_START_COLUMN` = 6 (line 104) -- `CONTEXT_SIGNED_CONTEXT_START_ROWS` = 1 (line 105) -- `CONTEXT_SIGNED_CONTEXT_START_ROW` = 0 (line 106) - -### Imports -- `CONTEXT_BASE_ROWS`, `CONTEXT_BASE_ROW_SENDER`, `CONTEXT_BASE_ROW_CALLING_CONTRACT`, `CONTEXT_BASE_COLUMN` from LibContext -- `TaskV2` from IRaindexV6 -- `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4` from IInterpreterV4 -- `LibNamespace`, `FullyQualifiedNamespace` from LibNamespace -- `LibContext` from LibContext - -## Findings - -No security findings. The code is well-structured: - -- **Namespace handling**: `doPost` derives `namespace` from `msg.sender` and passes it unqualified to `store.set`, which is correct per `IInterpreterStoreV3` specification -- the store MUST fully qualify internally. -- **Eval uses qualified namespace**: `eval4` receives `qualifiedNamespace` for read operations, consistent with interpreter expectations. -- **Empty bytecode check**: Tasks with empty bytecode are correctly skipped (line 119). -- **Write optimization**: Writes are only committed when non-empty (line 133). -- **No reentrancy risk**: External calls go to interpreter (`eval4`) and store (`set`), which are trusted components provided by the task. The caller context is not modified after external calls. -- **No assembly**: No assembly blocks in this library. -- **No string reverts**: No revert statements in this file. diff --git a/audit/2026-03-14-01/pass1/LibOrderBookArb.md b/audit/2026-03-14-01/pass1/LibOrderBookArb.md deleted file mode 100644 index a0405ae8cc..0000000000 --- a/audit/2026-03-14-01/pass1/LibOrderBookArb.md +++ /dev/null @@ -1,34 +0,0 @@ -# A12: LibOrderBookArb.sol - Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/lib/LibOrderBookArb.sol` (77 lines) - -### Library -- `LibOrderBookArb` (line 14) - -### Functions -- `finalizeArb(TaskV2 memory task, address ordersInputToken, uint8 inputDecimals, address ordersOutputToken, uint8 outputDecimals)` - line 20 - -### Imports -- `TaskV2` from IRaindexV6 -- `IERC20` from OpenZeppelin -- `LibOrderBook` from ./LibOrderBook.sol -- `Address` from OpenZeppelin -- `SafeERC20` from OpenZeppelin -- `IERC20Metadata` from OpenZeppelin (unused import -- but not a security finding) -- `LibDecimalFloat`, `Float` from rain.math.float - -### Using directives -- `SafeERC20 for IERC20` (line 15) - -## Findings - -No security findings. Analysis of each concern: - -- **ERC20 transfers**: Uses `SafeERC20.safeTransfer` (lines 34, 45), correctly handling non-standard ERC20 tokens. Transfers only occur when balance > 0. -- **Native gas transfer**: Uses OpenZeppelin `Address.sendValue` (line 62), which handles the low-level call correctly with revert propagation. -- **Float conversion after transfer**: The `fromFixedDecimalLossyPacked` calls (lines 37, 49) use the `inputBalance` / `outputBalance` values captured BEFORE the `safeTransfer` calls. This means the Float values in context represent what was sent, not remaining balance. This is correct per the docstring ("amounts sent as Floats"). -- **int256 cast of gasBalance** (line 67): The comment correctly explains that `gasBalance` (native ETH) cannot exceed `int256.max` because total ETH supply is far below that threshold. The `packLossless` call would revert on overflow anyway. -- **No reentrancy concern**: `msg.sender` receives funds, then `doPost` runs. If `msg.sender` is a contract, it could reenter during `sendValue`, but at that point all three transfers are complete and the function only calls `doPost` afterward. The function is `internal` so reentrancy guards are the caller's responsibility, and the state is consistent at each external call point. -- **No string reverts**: No revert statements in this file. diff --git a/audit/2026-03-14-01/pass1/LibOrderBookDeploy.md b/audit/2026-03-14-01/pass1/LibOrderBookDeploy.md deleted file mode 100644 index efc52983a7..0000000000 --- a/audit/2026-03-14-01/pass1/LibOrderBookDeploy.md +++ /dev/null @@ -1,34 +0,0 @@ -# A14: LibOrderBookDeploy.sol - Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` (69 lines) - -### Library -- `LibOrderBookDeploy` (line 29) - -### Functions -- `etchOrderBook(Vm vm)` - line 58 - -### Constants -- `ORDERBOOK_DEPLOYED_ADDRESS` = ORDERBOOK_ADDR (line 32) -- `ORDERBOOK_DEPLOYED_CODEHASH` = ORDERBOOK_HASH (line 36) -- `SUB_PARSER_DEPLOYED_ADDRESS` = SUB_PARSER_ADDR (line 40) -- `SUB_PARSER_DEPLOYED_CODEHASH` = SUB_PARSER_HASH (line 44) -- `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` = ROUTE_PROCESSOR_ADDR (line 48) -- `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` = ROUTE_PROCESSOR_HASH (line 52) - -### Imports -- `Vm` from forge-std -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` as ORDERBOOK_* from OrderBookV6.pointers.sol -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` as SUB_PARSER_* from OrderBookV6SubParser.pointers.sol -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` as ROUTE_PROCESSOR_* from RouteProcessor4.pointers.sol - -## Findings - -No security findings. Analysis: - -- **Test-only library**: This library uses `Vm` (Forge cheatcodes), meaning it can only run in a Foundry test/script context, not in production. The `vm.etch` cheatcode is a test primitive. -- **Codehash guard**: Each `etch` call is guarded by a codehash comparison (lines 59, 62, 65), preventing unnecessary etching when the contract is already correctly deployed. This is idempotent and safe. -- **No external calls to untrusted contracts**: All interactions are with the Forge VM cheatcode interface. -- **No assembly, no string reverts, no state mutations**: Pure deployment utility. diff --git a/audit/2026-03-14-01/pass1/LibOrderBookSubParser.md b/audit/2026-03-14-01/pass1/LibOrderBookSubParser.md deleted file mode 100644 index 8e30c48b57..0000000000 --- a/audit/2026-03-14-01/pass1/LibOrderBookSubParser.md +++ /dev/null @@ -1,77 +0,0 @@ -# A13: LibOrderBookSubParser.sol - Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/lib/LibOrderBookSubParser.sol` (633 lines) - -### Library -- `LibOrderBookSubParser` (line 101) - -### Functions -- `subParserSender(uint256, uint256, OperandV2)` - line 105 -- `subParserCallingContract(uint256, uint256, OperandV2)` - line 111 -- `subParserOrderHash(uint256, uint256, OperandV2)` - line 121 -- `subParserOrderOwner(uint256, uint256, OperandV2)` - line 130 -- `subParserOrderCounterparty(uint256, uint256, OperandV2)` - line 141 -- `subParserMaxOutput(uint256, uint256, OperandV2)` - line 152 -- `subParserIORatio(uint256, uint256, OperandV2)` - line 162 -- `subParserInputToken(uint256, uint256, OperandV2)` - line 172 -- `subParserInputTokenDecimals(uint256, uint256, OperandV2)` - line 182 -- `subParserInputVaultId(uint256, uint256, OperandV2)` - line 192 -- `subParserInputBalanceBefore(uint256, uint256, OperandV2)` - line 202 -- `subParserInputBalanceDiff(uint256, uint256, OperandV2)` - line 212 -- `subParserOutputToken(uint256, uint256, OperandV2)` - line 222 -- `subParserOutputTokenDecimals(uint256, uint256, OperandV2)` - line 232 -- `subParserOutputVaultId(uint256, uint256, OperandV2)` - line 242 -- `subParserOutputBalanceBefore(uint256, uint256, OperandV2)` - line 252 -- `subParserOutputBalanceDiff(uint256, uint256, OperandV2)` - line 262 -- `subParserSigners(uint256, uint256, OperandV2 operand)` - line 273 -- `subParserDepositToken(uint256, uint256, OperandV2)` - line 283 -- `subParserDepositVaultId(uint256, uint256, OperandV2)` - line 293 -- `subParserDepositVaultBalanceBefore(uint256, uint256, OperandV2)` - line 304 -- `subParserDepositVaultBalanceAfter(uint256, uint256, OperandV2)` - line 317 -- `subParserWithdrawToken(uint256, uint256, OperandV2)` - line 330 -- `subParserWithdrawVaultId(uint256, uint256, OperandV2)` - line 340 -- `subParserWithdrawVaultBalanceBefore(uint256, uint256, OperandV2)` - line 350 -- `subParserWithdrawVaultBalanceAfter(uint256, uint256, OperandV2)` - line 364 -- `subParserWithdrawTargetAmount(uint256, uint256, OperandV2)` - line 377 -- `subParserSignedContext(uint256, uint256, OperandV2 operand)` - line 390 -- `authoringMetaV2()` - line 406 - -### Constants (file-level) -- `SUB_PARSER_WORD_PARSERS_LENGTH` = 2 (line 49) -- `EXTERN_PARSE_META_BUILD_DEPTH` = 1 (line 50) -- `WORD_ORDER_CLEARER` through `WORD_WITHDRAW_TARGET_AMOUNT` (lines 52-81, 18 word constants) -- `DEPOSIT_WORD_DEPOSITOR` = 0 (line 83) -- `DEPOSIT_WORD_TOKEN` = 1 (line 84) -- `DEPOSIT_WORD_VAULT_ID` = 2 (line 85) -- `DEPOSIT_WORD_VAULT_BEFORE` = 3 (line 86) -- `DEPOSIT_WORD_VAULT_AFTER` = 4 (line 87) -- `DEPOSIT_WORDS_LENGTH` = 5 (line 88) -- `WITHDRAW_WORD_WITHDRAWER` = 0 (line 90) -- `WITHDRAW_WORD_TOKEN` = 1 (line 91) -- `WITHDRAW_WORD_VAULT_ID` = 2 (line 92) -- `WITHDRAW_WORD_VAULT_BEFORE` = 3 (line 93) -- `WITHDRAW_WORD_VAULT_AFTER` = 4 (line 94) -- `WITHDRAW_WORD_TARGET_AMOUNT` = 5 (line 95) -- `WITHDRAW_WORDS_LENGTH` = 6 (line 96) - -### Imports -- `AuthoringMetaV2`, `OperandV2` from ISubParserV4 -- `LibUint256Matrix` from rain.solmem -- `LibSubParse` from rain.interpreter -- All CONTEXT_* constants from LibOrderBook - -### Assembly blocks -- Lines 622-624: `metaUint256 := meta` (type cast `AuthoringMetaV2[][]` to `uint256[][]`) -- Lines 627-629: `metaFlattened := metaUint256Flattened` (type cast `uint256[]` to `AuthoringMetaV2[]`) - -## Findings - -No security findings. Analysis: - -- **All subParser functions are `pure`**: They only map word names to context column/row indices. No state, no external calls, no side effects. -- **Assembly type casts** (lines 622-624, 627-629): These reinterpret `AuthoringMetaV2[][]` as `uint256[][]` for flattening, then cast back. This is safe because both types have identical memory layout (array of 32-byte slots). The `AuthoringMetaV2` struct has two `bytes32` fields, and `uint256` is also 32 bytes, so the pointer cast is layout-compatible for the purpose of `flatten()`. -- **`subParserSigners`** (line 273): Uses raw operand as row index. No bounds check, but this is a parser-time operation that produces context references -- out-of-bounds access would be caught at runtime by the interpreter when the context array is indexed. -- **`subParserSignedContext`** (line 390): Extracts column from low byte and row from next byte of operand. Same parser-time safety as above. -- **No string reverts**: No revert statements in this file. diff --git a/audit/2026-03-14-01/pass1/OrderBookV6.md b/audit/2026-03-14-01/pass1/OrderBookV6.md deleted file mode 100644 index fe06f7b108..0000000000 --- a/audit/2026-03-14-01/pass1/OrderBookV6.md +++ /dev/null @@ -1,92 +0,0 @@ -# A08 — OrderBookV6.sol — Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/concrete/ob/OrderBookV6.sol` (1062 lines) - -**Contract:** `OrderBookV6` (inherits `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender`) - -**Errors (lines 69-125):** -- `ReentrancyGuardReentrantCall()` — line 69 -- `NotOrderOwner(address owner)` — line 73 -- `TokenMismatch()` — line 76 -- `TokenSelfTrade()` — line 79 -- `TokenDecimalsMismatch()` — line 83 -- `MinimumIO(Float minimumIO, Float actualIO)` — line 88 -- `SameOwner()` — line 91 -- `UnsupportedCalculateInputs(uint256 inputs)` — line 95 -- `UnsupportedCalculateOutputs(uint256 outputs)` — line 99 -- `NegativeInput()` — line 102 -- `NegativeOutput()` — line 105 -- `NegativeVaultBalance(Float vaultBalance)` — line 109 -- `NegativeVaultBalanceChange(Float amount)` — line 113 -- `NegativePull()` — line 116 -- `NegativePush()` — line 119 -- `NegativeBounty()` — line 122 -- `ClearZeroAmount()` — line 125 - -**Constants (lines 129-150):** -- `ORDER_LIVE = 1` — line 129 -- `ORDER_DEAD = 0` — line 134 -- `CALCULATE_ORDER_ENTRYPOINT = SourceIndexV2.wrap(0)` — line 137 -- `HANDLE_IO_ENTRYPOINT = SourceIndexV2.wrap(1)` — line 140 -- `CALCULATE_ORDER_MIN_OUTPUTS = 2` — line 143 -- `CALCULATE_ORDER_MAX_OUTPUTS = 2` — line 145 -- `HANDLE_IO_MIN_OUTPUTS = 0` — line 148 -- `HANDLE_IO_MAX_OUTPUTS = 0` — line 150 - -**Struct:** -- `OrderIOCalculationV4` — line 178 - -**State variables:** -- `sOrders` — line 208 (`mapping(bytes32 => uint256)`) -- `sVaultBalances` — line 215 (`mapping(address => mapping(address => mapping(bytes32 => Float)))`) - -**Functions:** -- `vaultBalance2(address, address, bytes32)` — line 219 (external view) -- `_vaultBalance(address, address, bytes32)` — line 226 (internal view) -- `orderExists(bytes32)` — line 244 (external view) -- `entask2(TaskV2[])` — line 249 (external) -- `deposit4(address, bytes32, Float, TaskV2[])` — line 254 (external) -- `withdraw4(address, bytes32, Float, TaskV2[])` — line 289 (external) -- `addOrder4(OrderConfigV4, TaskV2[])` — line 328 (external) -- `removeOrder3(OrderV4, TaskV2[])` — line 378 (external) -- `checkTokenSelfTrade(OrderV4, uint256, uint256)` — line 403 (internal pure) -- `quote2(QuoteV2)` — line 410 (external view) -- `takeOrders4(TakeOrdersConfigV5)` — line 433 (external) -- `clear3(OrderV4, OrderV4, ClearConfigV2, SignedContextV1[], SignedContextV1[])` — line 593 (external) -- `calculateOrderIO(OrderV4, uint256, uint256, address, SignedContextV1[])` — line 698 (internal view) -- `increaseVaultBalance(address, address, bytes32, Float)` — line 822 (internal) -- `decreaseVaultBalance(address, address, bytes32, Float)` — line 855 (internal) -- `recordVaultIO(Float, Float, OrderIOCalculationV4)` — line 893 (internal) -- `handleIO(OrderIOCalculationV4)` — line 919 (internal) -- `calculateClearStateChange(OrderIOCalculationV4, OrderIOCalculationV4)` — line 971 (internal pure) -- `calculateClearStateAlice(OrderIOCalculationV4, OrderIOCalculationV4)` — line 987 (internal pure) -- `pullTokens(address, address, Float)` — line 1008 (internal) -- `pushTokens(address, address, Float)` — line 1032 (internal) -- `_nonZeroVaultId(address, address, bytes32)` — line 1052 (internal pure) -- `nonZeroVaultId` modifier — line 1058 - -## Findings - -### A08-1 — LOW — `clear3` computes `aliceOrder.hash()` and `bobOrder.hash()` twice each - -**Location:** `src/concrete/ob/OrderBookV6.sol`, lines 623-628 - -**Description:** In `clear3`, `aliceOrder.hash()` is called on line 623 for the liveness check, and then again implicitly inside `calculateOrderIO` on line 706 (called from line 635). Similarly for `bobOrder.hash()` on lines 627 and 638. This is a gas inefficiency rather than a correctness issue, but the duplicate hashing costs meaningful gas for a function that may be called frequently. The hash involves `abi.encode` of the full `OrderV4` struct which is non-trivial. - -**Impact:** Gas waste only. No correctness or security impact — the hash is deterministic so re-computation returns the same value. - -### A08-2 — INFO — Unused errors `UnsupportedCalculateInputs`, `NegativeInput`, `NegativeOutput`, `TokenDecimalsMismatch` - -**Location:** `src/concrete/ob/OrderBookV6.sol`, lines 83, 95, 102, 105 - -**Description:** Several custom errors are declared but never used within the contract: -- `TokenDecimalsMismatch` (line 83) — no code path reverts with this error -- `UnsupportedCalculateInputs` (line 95) — the calculate order entrypoint sends no inputs (empty stack at line 778), so this error can never trigger -- `NegativeInput` (line 102) — never referenced in any revert -- `NegativeOutput` (line 105) — never referenced in any revert - -These may be used by other contracts or are vestigial from a previous version. - -**Impact:** No security impact. Dead code that may cause confusion during maintenance. diff --git a/audit/2026-03-14-01/pass1/OrderBookV6ArbCommon.md b/audit/2026-03-14-01/pass1/OrderBookV6ArbCommon.md deleted file mode 100644 index ad050f0da6..0000000000 --- a/audit/2026-03-14-01/pass1/OrderBookV6ArbCommon.md +++ /dev/null @@ -1,57 +0,0 @@ -# A01: OrderBookV6ArbCommon.sol - Pass 1 (Security) - -**File:** `src/abstract/OrderBookV6ArbCommon.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6ArbCommon` (abstract, line 29) - -**Struct:** -- `OrderBookV6ArbConfig` (line 13): fields `task` (TaskV2), `implementationData` (bytes) - -**Error:** -- `WrongTask()` (line 19) - -**Constant:** -- `BEFORE_ARB_SOURCE_INDEX` (line 23): `SourceIndexV2.wrap(0)` - -**Event:** -- `Construct(address sender, OrderBookV6ArbConfig config)` (line 35) - -**State:** -- `iTaskHash` (line 39): `bytes32 public immutable`, initialized to 0 - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 42) -- `onlyValidTask(TaskV2 memory task)` modifier (line 54) - -**Imports:** -- `EvaluableV4`, `SignedContextV1` from `IInterpreterCallerV4.sol` (line 5) -- `SourceIndexV2` from `IInterpreterV4.sol` (line 6) -- `IRaindexV6`, `TaskV2` from `IRaindexV6.sol` (line 7) -- `LibEvaluable` from `LibEvaluable.sol` (line 8) - -**Using:** -- `LibEvaluable for EvaluableV4` (line 30) - -## Security Analysis - -### Constructor (line 42-49) -- Emits `Construct` before any state changes or external calls -- correct ordering. -- Sets `iTaskHash` only if `config.task.evaluable.bytecode.length != 0`. Zero-length bytecode means no task gating. -- `keccak256(abi.encode(config.task))` is collision-resistant for structured data. - -### onlyValidTask modifier (line 54-58) -- Short-circuits when `iTaskHash == bytes32(0)` (no task configured), allowing unrestricted access. This is documented behavior. -- When a task IS configured, requires exact hash match. Uses `keccak256(abi.encode(task))` which is deterministic for the same `TaskV2` struct. - -### BEFORE_ARB_SOURCE_INDEX (line 23) -- Declared but not used within this file. It is a public constant for inheriting contracts. Not a security concern. - -## Findings - -No security findings. The contract is minimal and correct: -- Immutable task hash prevents post-deployment mutation. -- The modifier correctly gates access when a task is configured. -- No external calls, no state mutations beyond immutable initialization. -- Custom error `WrongTask()` is used (no string reverts). diff --git a/audit/2026-03-14-01/pass1/OrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass1/OrderBookV6ArbOrderTaker.md deleted file mode 100644 index fa0cfca489..0000000000 --- a/audit/2026-03-14-01/pass1/OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,56 +0,0 @@ -# A02: OrderBookV6ArbOrderTaker.sol - Pass 1 (Security) - -**File:** `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6ArbOrderTaker` (abstract, line 20) -- Inherits: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 29) -- `supportsInterface(bytes4 interfaceId)` (line 32): public view virtual override -- `arb5(IRaindexV6 orderBook, TakeOrdersConfigV5 calldata takeOrders, TaskV2 calldata task)` (line 38): external payable nonReentrant onlyValidTask -- `onTakeOrders2(address, address, Float, Float, bytes calldata)` (line 70): public virtual override (no-op) - -**Imports (lines 5-14):** -- `ERC165`, `IERC165` from OpenZeppelin -- `ReentrancyGuard` from OpenZeppelin -- `IERC20`, `SafeERC20` from OpenZeppelin -- `IRaindexV6` from rain.raindex.interface -- `IRaindexV6ArbOrderTaker`, `TaskV2` from rain.raindex.interface -- `TakeOrdersConfigV5`, `Float` from rain.raindex.interface -- `OrderBookV6ArbConfig`, `EvaluableV4`, `OrderBookV6ArbCommon`, `SignedContextV1` from `./OrderBookV6ArbCommon.sol` -- `LibOrderBookArb` from `../lib/LibOrderBookArb.sol` -- `IRaindexV6OrderTaker` from rain.raindex.interface -- `LibTOFUTokenDecimals` from rain.tofu.erc20-decimals - -**Using:** -- `SafeERC20 for IERC20` (line 27) - -## Security Analysis - -### arb5 (lines 38-64) -- **Reentrancy:** Protected by `nonReentrant`. -- **Task validation:** `onlyValidTask(task)` correctly applied. -- **Zero-order check:** line 45 reverts with `IRaindexV6.NoOrders()` -- matches OrderBook behavior. -- **Token extraction:** lines 49-50 read from `takeOrders.orders[0]`. The OrderBook's `takeOrders4` enforces `TokenMismatch` if subsequent orders use different tokens, so using index 0 is safe. -- **Approval pattern:** lines 52-55: `forceApprove(max)` -> `takeOrders4` -> `forceApprove(0)`. Classic approve-call-revoke. Uses `forceApprove` which handles non-standard tokens (USDT-style). -- **Unvalidated `orderBook` parameter:** The caller supplies the `orderBook` address. A malicious address could exploit the `type(uint256).max` approval window. However, since the caller IS `msg.sender` and `finalizeArb` sends all proceeds to `msg.sender`, the caller would only be attacking themselves. The contract holds no tokens between operations. - -### onTakeOrders2 (line 70) -- No-op in the base. No `msg.sender` validation, which the `IRaindexV6OrderTaker` interface documentation says MUST be present. However, the doc comment on line 67-69 explains this is intentional because the contract holds no value between operations and the caller chooses the orderbook. - -### supportsInterface (lines 32-35) -- Correctly reports support for both `IRaindexV6OrderTaker` and `IRaindexV6ArbOrderTaker`. Calls `super.supportsInterface` for ERC165 chain. - -## Findings - -No security findings. The contract correctly applies: -- `nonReentrant` on the entry point -- approve-call-revoke pattern with `forceApprove` -- Custom errors only (no string reverts) -- Zero-order guard before external calls -- Task-based access control - -The unvalidated `orderBook` parameter is a conscious design choice documented in comments. The caller controls this parameter and would only harm themselves by passing a malicious address since `finalizeArb` sends all proceeds to `msg.sender`. diff --git a/audit/2026-03-14-01/pass1/OrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass1/OrderBookV6FlashBorrower.md deleted file mode 100644 index e2e7fd62d1..0000000000 --- a/audit/2026-03-14-01/pass1/OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,72 +0,0 @@ -# A03: OrderBookV6FlashBorrower.sol - Pass 1 (Security) - -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashBorrower` (abstract, line 60) -- Inherits: `IERC3156FlashBorrower`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -**Errors:** -- `BadInitiator(address badInitiator)` (line 20) -- `BadLender(address badLender)` (line 25) -- `FlashLoanFailed()` (line 28) - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 63) -- `supportsInterface(bytes4 interfaceId)` (line 66): public view virtual override -- `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData)` (line 79): internal virtual (no-op hook) -- `onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data)` (line 82): external, returns bytes32 -- `arb4(IRaindexV6 orderBook, TakeOrdersConfigV5 calldata takeOrders, bytes calldata exchangeData, TaskV2 calldata task)` (line 129): external payable nonReentrant onlyValidTask - -**Imports (lines 5-16):** -- `ERC165`, `IERC165` from OpenZeppelin -- `SafeERC20` from OpenZeppelin -- `IERC20` from OpenZeppelin -- `ReentrancyGuard` from OpenZeppelin -- `ON_FLASH_LOAN_CALLBACK_SUCCESS` from rain.raindex.interface -- `IRaindexV6`, `TakeOrdersConfigV5`, `TaskV2` from rain.raindex.interface -- `IERC3156FlashBorrower` from rain.raindex.interface -- `OrderBookV6ArbConfig`, `OrderBookV6ArbCommon` from `./OrderBookV6ArbCommon.sol` -- `LibOrderBookArb` from `../lib/LibOrderBookArb.sol` -- `LibOrderBookDeploy` from `../lib/deploy/LibOrderBookDeploy.sol` -- `LibTOFUTokenDecimals` from rain.tofu.erc20-decimals -- `LibDecimalFloat` from rain.math.float - -**Using:** -- `SafeERC20 for IERC20` (line 61) - -## Security Analysis - -### onFlashLoan (lines 82-108) -- **Lender validation:** line 84 checks `msg.sender != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS`. This is a hardcoded deterministic address. Correct -- prevents arbitrary contracts from triggering the callback. -- **Initiator validation:** line 88 checks `initiator != address(this)`. Prevents other contracts from initiating flash loans on behalf of this contract. -- **Data decoding:** line 92-93 decodes `(TakeOrdersConfigV5, bytes)` from calldata. The decode will revert on malformed data (standard ABI behavior). -- **Flow:** calls `_exchange` hook, then `takeOrders4` on the validated `msg.sender` (which must be the deterministic orderbook). -- **Return:** returns `ON_FLASH_LOAN_CALLBACK_SUCCESS` constant. -- **Named unused params:** `address` (token), `uint256` (amount), `uint256` (fee) are unnamed -- correct since they're not needed. - -### arb4 (lines 129-166) -- **Reentrancy:** Protected by `nonReentrant`. -- **Task validation:** `onlyValidTask(task)` correctly applied. -- **Zero-order check:** line 136 reverts with `IRaindexV6.NoOrders()`. -- **Token extraction:** lines 144-145 read from `takeOrders.orders[0]` -- safe due to OrderBook's `TokenMismatch` enforcement. -- **Flash loan amount:** line 152 uses `toFixedDecimalLossless` which reverts on precision loss, preventing silent truncation. -- **Approval pattern:** lines 157-163: `forceApprove(max)` for both tokens -> `flashLoan` -> `forceApprove(0)` for both tokens. Correct approve-call-revoke. -- **Flash loan failure check:** line 159 checks the boolean return and reverts with `FlashLoanFailed()`. -- **Unvalidated `orderBook` parameter:** Same analysis as A02. The caller controls this parameter. If `orderBook` is not the real deterministic orderbook, `onFlashLoan` will revert with `BadLender`. If the fake orderbook never calls `onFlashLoan` and just returns true, approvals exist but the contract holds no tokens at that point. - -### _exchange (line 79) -- Virtual no-op hook for inheritors. Marked `internal` so cannot be called externally. - -### supportsInterface (lines 66-68) -- Reports support for `IERC3156FlashBorrower`. Calls `super.supportsInterface`. - -## Findings - -No security findings. The contract implements a robust flash-loan-based arb pattern: -- Dual validation (lender address + initiator address) on the callback -- `nonReentrant` on the entry point -- approve-call-revoke for both tokens with `forceApprove` -- Custom errors only (no string reverts) -- Lossless decimal conversion prevents silent precision loss diff --git a/audit/2026-03-14-01/pass1/OrderBookV6FlashLender.md b/audit/2026-03-14-01/pass1/OrderBookV6FlashLender.md deleted file mode 100644 index 14e8a1909f..0000000000 --- a/audit/2026-03-14-01/pass1/OrderBookV6FlashLender.md +++ /dev/null @@ -1,59 +0,0 @@ -# A04: OrderBookV6FlashLender.sol - Pass 1 (Security) - -**File:** `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence of Thorough Reading - -**Contract:** `OrderBookV6FlashLender` (abstract, line 29) -- Inherits: `IERC3156FlashLender`, `ERC165` - -**Error:** -- `FlashLenderCallbackFailed(bytes32 result)` (line 18) - -**Constant:** -- `FLASH_FEE` (line 23): `uint256 constant = 0` - -**Functions:** -- `supportsInterface(bytes4 interfaceId)` (line 33): public view virtual override -- `flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)` (line 38): external override, returns bool -- `flashFee(address, uint256)` (line 70): external pure override, returns uint256 -- `maxFlashLoan(address token)` (line 77): external view override, returns uint256 - -**Imports (lines 5-13):** -- `ERC165`, `IERC165` from OpenZeppelin -- `IERC20` from OpenZeppelin -- `SafeERC20` from OpenZeppelin -- `IERC3156FlashBorrower`, `ON_FLASH_LOAN_CALLBACK_SUCCESS` from rain.raindex.interface -- `IERC3156FlashLender` from rain.raindex.interface - -**Using:** -- `SafeERC20 for IERC20` (line 30) - -## Security Analysis - -### flashLoan (lines 38-67) -- **Token transfer out:** line 43 uses `safeTransfer` to send `amount` to `receiver`. Reverts if balance insufficient -- implicit `maxFlashLoan` check. -- **Callback:** line 45 calls `receiver.onFlashLoan(msg.sender, token, amount, FLASH_FEE, data)`. -- **Callback validation:** line 46-48 checks return value against `ON_FLASH_LOAN_CALLBACK_SUCCESS`. Reverts with `FlashLenderCallbackFailed` on mismatch. This is per ERC3156 spec. -- **Repayment:** line 64 uses `safeTransferFrom` to pull `amount + FLASH_FEE` (= `amount + 0`) from receiver. Requires the receiver to have approved the lender. -- **No reentrancy guard:** The function does NOT have `nonReentrant`. This is intentional for ERC3156 composability -- flash loans should be nestable. The concrete `OrderBookV6` inherits `ReentrancyGuard` but does not apply `nonReentrant` to `flashLoan`. The callback to `receiver.onFlashLoan` could re-enter `flashLoan` for a nested loan. Each nested loan must be fully repaid (safeTransferFrom at the end of each frame), so the balance is always restored. -- **External call to untrusted receiver:** The `receiver` is caller-supplied. The `onFlashLoan` callback executes arbitrary code. This is by design per ERC3156. The repayment via `safeTransferFrom` ensures the lender is made whole regardless of what the callback does. - -### flashFee (line 70-72) -- Always returns 0. No token parameter validation needed since fee is constant. - -### maxFlashLoan (lines 77-79) -- Returns `IERC20(token).balanceOf(address(this))`. This is an external call that could fail for non-ERC20 addresses, but that would simply revert the view call. No state corruption risk. - -### supportsInterface (lines 33-35) -- Reports support for `IERC3156FlashLender`. Calls `super.supportsInterface`. - -## Findings - -No security findings. The implementation follows the ERC3156 reference implementation faithfully: -- Callback return value is validated -- Repayment is enforced via `safeTransferFrom` -- Zero fee is a valid design choice, documented in comments -- Lack of `nonReentrant` is correct for ERC3156 composability -- Custom error `FlashLenderCallbackFailed` used (no string reverts) -- The Slither suppression on line 63 is well-documented with a thorough rationale diff --git a/audit/2026-03-14-01/pass1/OrderBookV6SubParser.md b/audit/2026-03-14-01/pass1/OrderBookV6SubParser.md deleted file mode 100644 index 1420096181..0000000000 --- a/audit/2026-03-14-01/pass1/OrderBookV6SubParser.md +++ /dev/null @@ -1,46 +0,0 @@ -# A09 — OrderBookV6SubParser.sol — Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` (301 lines) - -**Contract:** `OrderBookV6SubParser` (inherits `BaseRainterpreterSubParser`) - -**Functions:** -- `describedByMetaV1()` — line 73 (external pure) -- `subParserParseMeta()` — line 78 (internal pure override) -- `subParserWordParsers()` — line 83 (internal pure override) -- `subParserOperandHandlers()` — line 88 (internal pure override) -- `buildLiteralParserFunctionPointers()` — line 93 (external pure) -- `buildOperandHandlerFunctionPointers()` — line 98 (external pure) -- `buildSubParserWordParsers()` — line 183 (external pure) - -**Types/Errors/Constants defined in this file:** None (all imported) - -**Using-for directives:** -- `LibUint256Matrix for uint256[][]` — line 70 - -**Imports (significant):** -- `LibParseOperand`, `BaseRainterpreterSubParser`, `OperandV2`, `IParserToolingV1` — line 6 -- `LibConvert` — line 11 -- `LibUint256Matrix` — line 12 -- `LibOrderBookSubParser` and various `SUB_PARSER_WORD_PARSERS_LENGTH`, `DEPOSIT_WORD_*`, `WITHDRAW_WORD_*` constants — lines 14-30 -- `CONTEXT_*` constants — lines 31-60 -- Generated pointers: `DESCRIBED_BY_META_HASH`, `SUB_PARSER_PARSE_META`, `SUB_PARSER_WORD_PARSERS`, `SUB_PARSER_OPERAND_HANDLERS` — lines 62-66 - -**Assembly blocks:** -- Line 174-176: `handlers` (function pointer 2D array) cast to `handlersUint256` (uint256 2D array) -- Line 295-297: `parsers` (function pointer 2D array) cast to `parsersUint256` (uint256 2D array) - -## Findings - -No security findings identified. - -### Analysis Notes - -The two assembly blocks at lines 174-176 and 295-297 perform type punning casts from function-pointer arrays to `uint256[][]`. Both are marked `"memory-safe"`. This is safe because: -1. Function pointers and `uint256` have the same size (32 bytes) in the EVM ABI. -2. The resulting `uint256[][]` is immediately passed to `LibConvert.unsafeTo16BitBytes(...)` via `.flatten()`, which reads the values as raw bytes. No writes occur. -3. The arrays are freshly allocated within the same function, so there is no aliasing concern. - -All `buildOperandHandlerFunctionPointers` and `buildSubParserWordParsers` are `external pure` functions that produce deterministic pointer tables. They contain no state access, external calls, or user-controlled inputs that could lead to security issues. diff --git a/audit/2026-03-14-01/pass1/RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass1/RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index a9979702b8..0000000000 --- a/audit/2026-03-14-01/pass1/RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,45 +0,0 @@ -# A07 — RouteProcessorOrderBookV6ArbOrderTaker.sol — Pass 1 (Security) - -## Evidence of Thorough Reading - -**File:** `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` (56 lines) - -**Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (inherits `OrderBookV6ArbOrderTaker`) - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` — line 21 -- `onTakeOrders2(address inputToken, address outputToken, Float inputAmountSent, Float totalOutputAmount, bytes calldata takeOrdersData)` — line 27 -- `receive()` — line 54 -- `fallback()` — line 55 - -**Types/Errors/Constants:** None defined in this file. - -**State variables:** -- `iRouteProcessor` (immutable, `IRouteProcessor`) — line 19 - -**Imports:** -- `IRouteProcessor` from sushixswap-v2 (line 5) -- `IERC20` from OpenZeppelin (line 6) -- `SafeERC20` from OpenZeppelin (line 7) -- `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float` (line 9) -- `LibDecimalFloat` (line 10) -- `IERC20Metadata` (line 11) - -**Using-for directives:** -- `SafeERC20 for IERC20` (line 16) - -## Findings - -No security findings identified. - -### Analysis Notes - -The approve-call-revoke pattern on lines 35/49 is correctly implemented: `forceApprove(max)` before the route processor call and `forceApprove(0)` after. - -The `onTakeOrders2` function is called by OrderBook during `takeOrders4` (via the `config.data` callback mechanism). The parent `onTakeOrders2` at line 34 (`super.onTakeOrders2(...)`) is a no-op in the base class, which is correct. - -The lossy conversion at line 40-41 for `inputTokenAmount` is acceptable as noted in the comment — the route processor only needs an approximate amount. For `outputTokenAmount` (lines 42-46), the `++` on lossy conversion correctly rounds up the minimum output to protect against receiving fewer tokens than needed. - -The `iRouteProcessor` is immutable (set at construction), which prevents it from being changed after deployment. - -The `receive()` and `fallback()` functions are intentionally open for the same reason as the flash borrower — to receive ETH during swaps, with all balances swept by `finalizeArb`. diff --git a/audit/2026-03-14-01/pass2/A01-OrderBookV6ArbCommon.md b/audit/2026-03-14-01/pass2/A01-OrderBookV6ArbCommon.md deleted file mode 100644 index 6a6c208b01..0000000000 --- a/audit/2026-03-14-01/pass2/A01-OrderBookV6ArbCommon.md +++ /dev/null @@ -1,37 +0,0 @@ -# Pass 2 -- Test Coverage: A01 OrderBookV6ArbCommon - -**Source file:** `src/abstract/OrderBookV6ArbCommon.sol` (60 lines) - -## Source Summary - -- `OrderBookV6ArbConfig` struct (task + implementationData) -- `WrongTask` error -- `BEFORE_ARB_SOURCE_INDEX` constant (SourceIndexV2.wrap(0)) -- `iTaskHash` immutable bytes32 (defaults to 0) -- Constructor: emits `Construct`, sets `iTaskHash = keccak256(abi.encode(task))` when bytecode is non-empty -- `onlyValidTask` modifier: reverts `WrongTask` if iTaskHash != 0 and hash mismatch - -## Test Files Found - -| Test file | What it covers | -|-----------|---------------| -| `test/abstract/OrderBookV6ArbCommon.iTaskHash.t.sol` | iTaskHash non-empty and empty bytecode | -| `test/abstract/OrderBookV6ArbCommon.fallback.t.sol` | fallback/receive on OrderTaker and FlashBorrower | -| `test/abstract/OrderBookV6FlashBorrower.wrongTask.t.sol` | WrongTask revert on arb4 (FlashBorrower path) | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | WrongTask revert on arb5 (OrderTaker path) | -| `test/util/abstract/ArbTest.sol` | Construct event emission verified | - -## Coverage Analysis - -### Well-covered - -- iTaskHash set correctly for non-empty bytecode (testITaskHashNonEmpty) -- iTaskHash is bytes32(0) for empty bytecode (testITaskHashEmpty) -- WrongTask revert on arb4 (FlashBorrower path) with fuzzed evaluable -- WrongTask revert on arb5 (OrderTaker path) with fuzzed evaluable -- Construct event emission (ArbTest constructor uses vm.expectEmit) -- Passthrough when iTaskHash is bytes32(0) (many tests pass empty bytecode) - -### Gaps - -**No gaps found.** All functions, error paths, and the modifier are exercised. diff --git a/audit/2026-03-14-01/pass2/A02-OrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass2/A02-OrderBookV6ArbOrderTaker.md deleted file mode 100644 index 264a662827..0000000000 --- a/audit/2026-03-14-01/pass2/A02-OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,41 +0,0 @@ -# Pass 2 -- Test Coverage: A02 OrderBookV6ArbOrderTaker - -**Source file:** `src/abstract/OrderBookV6ArbOrderTaker.sol` (71 lines) - -## Source Summary - -- Inherits: IRaindexV6OrderTaker, IRaindexV6ArbOrderTaker, ReentrancyGuard, ERC165, OrderBookV6ArbCommon -- Constructor: passes config to OrderBookV6ArbCommon -- `supportsInterface`: reports IRaindexV6OrderTaker + IRaindexV6ArbOrderTaker + ERC165 -- `arb5`: external payable, nonReentrant, onlyValidTask. Reverts NoOrders if empty. Reads input/output tokens from orders[0]. forceApprove input -> OB, takeOrders4, revoke approval, finalizeArb. -- `onTakeOrders2`: public virtual, empty no-op - -## Test Files Found - -| Test file | What it covers | -|-----------|---------------| -| `test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol` | supportsInterface for IERC165, IRaindexV6ArbOrderTaker, IRaindexV6OrderTaker, rejects bad IDs | -| `test/abstract/OrderBookV6ArbOrderTaker.noOrders.t.sol` | arb5 reverts NoOrders with empty array | -| `test/abstract/OrderBookV6ArbOrderTaker.reentrancy.t.sol` | arb5 reverts ReentrancyGuardReentrantCall when re-entered | -| `test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol` | Full arb5 cycle with real ERC20 transfers | -| `test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol` | Direct call to onTakeOrders2 succeeds (no-op) | -| `test/abstract/OrderBookV6ArbOrderTaker.context.t.sol` | Context column values in finalizeArb task | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | WrongTask revert + correct task passthrough on arb5 | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` | arb5 end-to-end with mocked OB | - -## Coverage Analysis - -### Well-covered - -- supportsInterface (positive + negative fuzz) -- arb5 NoOrders revert -- arb5 reentrancy guard -- arb5 full cycle with real tokens -- arb5 WrongTask revert (via expression test) -- arb5 with valid task passthrough -- onTakeOrders2 direct call (no-op behavior) -- Context values in finalizeArb - -### Gaps - -**No gaps found.** All functions and error paths are exercised through both unit and integration-style tests. diff --git a/audit/2026-03-14-01/pass2/A03-OrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass2/A03-OrderBookV6FlashBorrower.md deleted file mode 100644 index 4c022604ad..0000000000 --- a/audit/2026-03-14-01/pass2/A03-OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,53 +0,0 @@ -# Pass 2 -- Test Coverage: A03 OrderBookV6FlashBorrower - -**Source file:** `src/abstract/OrderBookV6FlashBorrower.sol` (167 lines) - -## Source Summary - -- Errors: `BadInitiator(address)`, `BadLender(address)`, `FlashLoanFailed` -- Inherits: IERC3156FlashBorrower, ReentrancyGuard, ERC165, OrderBookV6ArbCommon -- Constructor: passes config to OrderBookV6ArbCommon -- `supportsInterface`: reports IERC3156FlashBorrower + ERC165 -- `_exchange`: internal virtual, empty no-op (hook for inheritors) -- `onFlashLoan`: external. Checks BadLender (msg.sender != deterministic OB), BadInitiator (initiator != address(this)). Decodes data, calls _exchange, calls takeOrders4. Returns ON_FLASH_LOAN_CALLBACK_SUCCESS. -- `arb4`: external payable, nonReentrant, onlyValidTask. Reverts NoOrders if empty. Reads tokens, gets decimals, computes flashLoanAmount from minimumIO. forceApprove both tokens -> OB, flashLoan, revoke both approvals, finalizeArb. Reverts FlashLoanFailed if flashLoan returns false. - -## Test Files Found - -| Test file | What it covers | -|-----------|---------------| -| `test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol` | supportsInterface for IERC165 + IERC3156FlashBorrower, rejects bad IDs | -| `test/abstract/OrderBookV6FlashBorrower.noOrders.t.sol` | arb4 reverts NoOrders with empty array | -| `test/abstract/OrderBookV6FlashBorrower.wrongTask.t.sol` | arb4 reverts WrongTask with mismatched task | -| `test/abstract/OrderBookV6FlashBorrower.badInitiator.t.sol` | onFlashLoan reverts BadInitiator when initiator != self | -| `test/abstract/OrderBookV6FlashBorrower.lenderValidation.t.sol` | onFlashLoan reverts BadLender when called by non-OB contract | -| `test/abstract/OrderBookV6FlashBorrower.badLenderApproval.t.sol` | Malicious OB triggers BadLender; approvals don't persist | -| `test/abstract/OrderBookV6FlashBorrower.flashLoanFailed.t.sol` | arb4 reverts FlashLoanFailed when flashLoan returns false | -| `test/abstract/OrderBookV6FlashBorrower.realTokenTransfers.t.sol` | Full arb4 cycle with real ERC20 transfers | -| `test/abstract/OrderBookV6FlashBorrower.mixedDecimals.t.sol` | arb4 with 6-decimal output + 18-decimal input | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol` | arb4 end-to-end with mocked OB | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol` | ETH forwarded during _exchange | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol` | Spender approval revoked after _exchange | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol` | Exchange revert propagates through arb4 | - -## Coverage Analysis - -### Well-covered - -- supportsInterface (positive + negative fuzz) -- arb4 NoOrders revert -- arb4 WrongTask revert (fuzzed evaluable) -- onFlashLoan BadInitiator (fuzzed bad initiator) -- onFlashLoan BadLender (malicious lender contract) -- BadLender via malicious OB passed to arb4 (approval atomicity) -- FlashLoanFailed when flashLoan returns false -- Full cycle with real ERC20 transfers -- Mixed decimal tokens (6 + 18) -- _exchange hook (tested through GenericPool concrete) - -### Gaps - -#### GAP-A03-1: No reentrancy test for arb4 - -**Severity:** Low -**Details:** `arb5` on `OrderBookV6ArbOrderTaker` has a dedicated reentrancy test (`OrderBookV6ArbOrderTaker.reentrancy.t.sol`) that verifies `nonReentrant` prevents re-entry via the `takeOrders4` callback. There is no equivalent test for `arb4` on `OrderBookV6FlashBorrower`. While `arb4` also uses `nonReentrant`, explicit test coverage for the flash borrower reentrancy path is missing. The flash loan callback creates a distinct reentrancy vector (via `onFlashLoan` -> `_exchange` -> re-enter `arb4`) that should be tested independently. diff --git a/audit/2026-03-14-01/pass2/A04-OrderBookV6FlashLender.md b/audit/2026-03-14-01/pass2/A04-OrderBookV6FlashLender.md deleted file mode 100644 index 228dd8813e..0000000000 --- a/audit/2026-03-14-01/pass2/A04-OrderBookV6FlashLender.md +++ /dev/null @@ -1,44 +0,0 @@ -# Pass 2 -- Test Coverage: A04 OrderBookV6FlashLender - -**Source file:** `src/abstract/OrderBookV6FlashLender.sol` (80 lines) - -## Source Summary - -- Error: `FlashLenderCallbackFailed(bytes32 result)` -- Constant: `FLASH_FEE = 0` -- Inherits: IERC3156FlashLender, ERC165 -- `supportsInterface`: reports IERC3156FlashLender + ERC165 -- `flashLoan`: external. safeTransfer amount to receiver, calls receiver.onFlashLoan, checks result == ON_FLASH_LOAN_CALLBACK_SUCCESS (reverts FlashLenderCallbackFailed otherwise), safeTransferFrom amount+fee back. Returns true. -- `flashFee`: pure, returns FLASH_FEE (0) -- `maxFlashLoan`: returns IERC20(token).balanceOf(address(this)) - -## Test Files Found - -| Test file | What it covers | -|-----------|---------------| -| `test/abstract/OrderBookV6FlashLender.ierc165.t.sol` | supportsInterface for IERC165 + IERC3156FlashLender, rejects bad IDs | -| `test/abstract/OrderBookV6FlashLender.fee.t.sol` | flashFee returns 0 for any token/amount (fuzzed) | -| `test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol` | maxFlashLoan returns mocked balanceOf (fuzzed) | -| `test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol` | flashLoan succeeds with mocked transfers and correct callback | -| `test/abstract/OrderBookV6FlashLender.transfers.t.sol` | Real token transfer cycle: success path (Bob returns tokens), fail path (Carol withholds tokens), and bad callback return | -| `test/abstract/OrderBookV6FlashLender.reentrant.t.sol` | Flash borrower can reenter OB (deposit, withdraw, addOrder, removeOrder, takeOrders, clear, vaultBalance, orderExists) | -| `test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol` | Reverts for EOA receiver, bad callback value, and non-bytes32 return | - -## Coverage Analysis - -### Well-covered - -- supportsInterface (positive + negative fuzz) -- flashFee always returns 0 (fuzzed) -- maxFlashLoan returns token balance (fuzzed) -- flashLoan success path (mocked + real tokens) -- FlashLenderCallbackFailed revert (bad return value) -- Transfer failure when borrower can't repay (Carol withholds) -- EOA receiver revert (no code at address) -- Non-bytes32 callback return revert -- Reentrancy from within flash loan (all major OB operations) -- Real token transfer accounting (Bob returns all tokens) - -### Gaps - -**No gaps found.** All functions and error paths are well-exercised with both unit tests and integration scenarios. The reentrancy test suite is particularly thorough, covering all major orderbook operations from within a flash loan callback. diff --git a/audit/2026-03-14-01/pass2/A05-GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass2/A05-GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index a6d9d4e690..0000000000 --- a/audit/2026-03-14-01/pass2/A05-GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,103 +0,0 @@ -# Pass 2: Test Coverage -- A05 GenericPoolOrderBookV6ArbOrderTaker - -**File:** `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` - -## Evidence of Reading - -### Source File (47 lines) - -**Contract:** `GenericPoolOrderBookV6ArbOrderTaker is OrderBookV6ArbOrderTaker` - -| Item | Kind | Line | -|------|------|------| -| `constructor(OrderBookV6ArbConfig memory config)` | constructor | 18 | -| `onTakeOrders2(address inputToken, address outputToken, Float inputAmountSent, Float totalOutputAmount, bytes calldata takeOrdersData)` | function (public virtual override) | 21-41 | -| `receive()` | special function (external payable) | 45 | -| `fallback()` | special function (external payable) | 46 | - -**Imports used:** `IERC20`, `SafeERC20`, `Address`, `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float` - -**Inherited from `OrderBookV6ArbOrderTaker` (lines relevant to this concrete contract):** -- `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` -- entry point (line 38-64 of parent) -- `onTakeOrders2(...)` -- base no-op (line 70 of parent), overridden by this contract -- `supportsInterface(bytes4)` -- ERC165 (line 32-35 of parent) -- `nonReentrant` modifier from `ReentrancyGuard` -- `onlyValidTask(task)` modifier from `OrderBookV6ArbCommon` - -**`onTakeOrders2` logic (lines 27-41):** -1. Calls `super.onTakeOrders2(...)` (no-op in parent) -2. `abi.decode(takeOrdersData, (address, address, bytes))` into `(spender, pool, encodedFunctionCall)` -3. `IERC20(inputToken).forceApprove(spender, type(uint256).max)` -- line 35 -4. `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -- line 39 -5. `IERC20(inputToken).forceApprove(spender, 0)` -- line 40 (revoke) - -### Test Files Read in Full - -| # | Test file | Tests | What it covers | -|---|-----------|-------|----------------| -| 1 | `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | `testGenericPoolTakeOrdersWrongExpression`, `testGenericPoolTakeOrdersExpression` | WrongTask revert when task mismatch; correct expression passthrough via arb5 with mocked interpreter | -| 2 | `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` | `testGenericPoolTakeOrdersSender` | arb5 end-to-end with mocked OB (FlashLendingMockOrderBook + Refundoor) | -| 3 | `test/abstract/OrderBookV6ArbCommon.fallback.t.sol` | `testFallbackAcceptsCalldata`, `testFallbackAcceptsEmptyCalldata`, `testReceiveAcceptsETH`, `testFallbackAcceptsETHWithCalldata` | receive() and fallback() accept ETH and arbitrary calldata | -| 4 | `test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2.t.sol` | `testArb5RealTokenTransfers` | Full arb5 cycle with real ERC20 transfers through RealisticOrderTakerMockOrderBook + MockExchange; asserts all balances zero on arb at end | -| 5 | `test/abstract/OrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol` | `testOnTakeOrders2DirectCallSucceeds` | Direct external call to onTakeOrders2 by arbitrary address succeeds (no access control by design); verifies contract remains empty | -| 6 | `test/abstract/OrderBookV6ArbOrderTaker.noOrders.t.sol` | `testArb5NoOrders` | arb5 reverts with `NoOrders` on empty orders array | -| 7 | `test/abstract/OrderBookV6ArbOrderTaker.reentrancy.t.sol` | `testArb5Reentrancy` | arb5 reverts with `ReentrancyGuardReentrantCall` when mock OB re-enters arb5 during takeOrders4 callback | -| 8 | `test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol` | `testOrderBookV6ArbOrderTakerIERC165` | ERC165 interface reporting for IERC165, IRaindexV6ArbOrderTaker, IRaindexV6OrderTaker; fuzz rejects unknown IDs | -| 9 | `test/abstract/OrderBookV6ArbOrderTaker.context.t.sol` | `testOrderBookV6ArbOrderTakerContext` | Verifies context column values (input token, output token, gas balance) passed to finalizeArb task | -| 10 | `test/abstract/OrderBookV6ArbCommon.iTaskHash.t.sol` | `testITaskHashNonEmpty`, `testITaskHashEmpty` | iTaskHash set correctly for non-empty bytecode, zero for empty bytecode | -| 11 | `test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol` | `testFinalizeArbTransfersInputTokenProfit` | 20e18 profit swept to msg.sender; arb contract empty after | -| 12 | `test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol` | `testFinalizeArbSendsNativeGas` | ETH sent with arb5{value:}, forwarded to exchange via functionCallWithValue, returned, swept by finalizeArb | - -### Proposed Fix File Already Present - -| Fix file | Covers | -|----------|--------| -| `audit/2026-03-14-01/pass2/.fixes/GAP-A05-1-OrderTakerApprovalRevoked.t.sol` | Test asserting spender allowance is zero after onTakeOrders2 completes (approve-call-revoke) | - -## Coverage Analysis - -### Well-Covered - -1. **Constructor** -- deployed in every test via `GenericPoolOrderBookV6ArbOrderTakerTest` base or directly. Construct event tested in `ArbTest`. -2. **`onTakeOrders2` full flow** -- `testArb5RealTokenTransfers` (test #4) drives the complete decode -> approve -> pool call -> revoke cycle with real ERC20 transfers and asserts final balances. -3. **`onTakeOrders2` direct call safety** -- `testOnTakeOrders2DirectCallSucceeds` (test #5) confirms an arbitrary caller can invoke it without extracting value. -4. **`receive()` and `fallback()`** -- four tests (test #3) covering ETH-only, calldata-only, ETH+calldata, and empty calldata. -5. **WrongTask revert** -- fuzz test (test #1) validates revert when evaluable does not match stored task. -6. **Expression passthrough** -- fuzz test (test #1) validates interpreter eval4 call with correct task. -7. **NoOrders revert** -- test #6. -8. **Reentrancy guard** -- test #7 via `ReentrantMockOrderBook`. -9. **ERC165 interface support** -- fuzz test (test #8). -10. **Context values in finalizeArb** -- test #9 with real interpreter. -11. **iTaskHash construction** -- test #10. -12. **Token profit sweep** -- test #11. -13. **Native gas sweep** -- test #12 with `arb5{value: 1 ether}`, confirming ETH flows through `functionCallWithValue` and back via `finalizeArb`. - -### Gaps - -#### GAP-A05-1: No dedicated test that spender allowance is zero after onTakeOrders2 (approve-call-revoke) - -**Severity:** LOW - -**Details:** The `GenericPoolOrderBookV6FlashBorrower` has a dedicated test (`GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol`) verifying the spender's allowance is zero after `_exchange` completes. The equivalent approve-call-revoke pattern in `GenericPoolOrderBookV6ArbOrderTaker.onTakeOrders2` (lines 35-40) has no dedicated assertion verifying the allowance is revoked to zero after the pool call. The existing `onTakeOrders2.t.sol` test exercises the full flow but does not assert the post-call allowance state. - -A proposed fix is already present at `audit/2026-03-14-01/pass2/.fixes/GAP-A05-1-OrderTakerApprovalRevoked.t.sol` using `AllowanceCheckingExchange` to record `lastAllowance` during the call and then assert `allowance == 0` after arb5 completes. - -#### GAP-A05-2: No test for pool call revert propagation (order-taker path) - -**Severity:** LOW - -**Details:** The flash borrower path has a dedicated test (`GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol`) verifying that when the exchange/pool call reverts, the revert reason bubbles up through the entire arb transaction. The order-taker path uses `Address.functionCallWithValue` on line 39, which also bubbles reverts, but there is no corresponding test for this contract. Since `Address.functionCallWithValue` is well-tested OpenZeppelin code and the flash borrower already validates the pattern, the practical risk is minimal, but parity with the flash borrower test suite would improve confidence. - -#### GAP-A05-3: No test with spender != pool - -**Severity:** INFO - -**Details:** All existing tests use `spender == pool` (or `spender == exchange`). The `onTakeOrders2` logic supports `spender != pool` -- the approval goes to `spender` while the call goes to `pool`. No test exercises this split-address scenario. This is a design feature documented in the contract (the caller controls both addresses), but a test with distinct spender and pool addresses would confirm the approve targets the correct address independently of the call target. - -## Findings - -| ID | Severity | Title | -|----|----------|-------| -| A05-1 | LOW | No dedicated test for approval revocation after onTakeOrders2 | -| A05-2 | LOW | No test for pool call revert propagation (order-taker path) | -| A05-3 | INFO | No test with spender != pool | diff --git a/audit/2026-03-14-01/pass2/A06-GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass2/A06-GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index 310c767c1e..0000000000 --- a/audit/2026-03-14-01/pass2/A06-GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,96 +0,0 @@ -# Pass 2: Test Coverage — A06 GenericPoolOrderBookV6FlashBorrower - -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` - -## Evidence of Reading - -### Source: `GenericPoolOrderBookV6FlashBorrower.sol` (53 lines) - -**Contract:** `GenericPoolOrderBookV6FlashBorrower is OrderBookV6FlashBorrower` - -| Item | Kind | Line | -|---|---|---| -| `GenericPoolOrderBookV6FlashBorrower` | contract | 26 | -| `constructor(OrderBookV6ArbConfig)` | constructor | 30 | -| `_exchange(TakeOrdersConfigV5, bytes)` | internal virtual override | 33 | -| `receive()` | external payable | 51 | -| `fallback()` | external payable | 52 | - -**Inherited (from `OrderBookV6FlashBorrower`, relevant):** - -| Item | Kind | Line (parent) | -|---|---|---| -| `supportsInterface(bytes4)` | public view override | 66 | -| `onFlashLoan(address, address, uint256, uint256, bytes)` | external | 82 | -| `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` | external payable nonReentrant | 129 | -| `BadInitiator` | error | 20 | -| `BadLender` | error | 25 | -| `FlashLoanFailed` | error | 28 | - -**`_exchange` logic (lines 33-47):** -1. Decodes `exchangeData` into `(address spender, address pool, bytes encodedFunctionCall)`. -2. Reads `borrowedToken` from `takeOrders.orders[0].order.validOutputs[...].token`. -3. `forceApprove(spender, type(uint256).max)` on the borrowed token. -4. `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -- forwards all ETH. -5. `forceApprove(spender, 0)` to revoke approval. - -### Test Files Read in Full - -| Test File | Tests | -|---|---| -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol` | `testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender` (fuzz, 10 runs) | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol` | `testApprovalRevokedAfterExchange` | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol` | `testEthForwardedToExchangeDuringExchange` | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol` | `testExchangeRevertPropagates` | -| `test/abstract/OrderBookV6ArbCommon.fallback.t.sol` | `testFallbackAcceptsCalldata`, `testFallbackAcceptsEmptyCalldata`, `testReceiveAcceptsETH`, `testFallbackAcceptsETHWithCalldata` (FlashBorrower variant) | -| `test/abstract/OrderBookV6FlashBorrower.badLenderApproval.t.sol` | `testBadLenderRevertsWithApproval` | -| `test/abstract/OrderBookV6FlashBorrower.noOrders.t.sol` | `testArb4NoOrders` | -| `test/abstract/OrderBookV6FlashBorrower.wrongTask.t.sol` | `testArb4WrongTask` (fuzz, 10 runs) | -| `test/abstract/OrderBookV6FlashBorrower.realTokenTransfers.t.sol` | `testArb4RealTokenTransfers` | -| `test/abstract/OrderBookV6FlashBorrower.lenderValidation.t.sol` | `testMaliciousLenderCannotExploitOnFlashLoan` | -| `test/abstract/OrderBookV6FlashBorrower.flashLoanFailed.t.sol` | `testFlashLoanFailed` | -| `test/abstract/OrderBookV6FlashBorrower.mixedDecimals.t.sol` | `testArb4MixedDecimals` | -| `test/abstract/OrderBookV6FlashBorrower.badInitiator.t.sol` | `testOnFlashLoanBadInitiator` (fuzz) | - -## Coverage Summary - -**What IS tested:** -- Happy-path arb cycle with real ERC20 transfers (18-decimal tokens) -- Happy-path arb with mixed decimals (6/18) -- Approve-call-revoke pattern (max approval during call, zero after) -- ETH forwarding to pool via `functionCallWithValue` -- Exchange revert propagation -- `receive()` and `fallback()` accept ETH and arbitrary calldata -- `BadLender` error when malicious lender calls `onFlashLoan` directly -- `BadLender` error when malicious orderbook is passed to `arb4` -- `BadInitiator` error when initiator is not the arb contract (fuzz) -- `NoOrders` error on empty orders array -- `WrongTask` error on mismatched task hash (fuzz) -- `FlashLoanFailed` error when `flashLoan` returns false -- Construction emits `Construct` event (via `ArbTest` base) - -## Findings - -### A06-1: No test for `spender != pool` in `_exchange` (LOW) - -**Location:** `_exchange`, lines 33-47 of `GenericPoolOrderBookV6FlashBorrower.sol` - -**Description:** The `_exchange` function decodes three values from `exchangeData`: `spender`, `pool`, and `encodedFunctionCall`. The `spender` receives the ERC20 approval while the `pool` receives the function call. The NatSpec explicitly documents that these can differ ("If you are unsure, simply set it to the pool address"). However, every test sets `spender == pool`. There is no test exercising the case where the `spender` and `pool` are different addresses, which is a documented use case (e.g., router patterns where a router contract is called but a separate vault/spender pulls tokens). - -**Impact:** If a code change accidentally conflated the two addresses (e.g., approving `pool` instead of `spender`), no test would catch it. - -### A06-2: No fuzz test over `exchangeData` decoding in `_exchange` (LOW) - -**Location:** `_exchange`, line 34-35 of `GenericPoolOrderBookV6FlashBorrower.sol` - -**Description:** The `exchangeData` parameter is `abi.decode`d into `(address, address, bytes)`. There are no fuzz tests that exercise malformed or adversarial `exchangeData` payloads. While Solidity's `abi.decode` will revert on malformed data, a fuzz test would provide confidence that no edge case in the decoding or downstream usage (e.g., zero-address spender, zero-address pool, empty `encodedFunctionCall`) causes unexpected behavior rather than a clean revert. - -**Impact:** Low -- `abi.decode` provides built-in safety, but explicit coverage of edge cases (address(0) spender, address(0) pool, empty bytes) would strengthen the test suite. - -### A06-3: `supportsInterface` not tested for `GenericPoolOrderBookV6FlashBorrower` (INFO) - -**Location:** Inherited `supportsInterface` from `OrderBookV6FlashBorrower`, line 66 - -**Description:** There is no test verifying that `GenericPoolOrderBookV6FlashBorrower.supportsInterface` correctly returns `true` for `IERC3156FlashBorrower.interfaceId` and `IERC165.interfaceId`, and `false` for unsupported interface IDs. While this is standard OpenZeppelin behavior, explicit tests for ERC-165 compliance are a best practice for contracts that declare interface support. - -**Impact:** Informational -- unlikely to break, but good hygiene. diff --git a/audit/2026-03-14-01/pass2/A07-RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass2/A07-RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 3278d8c826..0000000000 --- a/audit/2026-03-14-01/pass2/A07-RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,85 +0,0 @@ -# Pass 2: Test Coverage — A07 RouteProcessorOrderBookV6ArbOrderTaker - -**File:** src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol - -## Evidence of Reading - -**Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (inherits `OrderBookV6ArbOrderTaker`) - -**State variables:** -- `iRouteProcessor` (immutable, `IRouteProcessor`) — line 19 - -**Functions/methods with line numbers:** -- `constructor(OrderBookV6ArbConfig memory config)` — line 21 -- `onTakeOrders2(address inputToken, address outputToken, Float inputAmountSent, Float totalOutputAmount, bytes calldata takeOrdersData)` — line 27 -- `receive() external payable` — line 54 -- `fallback() external payable` — line 55 - -**Inherited from `OrderBookV6ArbOrderTaker` (abstract):** -- `supportsInterface(bytes4)` — tested in `test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol` -- `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` — tested via sender/expression tests -- `onTakeOrders2(...)` base no-op — overridden - -**Types/errors/constants defined in this file:** None - -**Using-for directives:** -- `SafeERC20 for IERC20` — line 16 - -### Test files examined - -| Test file | What it tests | -|---|---| -| `test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol` | Base test harness; builds arb with `Refundoor` as `implementationData` | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol` | Full arb5 cycle with MockRouteProcessor + RealisticOrderTakerMockOrderBook; 18-decimal tokens only | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.invalidConstructor.t.sol` | Constructor revert on empty and malformed `implementationData` | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol` | Direct external call to `onTakeOrders2` by arbitrary sender with zero amounts | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol` | Fuzz test (100 runs) on `arb5` with varied `OrderV4` structs | -| `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` | Fuzz tests (100 runs each) for wrong-expression revert and valid expression eval | -| `test/abstract/OrderBookV6ArbOrderTaker.ierc165.t.sol` | ERC165 `supportsInterface` for parent abstract contract | - -### Mock infrastructure examined - -| Mock | Purpose | -|---|---| -| `MockRouteProcessor` | Pulls `amountIn` of `tokenIn` from sender, sends all its `tokenOut` balance to recipient | -| `RealisticOrderTakerMockOrderBook` | Sends `outputToken` to taker, fires `onTakeOrders2` callback, then pulls fixed `iPullAmount` of `inputToken` | -| `MockToken` | ERC20 with configurable decimals | - -## Findings - -### A07-1: No test for non-18-decimal tokens in onTakeOrders2 (MEDIUM) - -**Location:** `onTakeOrders2` lines 40-46 - -The `onTakeOrders2` function calls `LibDecimalFloat.toFixedDecimalLossy` using `IERC20Metadata(inputToken).decimals()` and `IERC20Metadata(outputToken).decimals()`. The only integration test (`testRouteProcessorArb5`) uses 18-decimal tokens exclusively. The `MockToken` mock supports configurable decimals but this capability is never exercised. - -Tokens with low decimals (e.g., USDC with 6, WBTC with 8) or zero decimals will produce very different fixed-point values and may interact differently with the route processor's `amountIn` parameter. The lossy rounding-up logic on `outputTokenAmount` (line 44-46) is also untested for cases where precision loss actually occurs (it only occurs for non-18-decimal tokens with certain Float values). - -**Gap:** No test exercises tokens with decimals other than 18, leaving the `toFixedDecimalLossy` conversion and the `outputTokenAmount++` rounding branch untested. - -### A07-2: No test for receive() and fallback() payable functions (LOW) - -**Location:** lines 54-55 - -The `receive()` and `fallback()` functions accept arbitrary ETH and calldata. No test verifies that: -1. The contract can receive plain ETH transfers. -2. The contract can receive ETH via calls with arbitrary calldata. -3. ETH received is correctly swept by `finalizeArb`. - -These are intentionally open (documented in the comment on line 52-53), but their behavior is not verified by any test. - -### A07-3: No fuzz test on onTakeOrders2 parameters directly (LOW) - -**Location:** `onTakeOrders2` line 27 - -The `sender.t.sol` fuzz test fuzzes the `OrderV4` struct but always passes fixed `takeOrdersData` (literal `bytes("0x00")`), and the `FlashLendingMockOrderBook` mock does not perform the actual `onTakeOrders2` callback with realistic Float amounts. The only test that exercises the real `onTakeOrders2` code path (`testRouteProcessorArb5`) uses a single hardcoded scenario with `Float.wrap(0)` for both amounts (set by `RealisticOrderTakerMockOrderBook`). - -There is no fuzz coverage of `onTakeOrders2` with varied `inputAmountSent`, `totalOutputAmount`, or `takeOrdersData` values. Edge cases such as very large Float values, Float values that overflow during `toFixedDecimalLossy`, or malformed `takeOrdersData` (not ABI-decodable as `bytes`) are untested. - -### A07-4: Constructor accepts address(0) as routeProcessor without revert (INFO) - -**Location:** constructor line 22 - -The constructor decodes `config.implementationData` as an address and sets `iRouteProcessor`. If the decoded address is `address(0)`, the constructor succeeds and the contract is deployed with a null route processor. Any subsequent `onTakeOrders2` call would then call `processRoute` on `address(0)`, which would silently succeed (as calls to EOAs succeed in the EVM) without performing any swap. - -The test suite covers empty and malformed `implementationData` but does not test `abi.encode(address(0))`. This is INFO severity because the deployer controls the address and a misconfiguration would be caught on first use (no tokens swapped), but it could be guarded in the constructor. diff --git a/audit/2026-03-14-01/pass2/A08-OrderBookV6.md b/audit/2026-03-14-01/pass2/A08-OrderBookV6.md deleted file mode 100644 index e38cdfc3b7..0000000000 --- a/audit/2026-03-14-01/pass2/A08-OrderBookV6.md +++ /dev/null @@ -1,231 +0,0 @@ -# Pass 2: Test Coverage -- A08 OrderBookV6 - -**File:** src/concrete/ob/OrderBookV6.sol - -## Evidence of Reading - -### Contract: `OrderBookV6` (line 191) -Inherits: `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender` - -### Errors (lines 69-125) -- `ReentrancyGuardReentrantCall` (line 69) -- `NotOrderOwner(address owner)` (line 73) -- `TokenMismatch` (line 76) -- `TokenSelfTrade` (line 79) -- `TokenDecimalsMismatch` (line 83) -- `MinimumIO(Float minimumIO, Float actualIO)` (line 88) -- `SameOwner` (line 91) -- `UnsupportedCalculateInputs(uint256 inputs)` (line 95) -- `UnsupportedCalculateOutputs(uint256 outputs)` (line 99) -- `NegativeInput` (line 102) -- `NegativeOutput` (line 105) -- `NegativeVaultBalance(Float vaultBalance)` (line 109) -- `NegativeVaultBalanceChange(Float amount)` (line 113) -- `NegativePull` (line 116) -- `NegativePush` (line 119) -- `NegativeBounty` (line 122) -- `ClearZeroAmount` (line 125) - -### Constants (lines 129-150) -- `ORDER_LIVE = 1` (line 129) -- `ORDER_DEAD = 0` (line 134) -- `CALCULATE_ORDER_ENTRYPOINT = SourceIndexV2.wrap(0)` (line 137) -- `HANDLE_IO_ENTRYPOINT = SourceIndexV2.wrap(1)` (line 140) -- `CALCULATE_ORDER_MIN_OUTPUTS = 2` (line 143) -- `CALCULATE_ORDER_MAX_OUTPUTS = 2` (line 145) -- `HANDLE_IO_MIN_OUTPUTS = 0` (line 148) -- `HANDLE_IO_MAX_OUTPUTS = 0` (line 150) - -### Struct (lines 178-187) -- `OrderIOCalculationV4` (line 178) - -### State Variables (lines 208-216) -- `sOrders` mapping (line 208) -- `sVaultBalances` mapping (line 215) - -### Functions -- `vaultBalance2(address, address, bytes32) external view` (line 219) -- `_vaultBalance(address, address, bytes32) internal view` (line 226) -- `orderExists(bytes32) external view` (line 244) -- `entask2(TaskV2[] calldata) external` (line 249) -- `deposit4(address, bytes32, Float, TaskV2[] calldata) external` (line 254) -- `withdraw4(address, bytes32, Float, TaskV2[] calldata) external` (line 289) -- `addOrder4(OrderConfigV4 calldata, TaskV2[] calldata) external` (line 328) -- `removeOrder3(OrderV4 calldata, TaskV2[] calldata) external` (line 378) -- `checkTokenSelfTrade(OrderV4, uint256, uint256) internal pure` (line 403) -- `quote2(QuoteV2 calldata) external view` (line 410) -- `takeOrders4(TakeOrdersConfigV5 calldata) external` (line 433) -- `clear3(OrderV4, OrderV4, ClearConfigV2, SignedContextV1[], SignedContextV1[]) external` (line 593) -- `calculateOrderIO(OrderV4, uint256, uint256, address, SignedContextV1[]) internal view` (line 698) -- `increaseVaultBalance(address, address, bytes32, Float) internal` (line 822) -- `decreaseVaultBalance(address, address, bytes32, Float) internal` (line 855) -- `recordVaultIO(Float, Float, OrderIOCalculationV4) internal` (line 893) -- `handleIO(OrderIOCalculationV4) internal` (line 919) -- `calculateClearStateChange(OrderIOCalculationV4, OrderIOCalculationV4) internal pure` (line 971) -- `calculateClearStateAlice(OrderIOCalculationV4, OrderIOCalculationV4) internal pure` (line 987) -- `pullTokens(address, address, Float) internal` (line 1008) -- `pushTokens(address, address, Float) internal` (line 1032) -- `_nonZeroVaultId(address, address, bytes32) internal pure` (line 1052) -- `nonZeroVaultId modifier` (line 1058) - -### Test Files Read -- `test/concrete/ob/OrderBookV6.deposit.t.sol` -- deposit basic, zero, zero vault id, gas, failure, many, event, reentrancy -- `test/concrete/ob/OrderBookV6.deposit.entask.t.sol` -- deposit entask, context, revert in action -- `test/concrete/ob/OrderBookV6.withdraw.t.sol` -- withdraw zero vault id, zero, empty vault, full, partial, failure, many -- `test/concrete/ob/OrderBookV6.withdraw.entask.t.sol` -- withdraw entask, context, revert in action, zero amount eval -- `test/concrete/ob/OrderBookV6.addOrder.t.sol` -- add order real (various stack sizes, inputs) -- `test/concrete/ob/OrderBookV6.addOrder.mock.t.sol` -- add without calculations/inputs/outputs, with meta, two accounts -- `test/concrete/ob/OrderBookV6.addOrder.entask.t.sol` -- add order entask, context, revert blocks add, noop on live -- `test/concrete/ob/OrderBookV6.addOrder.nonce.t.sol` -- nonce same order noop, different nonce state change -- `test/concrete/ob/OrderBookV6.addOrder.owner.t.sol` -- owner same order noop, different owner state change -- `test/concrete/ob/OrderBookV6.removeOrder.mock.t.sol` -- only owner, add/remove multi, does not exist, different orders/owners -- `test/concrete/ob/OrderBookV6.removeOrder.owner.t.sol` -- owner noop, different owner, wrong owner -- `test/concrete/ob/OrderBookV6.removeOrder.entask.t.sol` -- remove entask, context, dead order noop, revert blocks removal -- `test/concrete/ob/OrderBookV6.entask.t.sol` -- entask basic, stateless, read state, write state, namespaced -- `test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol` -- zero orders, non-live order (one and two) -- `test/concrete/ob/OrderBookV6.takeOrder.tokenMismatch.t.sol` -- input/output token mismatch -- `test/concrete/ob/OrderBookV6.takeOrder.sameToken.t.sol` -- same token self trade -- `test/concrete/ob/OrderBookV6.takeOrder.badStack.t.sol` -- empty and one stack -- `test/concrete/ob/OrderBookV6.takeOrder.handleIO.revert.t.sol` -- handle IO revert scenarios (0-10), missing handle IO, vault 0 -- `test/concrete/ob/OrderBookV6.takeOrder.maximumInput.t.sol` -- max input single/multi order, vault limited, vault 0 -- `test/concrete/ob/OrderBookV6.takeOrder.maximumOutput.t.sol` -- max output single/multi order, vault limited, vault 0 -- `test/concrete/ob/OrderBookV6.takeOrder.precision.t.sol` -- precision known-bad values, various decimal combos, vault 0 -- `test/concrete/ob/OrderBookV6.clear.mock.t.sol` -- comprehensive clear mocking with various IO ratios, NegativeBounty -- `test/concrete/ob/OrderBookV6.clear.zeroAmount.t.sol` -- clear zero amount -- `test/concrete/ob/OrderBookV6.clear.sameToken.t.sol` -- clear same token -- `test/concrete/ob/OrderBookV6.clear.badStack.t.sol` -- clear bad stack (empty, one, mixed) -- `test/concrete/ob/OrderBookV6.clear.handleIO.revert.t.sol` -- clear handle IO revert, missing handle IO, vault 0 -- `test/concrete/ob/OrderBookV6.clear.context.t.sol` (not fully read but referenced in glob) -- `test/concrete/ob/OrderBookV6.quote.t.sol` -- quote dead order, simple, max output, context/sender, vault 0 -- `test/concrete/ob/OrderBookV6.quote.sameToken.t.sol` -- quote same token error -- `test/concrete/ob/OrderBookV6.vaultBalance.t.sol` -- vault balance no deposits - -## Findings - -### A08-1: No test for `MinimumIO` revert in `takeOrders4` - -**Severity:** MEDIUM - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 558-563 - -The `takeOrders4` function checks whether the actual relevant taker IO meets the `minimumIO` threshold (line 560) and reverts with `MinimumIO(config.minimumIO, actualRelevantTakerIO)` if it does not. There are no tests anywhere in the test suite that trigger this `MinimumIO` revert. All test configurations set `minimumIO` to 0. This is a financially significant guard -- if untested, a regression could allow takers to accept trades below their minimum threshold without error, causing unexpected losses. - ---- - -### A08-2: No test for `SameOwner` revert in `clear3` - -**Severity:** MEDIUM - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 601-603 - -The `clear3` function checks `aliceOrder.owner == bobOrder.owner` and reverts with `SameOwner()` on line 602. There is no dedicated test that exercises this code path. The `clear.mock.t.sol` test always ensures `alice != bob`. A missing guard for self-clearing could allow an owner to clear against themselves, which may have unintended economic consequences (e.g., manipulating vault balances or extracting bounties). - ---- - -### A08-3: No test for `OrderExceedsMaxRatio` event/skip path in `takeOrders4` - -**Severity:** MEDIUM - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 500-501 - -When an order's `IORatio` exceeds `config.maximumIORatio`, the order is skipped and `OrderExceedsMaxRatio` is emitted. There are no tests that set a meaningful `maximumIORatio` below the order's ratio to verify this skip path. All tests set `maximumIORatio` to `type(int224).max`. This means the taker's max-ratio protection is untested -- a regression allowing expensive orders to execute despite the cap would go unnoticed. - ---- - -### A08-4: No test for `OrderZeroAmount` event/skip path in `takeOrders4` - -**Severity:** LOW - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 502-503 - -When an order's `outputMax` is zero, the order is skipped with `OrderZeroAmount` emitted. While the clear.mock.t.sol tests exercise zero-amount outputs in clearing, no `takeOrders4` test specifically verifies that a live order with zero `outputMax` is properly skipped (as opposed to dead orders, which are tested). The take-order code path handles this differently from dead orders -- it evaluates the expression first, then skips based on the result. - ---- - -### A08-5: No test for `NegativeVaultBalance` revert in `increaseVaultBalance` / `decreaseVaultBalance` - -**Severity:** LOW - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 844-846 (increase) and 878-879 (decrease) - -The `increaseVaultBalance` function has a guard against a negative resulting balance (line 844), though the comment acknowledges this "should never be possible." The `decreaseVaultBalance` function guards against the balance going negative (line 878), which can happen if an order tries to output more than its vault holds. Neither `NegativeVaultBalance` revert path is directly tested. For `decreaseVaultBalance`, the outputMax is capped at vault balance in `calculateOrderIO` (line 801), but a direct test that the guard fires correctly if somehow triggered would improve confidence. - ---- - -### A08-6: No test for `NegativeVaultBalanceChange` revert - -**Severity:** LOW - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 826-828 and 859-861 - -Both `increaseVaultBalance` and `decreaseVaultBalance` check that the `amount` parameter is not negative and revert with `NegativeVaultBalanceChange(amount)` if it is. These guards are defensive checks for internal invariants. No tests exercise these revert paths. - ---- - -### A08-7: No test for `NegativePull` and `NegativePush` reverts - -**Severity:** LOW - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 1013-1014 (NegativePull) and 1038-1039 (NegativePush) - -The `pullTokens` and `pushTokens` functions guard against negative amounts. These are defensive checks since the code should never call these with negative values, but no tests verify the revert messages are correct or that the guards fire. - ---- - -### A08-8: No test for `IOIsInput = false` branch correctness in `takeOrders4` with `minimumIO` check - -**Severity:** LOW - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 522-530, 559 - -When `IOIsInput` is false, `remainingTakerIO` tracks the output side and the `minimumIO` check applies to `totalTakerOutput`. The `takeOrder.maximumOutput.t.sol` file tests the output path mechanics, but `minimumIO` is always set to 0. There is no test verifying that the `minimumIO` check works correctly in `IOIsInput = false` mode -- i.e., that the minimum is correctly checked against `totalTakerOutput` rather than `totalTakerInput`. - ---- - -### A08-9: `TokenDecimalsMismatch` error is declared but never used - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 83 - -The error `TokenDecimalsMismatch` is declared at line 83 but is never thrown anywhere in the contract. It appears to be dead code. No test references it either. - ---- - -### A08-10: `NegativeInput` and `NegativeOutput` errors are declared but never used - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 102, 105 - -The errors `NegativeInput` (line 102) and `NegativeOutput` (line 105) are declared but never thrown anywhere in the contract. They appear to be dead code from a previous version. No tests reference them. - ---- - -### A08-11: `UnsupportedCalculateInputs` error is declared but never used - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 95 - -The error `UnsupportedCalculateInputs(uint256 inputs)` is declared and imported in `OrderBookV6AddOrderTest` but is never actually thrown by the contract. The `calculateOrderIO` function only checks minimum outputs (line 785), not inputs. The interpreter itself enforces input handling. This is dead code. - ---- - -### A08-12: No test for `Multicall` functionality - -**Severity:** LOW - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 191 - -`OrderBookV6` inherits `Multicall` from OpenZeppelin, which allows batching multiple calls. There are no tests verifying that `multicall` works correctly with OrderBookV6's functions, particularly around reentrancy guard interactions (each sub-call in multicall runs as a delegatecall in the same transaction context). The clear function comment at line 620-622 mentions using `Multicall` for bulk clearing, but this pattern is not tested. - ---- - -### A08-13: No test for `supportsInterface` (ERC165) - -**Severity:** INFO - -**Location:** Inherited via `OrderBookV6FlashLender` -> `ERC165` - -The `OrderBookV6FlashLender` tests in `test/abstract/` do test `supportsInterface` for the flash lender interface, but there is no test verifying `supportsInterface` on the concrete `OrderBookV6` contract directly. Since `OrderBookV6` does not override `supportsInterface`, this is covered by the abstract tests, but a direct integration test on the deployed contract would confirm correct behavior. diff --git a/audit/2026-03-14-01/pass2/A09-OrderBookV6SubParser.md b/audit/2026-03-14-01/pass2/A09-OrderBookV6SubParser.md deleted file mode 100644 index 864c882d9e..0000000000 --- a/audit/2026-03-14-01/pass2/A09-OrderBookV6SubParser.md +++ /dev/null @@ -1,117 +0,0 @@ -# Pass 2: Test Coverage -- A09 OrderBookV6SubParser - -**File:** src/concrete/parser/OrderBookV6SubParser.sol - -## Evidence of Reading - -### Contract: `OrderBookV6SubParser` (inherits `BaseRainterpreterSubParser`) - -**Functions:** -| # | Function | Line | Visibility | Mutability | -|---|----------|------|------------|------------| -| 1 | `describedByMetaV1()` | 73 | external | pure | -| 2 | `subParserParseMeta()` | 78 | internal | pure virtual override | -| 3 | `subParserWordParsers()` | 83 | internal | pure virtual override | -| 4 | `subParserOperandHandlers()` | 88 | internal | pure virtual override | -| 5 | `buildLiteralParserFunctionPointers()` | 93 | external | pure | -| 6 | `buildOperandHandlerFunctionPointers()` | 98 | external | pure | -| 7 | `buildSubParserWordParsers()` | 183 | external | pure | - -**Key imports/types:** -- `BaseRainterpreterSubParser` (parent contract) -- `LibParseOperand` (operand handling helpers) -- `LibOrderBookSubParser` (word parser functions) -- `LibConvert`, `LibUint256Matrix` (encoding utilities) -- `OperandV2` (operand type) -- Generated constants: `DESCRIBED_BY_META_HASH`, `SUB_PARSER_PARSE_META`, `SUB_PARSER_WORD_PARSERS`, `SUB_PARSER_OPERAND_HANDLERS` - -**Context columns configured in `buildOperandHandlerFunctionPointers()` (line 98):** -- `CONTEXT_BASE_COLUMN` -- 2 rows, all `handleOperandDisallowed` -- `CONTEXT_CALLING_CONTEXT_COLUMN` -- 3 rows, all `handleOperandDisallowed` -- `CONTEXT_CALCULATIONS_COLUMN` -- 2 rows, all `handleOperandDisallowed` -- `CONTEXT_VAULT_INPUTS_COLUMN` -- 5 rows, all `handleOperandDisallowed` -- `CONTEXT_VAULT_OUTPUTS_COLUMN` -- 5 rows, all `handleOperandDisallowed` -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` -- 1 row, `handleOperandSingleFullNoDefault` -- `CONTEXT_SIGNED_CONTEXT_START_COLUMN` -- 1 row, `handleOperandDoublePerByteNoDefault` -- Deposit column (CONTEXT_SIGNED_CONTEXT_START_COLUMN + 1) -- 5 rows, all `handleOperandDisallowed` -- Withdraw column (CONTEXT_SIGNED_CONTEXT_START_COLUMN + 2) -- 6 rows, all `handleOperandDisallowed` - -**Context columns configured in `buildSubParserWordParsers()` (line 183):** -- Base: `subParserSender`, `subParserCallingContract` -- Calling context: `subParserOrderHash`, `subParserOrderOwner`, `subParserOrderCounterparty` -- Calculations: `subParserMaxOutput`, `subParserIORatio` -- Vault inputs: 5 sub-parsers (token, decimals, vaultId, balanceBefore, balanceDiff) -- Vault outputs: 5 sub-parsers (token, decimals, vaultId, balanceBefore, balanceDiff) -- Signers: `subParserSigners` -- Signed context: `subParserSignedContext` -- Deposit: 5 sub-parsers (sender, depositToken, depositVaultId, depositVaultBalanceBefore, depositVaultBalanceAfter) -- Withdraw: 6 sub-parsers (sender, withdrawToken, withdrawVaultId, withdrawVaultBalanceBefore, withdrawVaultBalanceAfter, withdrawTargetAmount) - -### Test files read: -- `test/util/abstract/OrderBookV6SubParserContextTest.sol` -- abstract base for context word tests -- `test/util/fixture/LibOrderBookSubParserContextFixture.sol` -- context fixture -- `test/concrete/parser/OrderBookV6SubParser.describedByMeta.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.ierc165.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.pointers.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.signedContext.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.signers.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputToken.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputTokenDecimals.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultId.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderClearer.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderCounterparty.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderHash.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderOwner.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputToken.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputTokenDecimals.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputVaultId.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderBook.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextCalculatedIORatio.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol` -- `test/lib/deploy/LibOrderBookDeploy.t.sol` - -## Findings - -### A09-1: No dedicated sub-parser unit tests for deposit context words [LOW] - -**Description:** The contract registers 5 deposit context words (`depositor`, `deposit-token`, `deposit-vault-id`, `deposit-vault-before`, `deposit-vault-after`) in both `buildSubParserWordParsers()` (lines 269-273) and `buildOperandHandlerFunctionPointers()` (lines 154-158). Every other context word category (base, calling, calculations, vault inputs, vault outputs, signers, signed-context) has dedicated sub-parser unit tests that verify parsing, operand disallowing, and input disallowing via the `OrderBookV6SubParserContextTest` abstract pattern. Deposit words have none of these. - -The deposit words are exercised only via integration-level entask tests in `test/concrete/ob/OrderBookV6.deposit.entask.t.sol`, which test them in the context of a full deposit transaction. This provides coverage for the happy path but does not isolate and verify sub-parser behavior (operand disallowing, input rejection) at the unit level. - -**Impact:** A regression in sub-parser operand handling for deposit words (e.g., accidentally allowing operands when they should be disallowed) would not be caught by existing unit tests. - -**Recommendation:** Add unit test files following the `OrderBookV6SubParserContextTest` pattern for each deposit word. This requires extending `LibOrderBookSubParserContextFixture.hashedNamesContext()` to include the deposit context column. Example files: `OrderBookV6SubParser.contextDepositor.t.sol`, `OrderBookV6SubParser.contextDepositToken.t.sol`, etc. - ---- - -### A09-2: No dedicated sub-parser unit tests for withdraw context words [LOW] - -**Description:** The contract registers 6 withdraw context words (`withdrawer`, `withdraw-token`, `withdraw-vault-id`, `withdraw-vault-before`, `withdraw-vault-after`, `withdraw-target-amount`) in both `buildSubParserWordParsers()` (lines 285-290) and `buildOperandHandlerFunctionPointers()` (lines 164-169). Like deposit words (A09-1), every other context word category has dedicated sub-parser unit tests, but withdraw words do not. - -The withdraw words are exercised only via integration-level entask tests in `test/concrete/ob/OrderBookV6.withdraw.entask.t.sol`. - -Additionally, the test fixture `LibOrderBookSubParserContextFixture.hashedNamesContext()` allocates `CONTEXT_COLUMNS + 3` columns (8 total), but `CONTEXT_COLUMNS_EXTENDED` is 9. The fixture does not populate the withdraw context column at index 8, making it impossible to test withdraw words with the current fixture without extending it. - -**Impact:** Same as A09-1 -- a regression in sub-parser operand handling for withdraw words would not be caught at the unit level. - -**Recommendation:** Extend the fixture to populate all `CONTEXT_COLUMNS_EXTENDED` columns and add unit tests for each withdraw word following the existing pattern. - ---- - -### A09-3: `buildLiteralParserFunctionPointers()` has no direct test [INFO] - -**Description:** The function `buildLiteralParserFunctionPointers()` at line 93 returns an empty `bytes("")`. There is no test that directly calls this function or asserts its return value. The function is required by the `IParserToolingV1` interface and is trivially correct (it returns empty bytes because the sub-parser defines no literal parsers), but it still lacks test coverage. - -**Impact:** Negligible. The function is trivial and stateless. It returns a constant empty bytes value. - -**Recommendation:** Consider adding a simple assertion in the pointers test file: -```solidity -function testBuildLiteralParserFunctionPointers() external pure { - OrderBookV6SubParser extern = OrderBookV6SubParser(LibOrderBookDeploy.SUB_PARSER_DEPLOYED_ADDRESS); - assertEq(extern.buildLiteralParserFunctionPointers(), ""); -} -``` diff --git a/audit/2026-03-14-01/pass2/A10-LibOrder.md b/audit/2026-03-14-01/pass2/A10-LibOrder.md deleted file mode 100644 index 6b3ea22eee..0000000000 --- a/audit/2026-03-14-01/pass2/A10-LibOrder.md +++ /dev/null @@ -1,94 +0,0 @@ -# Pass 2: Test Coverage — A10 LibOrder - -**File:** src/lib/LibOrder.sol - -## Evidence of Reading - -**Source file:** `src/lib/LibOrder.sol` (19 lines) - -### Imports -- `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5) - -### Library: `LibOrder` (lines 10-19) - -| Item | Kind | Line | Details | -|------|------|------|---------| -| `hash(OrderV4 memory order)` | function | 16-18 | `internal pure`, returns `keccak256(abi.encode(order))` | - -### Types / Errors / Constants / Events -None defined. - -### External Dependency: `OrderV4` struct -```solidity -struct OrderV4 { - address owner; - EvaluableV4 evaluable; - IOV2[] validInputs; - IOV2[] validOutputs; - bytes32 nonce; -} -``` - -### Usage in Production Code -`LibOrder.hash` is used via `using LibOrder for OrderV4` in `OrderBookV6.sol` (line 194) at the following call sites: -- `addOrder2` (line 346) — determines the order hash stored in `sOrders` -- `removeOrder2` (line 386) — looks up order liveness via hash -- `quote2` (line 411) — checks order liveness -- `takeOrders3` (line 484) — checks order liveness during takes -- `clear3` (lines 623, 624, 627, 628) — checks liveness for both alice and bob orders -- `_calculateOrderIO` (line 706) — computes hash for context - -This function is security-critical: it is the sole mechanism by which orders are identified in state mappings. - ---- - -**Test file:** `test/lib/LibOrder.t.sol` (23 lines) - -### Contract: `LibOrderTest is Test` - -| Test | Line | Kind | Description | -|------|------|------|-------------| -| `testHashEqual(OrderV4 memory a)` | 14-16 | Fuzz (100 runs) | Asserts `hash(a) == hash(a)` — determinism | -| `testHashNotEqual(OrderV4 memory a, OrderV4 memory b)` | 20-22 | Fuzz (100 runs) | Asserts `hash(a) != hash(b)` — distinctness | - -## Findings - -### A10-1: `testHashNotEqual` missing `vm.assume` guard for equal inputs (LOW) - -**Severity:** LOW - -The fuzz test `testHashNotEqual` (line 20-22) asserts that `LibOrder.hash(a) != LibOrder.hash(b)` for any two fuzzed `OrderV4` values, but never ensures `a` and `b` are actually different. If the fuzzer generates `a == b`, the assertion would fail because equal inputs must produce equal hashes. - -In practice, with a complex struct containing two dynamic arrays and only 100 fuzz runs, the probability of identical inputs is negligible. However: -1. The test's logical contract is incorrect — it claims to test distinctness but does not enforce distinct inputs. -2. Increasing fuzz runs or changing the fuzzer seed could trigger a spurious failure. -3. It gives a false sense of coverage for collision resistance since input distinctness is never validated. - -**Fix:** Add `vm.assume(keccak256(abi.encode(a)) != keccak256(abi.encode(b)))` before the assertion. - -### A10-2: No known-value regression test for hash output (INFO) - -**Severity:** INFO - -There is no test that computes the hash for a specific hardcoded `OrderV4` and asserts it against a known `bytes32` constant. Such a test would detect accidental changes to the encoding scheme (e.g., if `abi.encode` were inadvertently changed to `abi.encodePacked`). - -### A10-3: No single-field-delta tests (INFO) - -**Severity:** INFO - -No tests verify that changing exactly one field of an `OrderV4` (e.g., only `nonce`, only `owner`) produces a different hash. While `abi.encode` is injective for distinct struct values, explicit per-field tests would provide targeted regression coverage. - -### A10-4: No empty-array edge case test (INFO) - -**Severity:** INFO - -No test explicitly covers orders where `validInputs` and/or `validOutputs` are empty arrays. `abi.encode` handles empty dynamic arrays correctly, but an explicit test would document this assumption and guard against regressions. - -## Findings Summary - -| ID | Severity | Title | -|----|----------|-------| -| A10-1 | LOW | `testHashNotEqual` missing `vm.assume` guard for equal inputs | -| A10-2 | INFO | No known-value regression test for hash output | -| A10-3 | INFO | No single-field-delta tests | -| A10-4 | INFO | No empty-array edge case test | diff --git a/audit/2026-03-14-01/pass2/A11-LibOrderBook.md b/audit/2026-03-14-01/pass2/A11-LibOrderBook.md deleted file mode 100644 index bfaa8a71a4..0000000000 --- a/audit/2026-03-14-01/pass2/A11-LibOrderBook.md +++ /dev/null @@ -1,43 +0,0 @@ -# A11: LibOrderBook.sol -- Test Coverage Audit - -## Source File -`src/lib/LibOrderBook.sol` - -## Evidence of Thorough Reading - -### Constants (lines 22-106) -- `CALLING_CONTEXT_COLUMNS = 4` -- `CONTEXT_COLUMNS = CALLING_CONTEXT_COLUMNS + 1` (= 5) -- `CONTEXT_COLUMNS_EXTENDED = CONTEXT_COLUMNS + 2 + 1 + 1` (= 9) -- Context column constants: `CONTEXT_CALLING_CONTEXT_COLUMN = 1`, `CONTEXT_CALCULATIONS_COLUMN = 2`, `CONTEXT_VAULT_INPUTS_COLUMN = 3`, `CONTEXT_VAULT_OUTPUTS_COLUMN = 4`, `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN = 5`, `CONTEXT_SIGNED_CONTEXT_START_COLUMN = 6` -- Row constants for calling context (order hash, owner, counterparty), deposit context, withdraw context, calculations, vault IO, signed context - -### Library Functions -- `doPost(bytes32[][] memory context, TaskV2[] memory post)` (lines 111-138): - - Computes namespace from `msg.sender` - - Qualifies namespace with `address(this)` - - Iterates over `post` tasks - - Skips tasks with empty bytecode (`task.evaluable.bytecode.length > 0` check at line 119) - - Evaluates via `eval4` with empty inputs and empty state overlay - - Calls `store.set(namespace, writes)` only if `writes.length > 0` (line 133) - -## Test Files Found -- No direct unit test file for `LibOrderBook.doPost` -- Indirect coverage via `test/concrete/ob/OrderBookV6.deposit.entask.t.sol` (deposit4 -> doPost) -- Indirect coverage via `test/concrete/ob/OrderBookV6.withdraw.entask.t.sol` (withdraw4 -> doPost) -- Indirect coverage via `test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol` (finalizeArb -> doPost) -- Indirect coverage via `test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol` (finalizeArb -> doPost) - -## Coverage Gaps - -### GAP-A11-1: No direct unit test for `doPost` with empty `post` array -**Severity**: Low -**Details**: `doPost` is only tested indirectly through higher-level functions (deposit4, withdraw4, finalizeArb). There is no direct test that calls `doPost` with an empty `post` array (`post.length == 0`) to verify it is a no-op. The deposit/withdraw entask tests pass `new bytes[](0)` for eval strings, but those don't create tasks -- they pass an empty `TaskV2[]` directly to the orderbook which may or may not call `doPost` at all. - -### GAP-A11-2: No test for `doPost` skipping tasks with empty bytecode -**Severity**: Low -**Details**: The function has an explicit `if (task.evaluable.bytecode.length > 0)` guard at line 119. There is no test that passes a task with zero-length bytecode to verify it is silently skipped. The deposit/withdraw entask tests always pass either no tasks or tasks with valid bytecode. - -### GAP-A11-3: No test for `doPost` store.set path when writes are empty -**Severity**: Low -**Details**: Line 133 checks `if (writes.length > 0)` before calling `store.set`. While the stateless eval tests (e.g., `testOrderBookDepositEnactOneStateless` with `"_:1;"`) do exercise the case where writes are empty, there is no assertion verifying that `store.set` is NOT called. The test only checks read/write counts on the store address, which is an indirect verification. diff --git a/audit/2026-03-14-01/pass2/A12-LibOrderBookArb.md b/audit/2026-03-14-01/pass2/A12-LibOrderBookArb.md deleted file mode 100644 index ccf9b3986a..0000000000 --- a/audit/2026-03-14-01/pass2/A12-LibOrderBookArb.md +++ /dev/null @@ -1,36 +0,0 @@ -# A12: LibOrderBookArb.sol -- Test Coverage Audit - -## Source File -`src/lib/LibOrderBookArb.sol` - -## Evidence of Thorough Reading - -### Function: `finalizeArb` (lines 20-75) -- Takes `task`, `ordersInputToken`, `inputDecimals`, `ordersOutputToken`, `outputDecimals` -- Creates a 1-column context array with 3 entries (input balance as Float, output balance as Float, gas balance as Float) -- Block 1 (lines 31-39): Gets input token balance, transfers if > 0, converts to Float via `fromFixedDecimalLossyPacked` -- Block 2 (lines 41-51): Gets output token balance, transfers if > 0, converts to Float via `fromFixedDecimalLossyPacked` -- Block 3 (lines 53-68): Gets native gas balance, sends via `Address.sendValue` if > 0, converts to Float via `packLossless` with exponent -18 -- Wraps task into a single-element `TaskV2[]` and calls `LibOrderBook.doPost(context, post)` - -## Test Files Found -- `test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol` -- 1 test: `testFinalizeArbTransfersInputTokenProfit` -- `test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol` -- 1 test: `testFinalizeArbSendsNativeGas` - -## Coverage Gaps - -### GAP-A12-1: No test for zero-balance token transfers (both tokens empty) -**Severity**: Low -**Details**: `finalizeArb` checks `if (inputBalance > 0)` and `if (outputBalance > 0)` before transferring. No test exercises the path where both token balances are zero after arb (i.e., the OB consumed everything). The existing `testFinalizeArbTransfersInputTokenProfit` test has 20e18 input token profit remaining and 0 output token remaining, but there is no explicit assertion that `safeTransfer` was NOT called for the output token with zero balance. - -### GAP-A12-2: No test for output token profit (only input token profit tested) -**Severity**: Medium -**Details**: `testFinalizeArbTransfersInputTokenProfit` only tests the case where the arber profits in the input token. There is no test where the arber has remaining output token balance that needs to be swept. While the code path is symmetric, the output token sweep at line 45 is untested with a nonzero balance. - -### GAP-A12-3: No test for post-arb task evaluation with context verification -**Severity**: Medium -**Details**: Both existing tests pass an empty task (zero-address interpreter, empty bytecode) so `doPost` is effectively a no-op. There is no test that verifies the context column passed to the post-arb task contains the correct Float-encoded balances (col[0] = input, col[1] = output, col[2] = gas). The context data is constructed but never verified by a test. - -### GAP-A12-4: No fuzz testing on finalizeArb -**Severity**: Low -**Details**: Both tests use fixed values (80e18, 100e18, 1 ether). There is no fuzz test covering different decimal values, edge-case amounts, or the interaction between `fromFixedDecimalLossyPacked` and `packLossless` with boundary values. diff --git a/audit/2026-03-14-01/pass2/A13-LibOrderBookSubParser.md b/audit/2026-03-14-01/pass2/A13-LibOrderBookSubParser.md deleted file mode 100644 index d254b7c162..0000000000 --- a/audit/2026-03-14-01/pass2/A13-LibOrderBookSubParser.md +++ /dev/null @@ -1,88 +0,0 @@ -# A13: LibOrderBookSubParser.sol -- Test Coverage Audit - -## Source File -`src/lib/LibOrderBookSubParser.sol` - -## Evidence of Thorough Reading - -### Constants (lines 49-96) -- `SUB_PARSER_WORD_PARSERS_LENGTH = 2`, `EXTERN_PARSE_META_BUILD_DEPTH = 1` -- Word constants for all context words: order-clearer, orderbook, order-hash, order-owner, order-counterparty, calculated-max-output, calculated-io-ratio, input-token, input-token-decimals, input-vault-id, input-vault-before, input-vault-increase, output-token, output-token-decimals, output-vault-id, output-vault-before, output-vault-decrease -- Deposit word constants: depositor, deposit-token, deposit-vault-id, deposit-vault-before, deposit-vault-after -- Withdraw word constants: withdrawer, withdraw-token, withdraw-vault-id, withdraw-vault-before, withdraw-vault-after, withdraw-target-amount -- Index constants for deposit words (0-4) and withdraw words (0-5) - -### Sub-parser functions (lines 101-399) -All `internal pure` functions returning `(bool, bytes memory, bytes32[] memory)`: -- `subParserSender` -> `CONTEXT_BASE_COLUMN, CONTEXT_BASE_ROW_SENDER` -- `subParserCallingContract` -> `CONTEXT_BASE_COLUMN, CONTEXT_BASE_ROW_CALLING_CONTRACT` -- `subParserOrderHash` -> `CONTEXT_CALLING_CONTEXT_COLUMN, CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` -- `subParserOrderOwner` -> `CONTEXT_CALLING_CONTEXT_COLUMN, CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` -- `subParserOrderCounterparty` -> `CONTEXT_CALLING_CONTEXT_COLUMN, CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` -- `subParserMaxOutput` -> `CONTEXT_CALCULATIONS_COLUMN, CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` -- `subParserIORatio` -> `CONTEXT_CALCULATIONS_COLUMN, CONTEXT_CALCULATIONS_ROW_IO_RATIO` -- `subParserInputToken` -> `CONTEXT_VAULT_INPUTS_COLUMN, CONTEXT_VAULT_IO_TOKEN` -- `subParserInputTokenDecimals` -> `CONTEXT_VAULT_INPUTS_COLUMN, CONTEXT_VAULT_IO_TOKEN_DECIMALS` -- `subParserInputVaultId` -> `CONTEXT_VAULT_INPUTS_COLUMN, CONTEXT_VAULT_IO_VAULT_ID` -- `subParserInputBalanceBefore` -> `CONTEXT_VAULT_INPUTS_COLUMN, CONTEXT_VAULT_IO_BALANCE_BEFORE` -- `subParserInputBalanceDiff` -> `CONTEXT_VAULT_INPUTS_COLUMN, CONTEXT_VAULT_IO_BALANCE_DIFF` -- `subParserOutputToken` -> `CONTEXT_VAULT_OUTPUTS_COLUMN, CONTEXT_VAULT_IO_TOKEN` -- `subParserOutputTokenDecimals` -> `CONTEXT_VAULT_OUTPUTS_COLUMN, CONTEXT_VAULT_IO_TOKEN_DECIMALS` -- `subParserOutputVaultId` -> `CONTEXT_VAULT_OUTPUTS_COLUMN, CONTEXT_VAULT_IO_VAULT_ID` -- `subParserOutputBalanceBefore` -> `CONTEXT_VAULT_OUTPUTS_COLUMN, CONTEXT_VAULT_IO_BALANCE_BEFORE` -- `subParserOutputBalanceDiff` -> `CONTEXT_VAULT_OUTPUTS_COLUMN, CONTEXT_VAULT_IO_BALANCE_DIFF` -- `subParserSigners` -> `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN`, row from operand -- `subParserDepositToken` -> deposit token -- `subParserDepositVaultId` -> deposit vault id -- `subParserDepositVaultBalanceBefore` -> deposit vault before -- `subParserDepositVaultBalanceAfter` -> deposit vault after -- `subParserWithdrawToken` -> withdraw token -- `subParserWithdrawVaultId` -> withdraw vault id -- `subParserWithdrawVaultBalanceBefore` -> withdraw vault before -- `subParserWithdrawVaultBalanceAfter` -> withdraw vault after -- `subParserWithdrawTargetAmount` -> withdraw target amount -- `subParserSignedContext` -> column from low byte, row from next byte of operand - -### `authoringMetaV2()` (lines 406-632) -- Builds `AuthoringMetaV2[][]` for all context columns including base, calling, calculations, vault IO, signers, signed, deposit, withdraw -- Flattens via `LibUint256Matrix.flatten()` and ABI-encodes - -## Test Files Found - -### Order-clearing context words (each has its own test file via `OrderBookV6SubParserContextTest` abstract): -- `test/concrete/parser/OrderBookV6SubParser.contextOrderClearer.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderBook.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderHash.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderOwner.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOrderCounterparty.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextCalculatedMaxOutput.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextCalculatedIORatio.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputToken.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputTokenDecimals.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputVaultId.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceBefore.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputToken.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputTokenDecimals.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultId.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceBefore.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol` - -### Signed context and signers: -- `test/concrete/parser/OrderBookV6SubParser.signedContext.t.sol` -- `test/concrete/parser/OrderBookV6SubParser.signers.t.sol` - -### Pointers/meta: -- `test/concrete/parser/OrderBookV6SubParser.pointers.t.sol` (tests `authoringMetaV2()`) - -### Indirect coverage for deposit/withdraw words: -- `test/concrete/ob/OrderBookV6.deposit.entask.t.sol` (tests depositor, deposit-token, deposit-vault-id, deposit-vault-before, deposit-vault-after) -- `test/concrete/ob/OrderBookV6.withdraw.entask.t.sol` (tests withdrawer, withdraw-token, withdraw-vault-id, withdraw-vault-before, withdraw-vault-after, withdraw-target-amount) - -## Coverage Gaps - -### GAP-A13-1: No dedicated sub-parser unit tests for deposit/withdraw context words -**Severity**: Low -**Details**: Every order-clearing context word (order-clearer, orderbook, order-hash, etc.) has its own dedicated test file under `test/concrete/parser/` using the `OrderBookV6SubParserContextTest` abstract. The deposit words (depositor, deposit-token, deposit-vault-id, deposit-vault-before, deposit-vault-after) and withdraw words (withdrawer, withdraw-token, withdraw-vault-id, withdraw-vault-before, withdraw-vault-after, withdraw-target-amount) have NO corresponding sub-parser test files. They are only tested indirectly through integration tests in `OrderBookV6.deposit.entask.t.sol` and `OrderBookV6.withdraw.entask.t.sol`. The integration tests do verify correctness, but the gap in the pattern is notable -- a sub-parser regression would only be caught by full integration tests, not targeted unit tests. - -Note: The deposit/withdraw sub-parser functions use different context column mappings from the order-clearing words (they map to `CONTEXT_CALLING_CONTEXT_COLUMN` with deposit/withdraw row constants, but the context fixture `LibOrderBookSubParserContextFixture.hashedNamesContext()` does not include deposit/withdraw context columns). This means these words cannot be tested via the existing `OrderBookV6SubParserContextTest` pattern without extending the fixture. diff --git a/audit/2026-03-14-01/pass2/A14-LibOrderBookDeploy.md b/audit/2026-03-14-01/pass2/A14-LibOrderBookDeploy.md deleted file mode 100644 index e495e5a9cb..0000000000 --- a/audit/2026-03-14-01/pass2/A14-LibOrderBookDeploy.md +++ /dev/null @@ -1,90 +0,0 @@ -# Pass 2: Test Coverage -- A14 LibOrderBookDeploy - -**File:** src/lib/deploy/LibOrderBookDeploy.sol - -## Evidence of Reading - -### Imports (lines 5-21) -- `Vm` from forge-std -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6.pointers.sol` (aliased as `ORDERBOOK_HASH`, `ORDERBOOK_ADDR`, `ORDERBOOK_RUNTIME_CODE`) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6SubParser.pointers.sol` (aliased as `SUB_PARSER_HASH`, `SUB_PARSER_ADDR`, `SUB_PARSER_RUNTIME_CODE`) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `RouteProcessor4.pointers.sol` (aliased as `ROUTE_PROCESSOR_HASH`, `ROUTE_PROCESSOR_ADDR`, `ROUTE_PROCESSOR_RUNTIME_CODE`) - -### Library: `LibOrderBookDeploy` (lines 29-69) - -#### Constants (lines 32-52) -- `ORDERBOOK_DEPLOYED_ADDRESS` (line 32) = `ORDERBOOK_ADDR` -- `ORDERBOOK_DEPLOYED_CODEHASH` (line 36) = `ORDERBOOK_HASH` -- `SUB_PARSER_DEPLOYED_ADDRESS` (line 40) = `SUB_PARSER_ADDR` -- `SUB_PARSER_DEPLOYED_CODEHASH` (line 44) = `SUB_PARSER_HASH` -- `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` (line 48) = `ROUTE_PROCESSOR_ADDR` -- `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` (line 52) = `ROUTE_PROCESSOR_HASH` - -#### Function: `etchOrderBook(Vm vm)` (lines 58-68) -- `internal` function, takes the Forge `Vm` cheatcode interface -- Line 59: If `ORDERBOOK_DEPLOYED_CODEHASH != ORDERBOOK_DEPLOYED_ADDRESS.codehash`, etches `ORDERBOOK_RUNTIME_CODE` at `ORDERBOOK_DEPLOYED_ADDRESS` -- Line 62: If `SUB_PARSER_DEPLOYED_CODEHASH != SUB_PARSER_DEPLOYED_ADDRESS.codehash`, etches `SUB_PARSER_RUNTIME_CODE` at `SUB_PARSER_DEPLOYED_ADDRESS` -- Line 65: If `ROUTE_PROCESSOR_DEPLOYED_CODEHASH != ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash`, etches `ROUTE_PROCESSOR_RUNTIME_CODE` at `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` - -### No errors, events, or custom types defined in this file. - -## Test Files Reviewed - -### `test/lib/deploy/LibOrderBookDeploy.t.sol` (120 lines) -10 test functions in `LibOrderBookDeployTest`: -- `testDeployAddressOrderBook` (line 24): Deploys OrderBookV6 via Zoltu, asserts address and codehash match library constants -- `testDeployAddressSubParser` (line 36): Deploys SubParser via Zoltu, asserts address and codehash match library constants -- `testExpectedCodeHashOrderBook` (line 48): `new OrderBookV6()` codehash matches `ORDERBOOK_DEPLOYED_CODEHASH` -- `testExpectedCodeHashSubParser` (line 55): `new OrderBookV6SubParser()` codehash matches `SUB_PARSER_DEPLOYED_CODEHASH` -- `testCreationCodeOrderBook` (line 62): Precompiled creation code matches compiler output -- `testCreationCodeSubParser` (line 68): Precompiled creation code matches compiler output -- `testRuntimeCodeOrderBook` (line 74): Precompiled runtime code matches deployed bytecode -- `testRuntimeCodeSubParser` (line 81): Precompiled runtime code matches deployed bytecode -- `testGeneratedDeployedAddressOrderBook` (line 88): Generated address matches library constant -- `testGeneratedDeployedAddressSubParser` (line 94): Generated address matches library constant -- `testEtchOrderBook` (line 100): Calls `etchOrderBook`, asserts codehash for OrderBook and SubParser only -- `testEtchOrderBookIdempotent` (line 111): Double-calls `etchOrderBook`, asserts codehash for OrderBook and SubParser only - -### `test/lib/deploy/LibOrderBookDeployProd.t.sol` (52 lines) -5 fork tests in `LibOrderBookDeployProdTest`: -- `testProdDeployArbitrum` / `testProdDeployBase` / `testProdDeployBaseSepolia` / `testProdDeployFlare` / `testProdDeployPolygon` -- Each forks the network and calls `_checkAllContracts()` which verifies code.length > 0 and codehash for OrderBook and SubParser only - -### Indirect usage (not direct unit tests of this library) -- `test/util/abstract/ArbTest.sol`: Uses `LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS` to etch mock OB code -- `test/util/abstract/OrderBookV6ExternalMockTest.sol`: Calls `etchOrderBook(vm)` and uses `ORDERBOOK_DEPLOYED_ADDRESS` -- `test/util/abstract/OrderBookV6ExternalRealTest.sol`: Calls `etchOrderBook(vm)` and uses `ORDERBOOK_DEPLOYED_ADDRESS` and `SUB_PARSER_DEPLOYED_ADDRESS` -- `test/util/abstract/OrderBookV6SubParserContextTest.sol`: Calls `etchOrderBook(vm)` and uses `SUB_PARSER_DEPLOYED_ADDRESS` - -### Related test -- `test/lib/deploy/LibRouteProcessor4CreationCode.t.sol`: Tests that deploying `ROUTE_PROCESSOR_4_CREATION_CODE` yields the known Sushi codehash. Does NOT reference `LibOrderBookDeploy` or verify any of its RouteProcessor constants. - -## Findings - -### A14-1: RouteProcessor constants have no unit test coverage [MEDIUM] - -**Severity:** MEDIUM - -**Details:** `LibOrderBookDeploy` defines 3 pairs of address/codehash constants. The test file `LibOrderBookDeploy.t.sol` has comprehensive tests for OrderBook and SubParser constants (Zoltu deploy address, codehash, creation code, runtime code, generated address), but zero tests for the RouteProcessor pair: -- No test that `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` matches the generated `ROUTE_PROCESSOR_ADDR` -- No test that `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` matches the generated `ROUTE_PROCESSOR_HASH` -- No test that deploying RouteProcessor4 via Zoltu produces the expected address -- No test that the deployed runtime codehash matches `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` - -The existing `LibRouteProcessor4CreationCode.t.sol` test only verifies the creation code produces a known codehash via `create`. It does not test the Zoltu deploy path or verify any constant from `LibOrderBookDeploy`. - -If the generated pointer file for RouteProcessor4 were to drift or contain an error, no test would catch it. - -### A14-2: `etchOrderBook` RouteProcessor branch not verified [MEDIUM] - -**Severity:** MEDIUM - -**Details:** The `etchOrderBook` function (lines 58-68) etches 3 contracts. Both `testEtchOrderBook` and `testEtchOrderBookIdempotent` only assert the codehash of OrderBook and SubParser after calling `etchOrderBook`. Neither test asserts that `ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash == ROUTE_PROCESSOR_DEPLOYED_CODEHASH` after etching. The RouteProcessor etch path (lines 65-67) has zero test verification. - -This means a bug in the RouteProcessor etch logic (e.g., wrong runtime code, wrong address) would go undetected. - -### A14-3: Prod fork tests do not verify RouteProcessor deployment [LOW] - -**Severity:** LOW - -**Details:** `LibOrderBookDeployProd.t.sol` forks 5 networks and calls `_checkAllContracts()`, which only verifies OrderBook and SubParser are deployed with correct codehashes. It does not check whether RouteProcessor4 is deployed at `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` on any network. If the RouteProcessor were not deployed on a network where it is expected, no test would detect this. diff --git a/audit/2026-03-14-01/pass2/A15-LibRouteProcessor4CreationCode.md b/audit/2026-03-14-01/pass2/A15-LibRouteProcessor4CreationCode.md deleted file mode 100644 index c3964f4f5f..0000000000 --- a/audit/2026-03-14-01/pass2/A15-LibRouteProcessor4CreationCode.md +++ /dev/null @@ -1,41 +0,0 @@ -# Pass 2: Test Coverage — A15 LibRouteProcessor4CreationCode - -**File:** src/lib/deploy/LibRouteProcessor4CreationCode.sol - -## Evidence of Reading - -The source file is 14 lines of meaningful content (plus whitespace). It declares a single file-level constant: - -- **Line 13-14:** `bytes constant ROUTE_PROCESSOR_4_CREATION_CODE` — a large hex literal containing the exact creation bytecode for SushiSwap's RouteProcessor4 contract, including constructor args that encode `address(0)` for the bento and no owner. - -There are **no functions, no types, no errors, no events, no modifiers** in this file. It is purely a data-only file exporting a single constant. - -### Consumers - -The constant is imported and used in: -- `script/Deploy.sol` (line 24, 101) — for broadcasting the deployment via `LibRainDeploy.deployAndBroadcast` -- `script/BuildPointers.sol` (line 13, 86) — for building pointer files via `LibRainDeploy.deployZoltu` -- `test/lib/deploy/LibRouteProcessor4CreationCode.t.sol` — the dedicated test file - -### Test File: `test/lib/deploy/LibRouteProcessor4CreationCode.t.sol` - -Single test contract `LibRouteProcessor4CreationCodeTest` with one test: - -- **Line 19-27:** `testRouteProcessor4Codehash()` — Deploys the creation code via inline assembly `create`, asserts the deployed address is non-zero, and asserts the runtime codehash matches `KNOWN_ROUTE_PROCESSOR_4_CODEHASH` (`0xeb3745a...`). - -## Findings - -### A15-1: No finding — adequate test coverage for data-only file [INFO] - -**Severity:** INFO - -This file is a pure data constant (no logic, no branching, no error paths). The existing test is appropriate and sufficient: - -1. It verifies the creation code deploys successfully (non-zero address). -2. It verifies the deployed runtime bytecode hash matches the known SushiSwap RouteProcessor4 codehash from Ethereum mainnet. - -This is the correct and complete way to test a static bytecode constant — the codehash check is a single assertion that proves the entire blob is bit-for-bit correct against the canonical deployment. - -There are no untested functions, untested error paths, missing edge cases, or missing fuzz tests because there is no logic to test. The constant is either correct (matching the known hash) or it is not, and the test covers that. - -**No gaps identified. No fixes proposed.** diff --git a/audit/2026-03-14-01/pass2/SUMMARY.md b/audit/2026-03-14-01/pass2/SUMMARY.md deleted file mode 100644 index 89ae7928ed..0000000000 --- a/audit/2026-03-14-01/pass2/SUMMARY.md +++ /dev/null @@ -1,113 +0,0 @@ -# Pass 2 Summary -- Test Coverage - -**Audit namespace:** `audit/2026-03-14-01` -**Date:** 2026-03-14 - -## Scope - -| Agent | Source file | Lines | -|-------|-----------|-------| -| A01 | `src/abstract/OrderBookV6ArbCommon.sol` | 60 | -| A02 | `src/abstract/OrderBookV6ArbOrderTaker.sol` | 71 | -| A03 | `src/abstract/OrderBookV6FlashBorrower.sol` | 167 | -| A04 | `src/abstract/OrderBookV6FlashLender.sol` | 80 | -| A05 | `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` | 47 | -| A11 | `src/lib/LibOrderBook.sol` | 139 | -| A12 | `src/lib/LibOrderBookArb.sol` | 77 | -| A13 | `src/lib/LibOrderBookSubParser.sol` | 633 | -| A14 | `src/lib/deploy/LibOrderBookDeploy.sol` | 69 | -| A15 | `script/Deploy.sol` | 143 | - -## Findings - -| ID | Severity | File | Description | -|----|----------|------|-------------| -| GAP-A03-1 | Low | OrderBookV6FlashBorrower.sol | No reentrancy test for `arb4` (flash borrower path) | -| GAP-A05-1 | Low | GenericPoolOrderBookV6ArbOrderTaker.sol | No test asserting approval revocation in `onTakeOrders2` | -| GAP-A11-1 | Low | LibOrderBook.sol | No direct unit test for `doPost` with empty post array | -| GAP-A11-2 | Low | LibOrderBook.sol | No test for `doPost` skipping tasks with empty bytecode | -| GAP-A12-1 | Low | LibOrderBookArb.sol | No test for zero-balance token transfers path | -| GAP-A12-2 | Medium | LibOrderBookArb.sol | No test for output token profit sweep | -| GAP-A12-3 | Medium | LibOrderBookArb.sol | No test verifying post-arb task context values | -| GAP-A12-4 | Low | LibOrderBookArb.sol | No fuzz testing on finalizeArb | -| GAP-A13-1 | Low | LibOrderBookSubParser.sol | No dedicated sub-parser unit tests for deposit/withdraw context words | -| GAP-A14-1 | Medium | LibOrderBookDeploy.sol | RouteProcessor constants not tested in deploy tests | -| GAP-A14-2 | Medium | LibOrderBookDeploy.sol | `etchOrderBook` RouteProcessor branch not verified | -| GAP-A14-3 | Low | LibOrderBookDeploy.sol | Prod fork tests do not verify RouteProcessor deployment | -| GAP-A15-1 | Low | Deploy.sol | Deploy script has zero unit test coverage | - -## Details (A01-A05) - -### GAP-A03-1: No reentrancy test for arb4 - -`arb5` on `OrderBookV6ArbOrderTaker` has a dedicated reentrancy test that verifies `nonReentrant` blocks re-entry via `takeOrders4`. No equivalent test exists for `arb4` on `OrderBookV6FlashBorrower`, which has a different reentrancy vector (flash loan callback -> _exchange -> re-enter arb4). - -**Fix:** `.fixes/GAP-A03-1-FlashBorrowerReentrancy.t.sol` - -### GAP-A05-1: No approval revocation assertion for onTakeOrders2 - -The flash borrower path has `GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol` asserting spender allowance is zero after `_exchange`. The equivalent approve-call-revoke pattern in `GenericPoolOrderBookV6ArbOrderTaker.onTakeOrders2` lacks a dedicated assertion verifying allowance returns to zero. - -**Fix:** `.fixes/GAP-A05-1-OrderTakerApprovalRevoked.t.sol` - -## Details (A11-A15) - -### GAP-A11-1: No direct unit test for doPost with empty post array -`doPost` is only tested indirectly through deposit4, withdraw4, and finalizeArb. No test explicitly calls it with an empty `TaskV2[]` to verify the no-op path. - -### GAP-A11-2: No test for doPost skipping tasks with empty bytecode -Line 119 checks `task.evaluable.bytecode.length > 0` before evaluating. No test passes a task with zero-length bytecode to verify silent skipping. - -### GAP-A12-1: No test for zero-balance token transfers -No test exercises finalizeArb where both token balances are zero, verifying the `if (balance > 0)` guards prevent unnecessary transfer calls. - -### GAP-A12-2: No test for output token profit sweep -Only input token profit is tested. The output token transfer at line 45 of `LibOrderBookArb.sol` is not tested with a nonzero balance. - -**Fix:** `.fixes/GAP-A12-2-OutputTokenProfit.sol` - -### GAP-A12-3: No test verifying post-arb task context values -Both existing arb tests pass an empty task (zero-address interpreter), so the context column (Float-encoded input/output/gas balances) is never actually read or verified. - -**Fix:** `.fixes/GAP-A12-3-ArbContextVerification.sol` - -### GAP-A12-4: No fuzz testing on finalizeArb -Both tests use fixed values. No fuzz testing covers different decimals, amounts, or Float encoding edge cases. - -### GAP-A13-1: No dedicated sub-parser unit tests for deposit/withdraw words -All 17 order-clearing context words have dedicated `OrderBookV6SubParser.context*.t.sol` test files. The 11 deposit/withdraw words (depositor, deposit-token, deposit-vault-id, deposit-vault-before, deposit-vault-after, withdrawer, withdraw-token, withdraw-vault-id, withdraw-vault-before, withdraw-vault-after, withdraw-target-amount) have no equivalent sub-parser unit tests. They are covered indirectly by integration tests in `OrderBookV6.deposit.entask.t.sol` and `OrderBookV6.withdraw.entask.t.sol`. - -### GAP-A14-1: RouteProcessor constants not tested -`LibOrderBookDeploy.t.sol` tests address/codehash constants for OrderBook and SubParser but not for RouteProcessor. No test verifies `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` or `ROUTE_PROCESSOR_DEPLOYED_CODEHASH`. - -**Fix:** `.fixes/GAP-A14-1-RouteProcessorDeployTest.sol` - -### GAP-A14-2: etchOrderBook RouteProcessor branch not verified -`testEtchOrderBook` and `testEtchOrderBookIdempotent` assert codehashes for OrderBook and SubParser after etching, but not for RouteProcessor. The RouteProcessor etch at lines 65-67 is unverified. - -**Fix:** `.fixes/GAP-A14-1-RouteProcessorDeployTest.sol` (same file, includes etch test) - -### GAP-A14-3: Prod fork tests skip RouteProcessor -`LibOrderBookDeployProd.t.sol` forks 5 networks and checks OrderBook + SubParser deployments. RouteProcessor is not checked on any network. - -**Fix:** `.fixes/GAP-A14-3-ProdRouteProcessor.sol` - -### GAP-A15-1: Deploy script has zero test coverage -`script/Deploy.sol` has no unit tests. This is common for Foundry deploy scripts and is mitigated by CI dry-run workflows. No fix proposed -- CI integration testing is the appropriate coverage mechanism. - -## Overall Assessment - -### A11 (LibOrderBook.sol) -`doPost` has solid indirect coverage through deposit, withdraw, and arb entask tests. The gaps are low severity -- edge-case paths (empty array, empty bytecode) are not directly tested but are exercised by the broader test suite's use of empty task arrays. - -### A12 (LibOrderBookArb.sol) -`finalizeArb` has two targeted tests but they are narrow. The medium-severity gaps (output token profit and context verification) represent genuinely untested code paths. The output token `safeTransfer` path with nonzero balance is never exercised, and the Float context construction is never verified by a reading task. - -### A13 (LibOrderBookSubParser.sol) -Excellent coverage for order-clearing context words (17/17 have dedicated tests). The deposit/withdraw words are covered by integration tests but lack the fine-grained sub-parser unit testing pattern used for all other words. The `authoringMetaV2()` function is tested via the pointers test. - -### A14 (LibOrderBookDeploy.sol) -Strong coverage for OrderBook and SubParser constants/etch. The RouteProcessor is a consistent blind spot -- its constants, etch behavior, and prod deployment are all untested. This is the most actionable finding in this batch. - -### A15 (Deploy.sol) -No unit tests, but this is expected for a Foundry deploy script. CI dry-runs provide the coverage. diff --git a/audit/2026-03-14-01/pass3/A01-OrderBookV6ArbCommon.md b/audit/2026-03-14-01/pass3/A01-OrderBookV6ArbCommon.md deleted file mode 100644 index 8fa56fa66a..0000000000 --- a/audit/2026-03-14-01/pass3/A01-OrderBookV6ArbCommon.md +++ /dev/null @@ -1,66 +0,0 @@ -# Pass 3: Documentation -- A01 OrderBookV6ArbCommon - -**File:** `src/abstract/OrderBookV6ArbCommon.sol` - -## Evidence of Reading - -**Structs:** -- `OrderBookV6ArbConfig` (line 13): fields `task`, `implementationData` - -**Errors:** -- `WrongTask()` (line 19) - -**Constants:** -- `BEFORE_ARB_SOURCE_INDEX` (line 23): `SourceIndexV2.wrap(0)` - -**Contract:** `OrderBookV6ArbCommon` (abstract, line 29) - -**State variables:** -- `iTaskHash` (line 39): `bytes32 public immutable`, default `0` - -**Functions/modifiers:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 42) -- `modifier onlyValidTask(TaskV2 memory task)` (line 54) - -**Events:** -- `Construct(address sender, OrderBookV6ArbConfig config)` (line 35) - -## Findings - -### A01-1: Unused constant `BEFORE_ARB_SOURCE_INDEX` is documented but never referenced [INFO] - -**Lines:** 21-23 - -The constant `BEFORE_ARB_SOURCE_INDEX` at line 23 has a `@dev` doc comment explaining it is "evaluated before the arb is executed" for "access control to the arb." However, this constant is never referenced anywhere within `OrderBookV6ArbCommon.sol` or its direct inheritors (`OrderBookV6ArbOrderTaker.sol`, `OrderBookV6FlashBorrower.sol`). The doc comment describes a purpose that is not implemented in this codebase. This is a documentation accuracy concern: the comment implies runtime behavior that does not exist in these contracts. - -**Severity:** INFO - -No fix needed -- the constant may be consumed by external tooling or downstream contracts outside this repository. - -### A01-2: `OrderBookV6ArbConfig.implementationData` field lacks usage documentation [INFO] - -**Lines:** 11-12 - -The `@param implementationData` doc says "The constructor data for the specific implementation of the arb contract" but the field is never read in `OrderBookV6ArbCommon`'s constructor (only `config.task` is used). The struct doc does not explain that `implementationData` is consumed by inheriting constructors, which could confuse readers. - -**Severity:** INFO - -No fix proposed -- the comment is technically accurate (it is "for the specific implementation"), just could be clearer. - -### A01-3: All public/external items are documented [INFO] - -Every public-facing declaration has NatSpec documentation: - -| Item | Has Doc | Doc Quality | -|------|---------|-------------| -| `OrderBookV6ArbConfig` struct | Yes (`@param` for both fields) | Adequate | -| `WrongTask` error | Yes (line 18) | Adequate | -| `BEFORE_ARB_SOURCE_INDEX` constant | Yes (`@dev`, line 21-22) | See A01-1 | -| `Construct` event | Yes (`@notice`, `@param` x2, lines 32-34) | Good | -| `iTaskHash` state variable | Yes (`@notice`, line 37-38) | Good | -| `constructor` | Yes (`@param`, line 41) | Minimal but adequate | -| `onlyValidTask` modifier | Yes (`@notice`, lines 51-53) | Good -- describes revert condition and pass-through | - -No undocumented public functions or types. - -**Severity:** INFO diff --git a/audit/2026-03-14-01/pass3/A02-OrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass3/A02-OrderBookV6ArbOrderTaker.md deleted file mode 100644 index e51a975e8b..0000000000 --- a/audit/2026-03-14-01/pass3/A02-OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,56 +0,0 @@ -# Pass 3: Documentation -- A02 OrderBookV6ArbOrderTaker - -**File:** `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence of Reading - -**Contract:** `OrderBookV6ArbOrderTaker` (abstract, line 20) -- Inherits: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 29) -- `supportsInterface(bytes4 interfaceId) public view virtual override returns (bool)` (line 32) -- `arb5(IRaindexV6 orderBook, TakeOrdersConfigV5 calldata takeOrders, TaskV2 calldata task) external payable` (line 38) -- `onTakeOrders2(address, address, Float, Float, bytes calldata) public virtual override` (line 70) - -**No local errors, events, or constants** (inherited from parent). - -## Findings - -### A02-1: Constructor has no NatSpec documentation [LOW] - -**Lines:** 29 - -The constructor at line 29 has no documentation at all. While it simply delegates to `OrderBookV6ArbCommon(config)`, it is a public API entry point for deployers and should at minimum have a `@param` tag or a note that it delegates to the parent constructor. - -**Severity:** LOW - -### A02-2: `onTakeOrders2` parameter names are elided [LOW] - -**Lines:** 70 - -The function signature at line 70 uses unnamed parameters: `(address, address, Float, Float, bytes calldata)`. While the `@inheritdoc IRaindexV6OrderTaker` tag and the `@dev` comment explain the no-op rationale, the unnamed parameters make it harder for readers to understand the function without consulting the interface. Solidity allows naming parameters even in no-op implementations, and the interface (`IRaindexV6OrderTaker`) documents them as `inputToken`, `outputToken`, `inputAmountSent`, `totalOutputAmount`, `takeOrdersData`. - -**Severity:** LOW - -### A02-3: `arb5` relies solely on `@inheritdoc` with no local documentation of implementation details [INFO] - -**Lines:** 37-64 - -The `arb5` function at line 38 uses `@inheritdoc IRaindexV6ArbOrderTaker` which provides interface-level documentation. However, the implementation contains significant logic (zero-order guard, token extraction from order arrays, approval/revocation pattern, calling `finalizeArb`) that is not documented via inline NatSpec or `@dev` comments. The interface doc says "Implementations MUST validate that `raindex` is a trusted contract" but the implementation does no such validation -- it trusts whatever `orderBook` is passed. This is an accuracy concern between the interface doc and the implementation. - -**Severity:** INFO - -The interface caveat about trusting `raindex` is a SHOULD/MUST for implementers. The design decision to not validate is intentional (the contract holds no value between operations). The existing `@dev` comment on `onTakeOrders2` explains this rationale, but `arb5` itself does not. - -### A02-4: Documentation completeness summary [INFO] - -| Item | Has Doc | Doc Quality | -|------|---------|-------------| -| Contract-level `@title`/`@notice` | Yes (lines 16-19) | Good | -| `constructor` | No | **Missing** (A02-1) | -| `supportsInterface` | Yes (`@inheritdoc IERC165`) | Adequate via inheritance | -| `arb5` | Yes (`@inheritdoc IRaindexV6ArbOrderTaker`) | Adequate via inheritance, see A02-3 | -| `onTakeOrders2` | Yes (`@inheritdoc` + `@dev`) | Good rationale, unnamed params (A02-2) | - -**Severity:** INFO diff --git a/audit/2026-03-14-01/pass3/A03-OrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass3/A03-OrderBookV6FlashBorrower.md deleted file mode 100644 index 8969e1a1cd..0000000000 --- a/audit/2026-03-14-01/pass3/A03-OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,77 +0,0 @@ -# Pass 3: Documentation -- A03 OrderBookV6FlashBorrower - -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence of Reading - -**Errors:** -- `BadInitiator(address badInitiator)` (line 20) -- `BadLender(address badLender)` (line 25) -- `FlashLoanFailed()` (line 28) - -**Contract:** `OrderBookV6FlashBorrower` (abstract, line 60) -- Inherits: `IERC3156FlashBorrower`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -**Functions:** -- `constructor(OrderBookV6ArbConfig memory config)` (line 63) -- `supportsInterface(bytes4 interfaceId) public view virtual override returns (bool)` (line 66) -- `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData) internal virtual` (line 79) -- `onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data) external returns (bytes32)` (line 82) -- `arb4(IRaindexV6 orderBook, TakeOrdersConfigV5 calldata takeOrders, bytes calldata exchangeData, TaskV2 calldata task) external payable` (line 129) - -## Findings - -### A03-1: Constructor has no NatSpec documentation [LOW] - -**Lines:** 63 - -The constructor at line 63 has no documentation. Same pattern as A02-1 -- it delegates to `OrderBookV6ArbCommon(config)` but provides no `@param` tag. - -**Severity:** LOW - -### A03-2: `onFlashLoan` parameter names are partially elided [LOW] - -**Lines:** 82 - -The function signature at line 82 is: -```solidity -function onFlashLoan(address initiator, address, uint256, uint256, bytes calldata data) external returns (bytes32) -``` - -Three parameters are unnamed: the second (`token`), third (`amount`), and fourth (`fee`). The `@inheritdoc IERC3156FlashBorrower` tag provides interface-level docs, but the unnamed parameters make the implementation harder to read in isolation. The ERC-3156 interface documents these as `token`, `amount`, and `fee`. Since `token` and `amount` are conceptually important to understanding the flash loan flow (even if unused in the body), naming them would improve readability. - -**Severity:** LOW - -### A03-3: `_exchange` hook documentation does not use NatSpec tags properly [LOW] - -**Lines:** 70-79 - -The `_exchange` function at line 79 has a plain comment block (lines 70-77) but does not use the `@notice` or `@dev` NatSpec tag prefix. The `@param` tags on lines 76-77 are present but the leading description text is a regular comment without `///` + NatSpec tag structure. Looking more carefully: the comments do use `///` (NatSpec-style) but the leading description lacks a `@notice` or `@dev` tag. NatSpec will treat the first untagged `///` block as the `@notice`, so this technically works, but it is inconsistent with the rest of the file which uses explicit tags. - -Actually, re-reading: lines 70-77 all use `///` prefix, which means the untagged text becomes the implicit `@notice`. The `@param` tags are correctly placed. This is valid NatSpec. However, the documentation does not describe the return value (there is none -- it is void), which is correct. - -**Severity:** LOW -- the missing explicit `@notice` or `@dev` tag is a minor style inconsistency. - -### A03-4: `FlashLoanFailed` error documentation is minimal [INFO] - -**Lines:** 27-28 - -The error `FlashLoanFailed()` at line 28 has a one-line doc: "Thrown when the flash loan fails somehow." The word "somehow" is vague. The only place this error is used is line 160, where it reverts if `orderBook.flashLoan(...)` returns `false`. The doc could be more precise: "Thrown when the orderbook's `flashLoan` call returns `false`." - -**Severity:** INFO - -### A03-5: Documentation completeness summary [INFO] - -| Item | Has Doc | Doc Quality | -|------|---------|-------------| -| Contract-level `@title`/`@notice` | Yes (lines 30-59) | Excellent -- detailed example with numbers | -| `BadInitiator` error | Yes (lines 18-19) | Good, includes `@param` | -| `BadLender` error | Yes (lines 22-24) | Good, includes `@param` | -| `FlashLoanFailed` error | Yes (line 27) | Vague (A03-4) | -| `constructor` | No | **Missing** (A03-1) | -| `supportsInterface` | Yes (`@inheritdoc IERC165`) | Adequate via inheritance | -| `_exchange` | Yes (lines 70-78) | Good -- describes purpose, has `@param` tags | -| `onFlashLoan` | Yes (`@inheritdoc IERC3156FlashBorrower`) | Adequate via inheritance, unnamed params (A03-2) | -| `arb4` | Yes (lines 110-128) | Good -- describes flow, all `@param` tags present | - -**Severity:** INFO diff --git a/audit/2026-03-14-01/pass3/A04-OrderBookV6FlashLender.md b/audit/2026-03-14-01/pass3/A04-OrderBookV6FlashLender.md deleted file mode 100644 index 890b9d53cd..0000000000 --- a/audit/2026-03-14-01/pass3/A04-OrderBookV6FlashLender.md +++ /dev/null @@ -1,49 +0,0 @@ -# Pass 3: Documentation — A04 OrderBookV6FlashLender - -**File:** `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence of Reading - -**Contract:** `OrderBookV6FlashLender` (abstract), lines 29-80 -- Inherits: `IERC3156FlashLender`, `ERC165` -- Uses: `SafeERC20 for IERC20` - -**Error (file-level):** -- `FlashLenderCallbackFailed(bytes32 result)` — line 18 - -**Constant (file-level):** -- `FLASH_FEE` = 0 — line 23 - -**Functions:** -1. `supportsInterface(bytes4 interfaceId)` — line 33, public view virtual override, returns bool -2. `flashLoan(IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data)` — line 38, external override, returns bool -3. `flashFee(address, uint256)` — line 70, external pure override, returns uint256 -4. `maxFlashLoan(address token)` — line 77, external view override, returns uint256 - -## Findings - -### A04-1 [INFO] — `flashFee` parameters are unnamed - -**Location:** Line 70 - -`flashFee` has unnamed parameters (`address, uint256`). While the function ignores both (fee is always zero), the interface (`IERC3156FlashLender`) documents them as `token` and `amount`. The `@inheritdoc` tag pulls the interface docs, so the NatSpec is technically inherited. However, naming the parameters in the implementation improves readability for anyone reading the source directly. - -**Recommendation:** Name the parameters to match the interface (`address token, uint256 amount`) even though they are unused, or add an explicit comment explaining why they are omitted. This is purely informational; the `@inheritdoc` already provides documentation. - -### A04-2 [INFO] — `supportsInterface` has no standalone documentation - -**Location:** Line 33 - -The function uses `@inheritdoc IERC165` which pulls the generic ERC165 description. It does not document that this override also advertises `IERC3156FlashLender` support. A reader must read the implementation to discover which interface IDs are supported. - -**Recommendation:** Add a brief doc comment noting the additional interface advertised, e.g.: -```solidity -/// @inheritdoc IERC165 -/// @dev Also returns true for `type(IERC3156FlashLender).interfaceId`. -``` - -### A04-3 [INFO] — All public functions have documentation via `@inheritdoc` - -All four public/external functions use `@inheritdoc` to inherit NatSpec from their respective interfaces (`IERC165`, `IERC3156FlashLender`). The interface documentation in `IERC3156FlashLender` describes parameters (`token`, `amount`, `receiver`, `data`) and return values. The file-level `FlashLenderCallbackFailed` error and `FLASH_FEE` constant both have doc comments. The `maxFlashLoan` function additionally has a custom comment (line 74-75) explaining the orderbook-specific behaviour. Documentation is complete and accurate relative to the implementation. - -No LOW or higher findings. No fixes needed. diff --git a/audit/2026-03-14-01/pass3/A05-GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass3/A05-GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 1606eaa5ad..0000000000 --- a/audit/2026-03-14-01/pass3/A05-GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,56 +0,0 @@ -# Pass 3: Documentation — A05 GenericPoolOrderBookV6ArbOrderTaker - -**File:** `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` - -## Evidence of Reading - -**Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (concrete), lines 14-47 -- Inherits: `OrderBookV6ArbOrderTaker` -- Uses: `SafeERC20 for IERC20`, `Address for address` - -**Functions/specials:** -1. `constructor(OrderBookV6ArbConfig memory config)` — line 18 -2. `onTakeOrders2(address inputToken, address outputToken, Float inputAmountSent, Float totalOutputAmount, bytes calldata takeOrdersData)` — line 21, public virtual override -3. `receive()` — line 45, external payable -4. `fallback()` — line 46, external payable - -## Findings - -### A05-1 [LOW] — Constructor has no NatSpec documentation - -**Location:** Line 18 - -The constructor takes an `OrderBookV6ArbConfig memory config` parameter but has no `@param` or `@dev` documentation. While the parent constructor is documented (via `OrderBookV6ArbCommon`), this concrete constructor does not use `@inheritdoc` and provides no description of what `config` should contain or how it is used. Users deploying this contract need to know what to pass. - -**Recommendation:** Add NatSpec to the constructor: -```solidity -/// @param config The arb configuration. See `OrderBookV6ArbConfig` for details. -constructor(OrderBookV6ArbConfig memory config) OrderBookV6ArbOrderTaker(config) {} -``` - -### A05-2 [LOW] — `onTakeOrders2` override lacks parameter documentation - -**Location:** Lines 21-41 - -The function uses `@inheritdoc OrderBookV6ArbOrderTaker`, which inherits from `IRaindexV6OrderTaker`. The interface documents the generic parameters well. However, this override completely changes the semantics: it decodes `takeOrdersData` as `(address spender, address pool, bytes encodedFunctionCall)` (line 29-30). This critical decoding format is documented only in the contract-level NatSpec (line 13: "The `takeOrdersData` is decoded as `(spender, pool, encodedFunctionCall)`") but not on the function itself. A reader looking at the function's NatSpec (via `@inheritdoc`) sees only the generic description "The data passed to `takeOrders` by the caller" for `takeOrdersData`. - -**Recommendation:** Add a `@dev` comment on the function documenting the expected encoding of `takeOrdersData`: -```solidity -/// @inheritdoc OrderBookV6ArbOrderTaker -/// @dev Decodes `takeOrdersData` as `(address spender, address pool, bytes encodedFunctionCall)`. -/// `spender` is approved for `type(uint256).max` of the input token before the pool call. -/// `pool` receives the `encodedFunctionCall` via `functionCallWithValue` with any ETH balance. -/// Approval is revoked after the call. -``` - -### A05-3 [INFO] — `receive()` and `fallback()` have adequate inline documentation - -**Location:** Lines 43-46 - -Both special functions have a shared comment (lines 43-44) explaining their purpose: allowing arbitrary calls and ETH transfers without reverting, with ETH swept by `finalizeArb`. This is sufficient for special functions which cannot carry NatSpec in the traditional sense. - -### A05-4 [INFO] — Contract-level NatSpec is present and accurate - -**Location:** Lines 11-13 - -The `@title` and `@notice` tags accurately describe the contract as an order-taker arb that swaps via an arbitrary external pool call, and documents the `takeOrdersData` encoding format. This is accurate relative to the implementation. diff --git a/audit/2026-03-14-01/pass3/A06-GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass3/A06-GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index d8b699b8b2..0000000000 --- a/audit/2026-03-14-01/pass3/A06-GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,68 +0,0 @@ -# Pass 3: Documentation — A06 GenericPoolOrderBookV6FlashBorrower - -**File:** `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` - -## Evidence of Reading - -**Contract:** `GenericPoolOrderBookV6FlashBorrower` (concrete), lines 26-53 -- Inherits: `OrderBookV6FlashBorrower` -- Uses: `SafeERC20 for IERC20`, `Address for address` - -**Functions/specials:** -1. `constructor(OrderBookV6ArbConfig memory config)` — line 30 -2. `_exchange(TakeOrdersConfigV5 memory takeOrders, bytes memory exchangeData)` — line 33, internal virtual override -3. `receive()` — line 51, external payable -4. `fallback()` — line 52, external payable - -## Findings - -### A06-1 [LOW] — Constructor has no NatSpec documentation - -**Location:** Line 30 - -The constructor takes an `OrderBookV6ArbConfig memory config` parameter but has no NatSpec documentation. The parent constructor (`OrderBookV6FlashBorrower` -> `OrderBookV6ArbCommon`) is documented with `@param config The arb config for this contract.` but this concrete constructor does not use `@inheritdoc` and provides no description. Users deploying this contract need to know what to pass. - -**Recommendation:** Add NatSpec to the constructor: -```solidity -/// @param config The arb configuration. See `OrderBookV6ArbConfig` for details. -constructor(OrderBookV6ArbConfig memory config) OrderBookV6FlashBorrower(config) {} -``` - -### A06-2 [LOW] — `_exchange` override lacks parameter documentation for `exchangeData` - -**Location:** Lines 33-47 - -The function uses `@inheritdoc OrderBookV6FlashBorrower`, which provides: "`_exchange` is responsible for converting the flash loaned assets into the assets required to fill the orders." and documents `takeOrders` and `exchangeData` as "As per `arb`." However, this concrete override decodes `exchangeData` as `(address spender, address pool, bytes encodedFunctionCall)` (line 34-35). This decoding format is documented at the contract level (lines 19-25) but not on the function itself. A reader looking only at the function's NatSpec gets no indication of the expected encoding. - -The parent abstract `_exchange` in `OrderBookV6FlashBorrower` says `exchangeData` is "As per `arb`", and the `arb4` function says it is "Arbitrary bytes that will be passed to `_exchange`... For example, `GenericPoolOrderBookV6FlashBorrower` uses this data as a literal encoded external call." This is backwards — the parent references the child as an example. The child itself should document its own encoding format directly. - -**Recommendation:** Add a `@dev` comment on the function documenting the expected encoding: -```solidity -/// @inheritdoc OrderBookV6FlashBorrower -/// @dev Decodes `exchangeData` as `(address spender, address pool, bytes encodedFunctionCall)`. -/// `spender` is approved for `type(uint256).max` of the borrowed token before the pool call. -/// `pool` receives the `encodedFunctionCall` via `functionCallWithValue` with any ETH balance. -/// Approval is revoked after the call. -``` - -### A06-3 [INFO] — Contract-level NatSpec is thorough and accurate - -**Location:** Lines 15-25 - -The `@title`, `@notice`, and `@dev` tags provide a detailed description of the contract, including how `exchangeData` is decoded and the role of the `spender` parameter. The documentation accurately describes: -- The contract implements `OrderBookV6FlashBorrower` for external liquidity sources -- `exchangeData` is decoded into `spender`, `pool`, and `callData` -- `callData` is the literal encoded function call to the pool -- `spender` is the address approved to spend the input token (usually the pool itself) - -This is accurate relative to the implementation. - -### A06-4 [INFO] — `receive()` and `fallback()` have adequate inline documentation - -**Location:** Lines 49-52 - -Both special functions have a shared comment (lines 49-50) explaining their purpose: allowing arbitrary calls and ETH transfers without reverting, with ETH swept by `finalizeArb`. This matches the identical pattern in `GenericPoolOrderBookV6ArbOrderTaker`. - -### A06-5 [INFO] — `_exchange` internal visibility means docs are for developer audience only - -The `_exchange` function is `internal`, so its documentation is relevant only to developers extending the contract, not to external callers. The contract-level NatSpec at lines 15-25 serves as the primary documentation for how callers should encode the `exchangeData` passed to `arb4`. This is an acceptable documentation strategy. diff --git a/audit/2026-03-14-01/pass3/A07-RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass3/A07-RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 8a6f2507b6..0000000000 --- a/audit/2026-03-14-01/pass3/A07-RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,64 +0,0 @@ -# Pass 3: Documentation — A07 RouteProcessorOrderBookV6ArbOrderTaker - -**File:** `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` - -## Evidence of Reading - -**Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (lines 15-56), inherits `OrderBookV6ArbOrderTaker`. - -### Public/External Functions and Methods -| # | Name | Visibility | Line | Has Doc Comment | -|---|------|-----------|------|-----------------| -| 1 | `constructor(OrderBookV6ArbConfig memory config)` | public | 21 | No | -| 2 | `onTakeOrders2(address, address, Float, Float, bytes calldata)` | public virtual override | 27 | Yes (`@inheritdoc`) | -| 3 | `receive()` | external payable | 54 | Partial (inline comment, no NatSpec) | -| 4 | `fallback()` | external payable | 55 | Partial (inline comment, no NatSpec) | - -### State Variables -| # | Name | Visibility | Line | Has Doc Comment | -|---|------|-----------|------|-----------------| -| 1 | `iRouteProcessor` | public immutable | 19 | Yes (`@dev`) | - -### Contract-Level Documentation -- `@title` present (line 13): "RouteProcessorOrderBookV6ArbOrderTaker" -- `@notice` present (line 14): "Order-taker arb that swaps via a Sushi RouteProcessor." - -### Imports (lines 4-11) -`IRouteProcessor`, `IERC20`, `SafeERC20`, `OrderBookV6ArbOrderTaker`, `OrderBookV6ArbConfig`, `Float`, `LibDecimalFloat`, `IERC20Metadata`. - -### Errors/Events/Constants -None defined in this file. - -## Findings - -### A07-1: Missing NatSpec on constructor (INFO) - -**Location:** Line 21 - -The constructor has no NatSpec documentation. It decodes `config.implementationData` as a single `address` (the route processor) but this is not documented anywhere in the contract. A reader must inspect the constructor body to understand the expected encoding. - -**Recommendation:** Add a `@param config` NatSpec tag explaining that `config.implementationData` must be ABI-encoded as `(address routeProcessor)`. - -### A07-2: Missing NatSpec on `receive()` and `fallback()` (INFO) - -**Location:** Lines 54-55 - -Both `receive()` and `fallback()` have an inline comment (line 52-53: "Allow arbitrary calls and ETH transfers to this contract without reverting. Any ETH received is swept to msg.sender by finalizeArb.") but this is not a NatSpec `///` or `/** */` comment attached to the functions via the standard pattern. The comment on lines 52-53 is a regular `///` comment that only attaches to `receive()` by proximity; `fallback()` on line 55 has no attached NatSpec at all. - -**Recommendation:** Add separate NatSpec `@dev` comments for both `receive()` and `fallback()`, or use a shared doc block that clearly covers both. - -### A07-3: `onTakeOrders2` uses `@inheritdoc` with no local parameter/behavior docs (INFO) - -**Location:** Line 26-50 - -The override uses `@inheritdoc OrderBookV6ArbOrderTaker`, which inherits from the base no-op implementation that has no parameter documentation itself (`IRaindexV6OrderTaker` defines the function signature). The actual behavior in this override is substantially different from the base no-op: it approves the route processor, decodes `takeOrdersData` as a route, converts float amounts to fixed decimal, calls `processRoute`, then revokes approval. None of this behavior is documented locally. - -**Recommendation:** Add a `@dev` comment describing the swap flow: approval, route decoding, lossy float-to-fixed conversion (with the rounding-up on output), route processor call, and approval revocation. - -### A07-4: Doc comment says "ETH received is swept to msg.sender by finalizeArb" but mechanism is not in this file (INFO) - -**Location:** Line 53 - -The comment references `finalizeArb` behavior that lives in the parent `OrderBookV6ArbCommon` (via `LibOrderBookArb.finalizeArb`). The statement that ETH is "swept to msg.sender" could be misleading since `finalizeArb` is called by `arb5` where `msg.sender` is the arb caller, not whoever sent ETH to the contract. This is not incorrect per se but could benefit from a cross-reference. - -**Recommendation:** Clarify the comment or add a `@dev` note pointing to `LibOrderBookArb.finalizeArb` for the sweep mechanism. diff --git a/audit/2026-03-14-01/pass3/A08-OrderBookV6.md b/audit/2026-03-14-01/pass3/A08-OrderBookV6.md deleted file mode 100644 index 9712eec53a..0000000000 --- a/audit/2026-03-14-01/pass3/A08-OrderBookV6.md +++ /dev/null @@ -1,176 +0,0 @@ -# Pass 3: Documentation — A08 OrderBookV6 - -**File:** `src/concrete/ob/OrderBookV6.sol` - -## Evidence of Reading - -**Contract:** `OrderBookV6` (lines 191-1062), inherits `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender`. - -### Public/External Functions and Methods -| # | Name | Visibility | Line | Has Doc Comment | -|---|------|-----------|------|-----------------| -| 1 | `vaultBalance2(address, address, bytes32)` | external view | 219 | Yes (`@inheritdoc IRaindexV6`) | -| 2 | `orderExists(bytes32)` | external view | 244 | Yes (`@inheritdoc IRaindexV6`) | -| 3 | `entask2(TaskV2[] calldata)` | external | 249 | Yes (`@inheritdoc IRaindexV6`) | -| 4 | `deposit4(address, bytes32, Float, TaskV2[] calldata)` | external | 254 | Yes (`@inheritdoc IRaindexV6`) | -| 5 | `withdraw4(address, bytes32, Float, TaskV2[] calldata)` | external | 289 | Yes (`@inheritdoc IRaindexV6`) | -| 6 | `addOrder4(OrderConfigV4 calldata, TaskV2[] calldata)` | external | 328 | Yes (`@inheritdoc IRaindexV6`) | -| 7 | `removeOrder3(OrderV4 calldata, TaskV2[] calldata)` | external | 378 | Yes (`@inheritdoc IRaindexV6`) | -| 8 | `quote2(QuoteV2 calldata)` | external view | 410 | Yes (`@inheritdoc IRaindexV6`) | -| 9 | `takeOrders4(TakeOrdersConfigV5 calldata)` | external | 433 | Yes (`@inheritdoc IRaindexV6`) | -| 10 | `clear3(OrderV4 memory, OrderV4 memory, ClearConfigV2 calldata, SignedContextV1[] memory, SignedContextV1[] memory)` | external | 593 | Yes (`@inheritdoc IRaindexV6`) | - -### Internal Functions -| # | Name | Visibility | Line | Has Doc Comment | -|---|------|-----------|------|-----------------| -| 11 | `_vaultBalance(address, address, bytes32)` | internal view | 226 | Yes (`@dev`) | -| 12 | `checkTokenSelfTrade(OrderV4 memory, uint256, uint256)` | internal pure | 403 | Yes (`@dev` inline) | -| 13 | `calculateOrderIO(OrderV4 memory, uint256, uint256, address, SignedContextV1[] memory)` | internal view | 698 | Yes (full NatSpec with `@param` tags) | -| 14 | `increaseVaultBalance(address, address, bytes32, Float)` | internal | 822 | Yes (`@dev`) | -| 15 | `decreaseVaultBalance(address, address, bytes32, Float)` | internal | 855 | Yes (`@dev`) | -| 16 | `recordVaultIO(Float, Float, OrderIOCalculationV4 memory)` | internal | 893 | Yes (partial: NatSpec `@param` tags) | -| 17 | `handleIO(OrderIOCalculationV4 memory)` | internal | 919 | Yes (`@dev`) | -| 18 | `calculateClearStateChange(OrderIOCalculationV4 memory, OrderIOCalculationV4 memory)` | internal pure | 971 | Yes (full NatSpec with `@param` and `@return`) | -| 19 | `calculateClearStateAlice(OrderIOCalculationV4 memory, OrderIOCalculationV4 memory)` | internal pure | 987 | Yes (`@dev`) | -| 20 | `pullTokens(address, address, Float)` | internal | 1008 | Yes (`@dev`) | -| 21 | `pushTokens(address, address, Float)` | internal | 1032 | Yes (`@dev`) | -| 22 | `_nonZeroVaultId(address, address, bytes32)` | internal pure | 1052 | Yes (`@dev`) | - -### Modifier -| # | Name | Line | Has Doc Comment | -|---|------|------|-----------------| -| 1 | `nonZeroVaultId(address, address, bytes32)` | 1058 | No | - -### State Variables -| # | Name | Visibility | Line | Has Doc Comment | -|---|------|-----------|------|-----------------| -| 1 | `sOrders` | internal | 208 | Yes (lines 199-205, multi-line comment) | -| 2 | `sVaultBalances` | internal | 215 | Yes (`@dev` on line 210) | - -### Contract-Level Documentation -- `@title` present (line 189): "OrderBookV6" -- Brief notice (line 190): "See `IRaindexV6` for more documentation." - -### Struct -| # | Name | Line | Has Doc Comment | -|---|------|------|-----------------| -| 1 | `OrderIOCalculationV4` | 178 | Yes (full field-level NatSpec, lines 152-187) | - -### Errors (lines 69-125) -| # | Name | Line | Has Doc Comment | -|---|------|------|-----------------| -| 1 | `ReentrancyGuardReentrantCall` | 69 | Yes (lines 67-68) | -| 2 | `NotOrderOwner(address)` | 73 | Yes (lines 71-72) | -| 3 | `TokenMismatch` | 76 | Yes (line 75) | -| 4 | `TokenSelfTrade` | 79 | Yes (line 78) | -| 5 | `TokenDecimalsMismatch` | 83 | Yes (lines 81-82) | -| 6 | `MinimumIO(Float, Float)` | 88 | Yes (lines 85-88) | -| 7 | `SameOwner` | 91 | Yes (line 90) | -| 8 | `UnsupportedCalculateInputs(uint256)` | 95 | Yes (lines 93-94) | -| 9 | `UnsupportedCalculateOutputs(uint256)` | 99 | Yes (lines 97-98) | -| 10 | `NegativeInput` | 102 | Yes (line 101) | -| 11 | `NegativeOutput` | 105 | Yes (line 104) | -| 12 | `NegativeVaultBalance(Float)` | 109 | Yes (lines 107-108) | -| 13 | `NegativeVaultBalanceChange(Float)` | 113 | Yes (lines 111-112) | -| 14 | `NegativePull` | 116 | Yes (line 115) | -| 15 | `NegativePush` | 119 | Yes (line 118) | -| 16 | `NegativeBounty` | 122 | Yes (line 121) | -| 17 | `ClearZeroAmount` | 125 | Yes (line 124) | - -### Constants (lines 127-150) -| # | Name | Line | Has Doc Comment | -|---|------|------|-----------------| -| 1 | `ORDER_LIVE` | 129 | Yes (`@dev`) | -| 2 | `ORDER_DEAD` | 134 | Yes (`@dev`) | -| 3 | `CALCULATE_ORDER_ENTRYPOINT` | 137 | Yes (`@dev`) | -| 4 | `HANDLE_IO_ENTRYPOINT` | 140 | Yes (`@dev`) | -| 5 | `CALCULATE_ORDER_MIN_OUTPUTS` | 143 | Yes (`@dev`) | -| 6 | `CALCULATE_ORDER_MAX_OUTPUTS` | 145 | Yes (`@dev`) | -| 7 | `HANDLE_IO_MIN_OUTPUTS` | 148 | Yes (`@dev`) | -| 8 | `HANDLE_IO_MAX_OUTPUTS` | 150 | Yes (`@dev`) | - -## Findings - -### A08-1: `recordVaultIO` doc comment truncated -- missing `@param` continuation (LOW) - -**Location:** Lines 887-893 - -The NatSpec for `recordVaultIO` reads: -``` -/// Given an order, final input and output amounts and the IO calculation -/// verbatim from `_calculateOrderIO`, dispatch the handle IO entrypoint if -/// it exists and update the order owner's vault balances. -/// @param input The input amount. -/// @param output The output amount. -/// @param orderIOCalculation The order IO calculation produced by -``` - -The `@param orderIOCalculation` tag ends with "produced by" and is truncated. The sentence is incomplete -- it should say something like "produced by `calculateOrderIO`." - -Additionally, the description says "dispatch the handle IO entrypoint if it exists" but `recordVaultIO` does NOT dispatch handle IO; it only records vault balance changes and emits `ContextV2`. The handle IO dispatch is done separately by `handleIO()`. This is a documentation accuracy error. - -**Recommendation:** Complete the truncated `@param` tag and correct the description to accurately reflect that `recordVaultIO` only updates vault balances and emits context, not dispatching handle IO. - -### A08-2: `nonZeroVaultId` modifier has no NatSpec (INFO) - -**Location:** Line 1058 - -The modifier `nonZeroVaultId` at line 1058 has no NatSpec. Its companion function `_nonZeroVaultId` at line 1052 has a `@dev` comment, but the modifier itself is undocumented. - -**Recommendation:** Add a `@dev` NatSpec tag on the modifier, or at minimum a comment indicating it delegates to `_nonZeroVaultId`. - -### A08-3: `checkTokenSelfTrade` documentation is a `@dev` inline only, no `@param` tags (INFO) - -**Location:** Lines 401-407 - -The function has a `@dev` tag explaining what it does ("Reverts with `TokenSelfTrade` if the input and output tokens are the same address.") but has no `@param` tags for its three parameters (`order`, `inputIOIndex`, `outputIOIndex`). - -**Recommendation:** Add `@param` tags for completeness. - -### A08-4: `calculateClearStateAlice` missing `@param` tags (INFO) - -**Location:** Lines 984-1003 - -The function has a `@dev` description ("Calculates Alice's input and output given both order calculations. Alice's output is capped by Bob's max output, and her input is derived from her IO ratio.") but no `@param` or `@return` tags for its parameters and return values. - -**Recommendation:** Add `@param` and `@return` tags. - -### A08-5: `handleIO` missing `@param` tag (INFO) - -**Location:** Lines 917-961 - -The function has a `@dev` description ("Persists interpreter state writes then evaluates the handle IO entrypoint for an order, if it has one.") but no `@param` tag for `orderIOCalculation`. - -**Recommendation:** Add a `@param orderIOCalculation` tag. - -### A08-6: Unused error `TokenDecimalsMismatch` (INFO) - -**Location:** Line 83 - -The error `TokenDecimalsMismatch` is declared with a comment ("Thrown when the input and output token decimals don't match, in either direction.") but is never used in `OrderBookV6.sol`. This may be a leftover from a previous version. - -**Recommendation:** Verify whether this error is used elsewhere in the codebase. If not, consider removing it. - -### A08-7: Unused errors `NegativeInput` and `NegativeOutput` (INFO) - -**Location:** Lines 102, 105 - -The errors `NegativeInput` and `NegativeOutput` are declared but never used in `OrderBookV6.sol`. The actual negative-amount checks use `NegativePull`, `NegativePush`, and `NegativeVaultBalanceChange` instead. - -**Recommendation:** Verify whether these errors are used elsewhere. If not, consider removing them. - -### A08-8: Unused error `UnsupportedCalculateInputs` (INFO) - -**Location:** Line 95 - -The error `UnsupportedCalculateInputs(uint256 inputs)` is declared and documented ("Thrown when calculate order expression wants inputs") but is never thrown in `OrderBookV6.sol`. The `calculateOrderIO` function passes `new StackItem[](0)` as inputs and only checks outputs via `UnsupportedCalculateOutputs`. - -**Recommendation:** Verify whether this error is used elsewhere. If not, consider removing it. - -### A08-9: Unused constant `CALCULATE_ORDER_MAX_OUTPUTS` (INFO) - -**Location:** Line 145 - -The constant `CALCULATE_ORDER_MAX_OUTPUTS` is declared and documented but never referenced in `OrderBookV6.sol`. Only `CALCULATE_ORDER_MIN_OUTPUTS` is used (line 785). - -**Recommendation:** Verify if used elsewhere; if not, consider removing. diff --git a/audit/2026-03-14-01/pass3/A09-OrderBookV6SubParser.md b/audit/2026-03-14-01/pass3/A09-OrderBookV6SubParser.md deleted file mode 100644 index 4f573eaa3a..0000000000 --- a/audit/2026-03-14-01/pass3/A09-OrderBookV6SubParser.md +++ /dev/null @@ -1,75 +0,0 @@ -# Pass 3: Documentation — A09 OrderBookV6SubParser - -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` - -## Evidence of Reading - -**Contract:** `OrderBookV6SubParser` (lines 69-301), inherits `BaseRainterpreterSubParser`. - -### Public/External Functions and Methods -| # | Name | Visibility | Line | Has Doc Comment | -|---|------|-----------|------|-----------------| -| 1 | `describedByMetaV1()` | external pure | 73 | Yes (`@inheritdoc IDescribedByMetaV1`) | -| 2 | `subParserParseMeta()` | internal pure virtual override | 78 | Yes (`@inheritdoc BaseRainterpreterSubParser`) | -| 3 | `subParserWordParsers()` | internal pure virtual override | 83 | Yes (`@inheritdoc BaseRainterpreterSubParser`) | -| 4 | `subParserOperandHandlers()` | internal pure virtual override | 88 | Yes (`@inheritdoc BaseRainterpreterSubParser`) | -| 5 | `buildLiteralParserFunctionPointers()` | external pure | 93 | Yes (`@inheritdoc IParserToolingV1`) | -| 6 | `buildOperandHandlerFunctionPointers()` | external pure | 98 | Yes (`@inheritdoc IParserToolingV1`) | -| 7 | `buildSubParserWordParsers()` | external pure | 183 | Partial (`@dev` only, no `@inheritdoc` or `@return`) | - -### State Variables -None. - -### Contract-Level Documentation -- No `@title` tag. -- No `@notice` tag. - -### Imports (lines 5-66) -- From `rain.interpreter`: `LibParseOperand`, `BaseRainterpreterSubParser`, `OperandV2`, `IParserToolingV1` -- From `rain.lib.typecast`: `LibConvert` -- From `rain.solmem`: `LibUint256Matrix` -- From `../../lib/LibOrderBookSubParser.sol`: `LibOrderBookSubParser`, `SUB_PARSER_WORD_PARSERS_LENGTH`, and all deposit/withdraw word constants -- From `../../lib/LibOrderBook.sol`: all `CONTEXT_*` constants -- From `../../generated/OrderBookV6SubParser.pointers.sol`: `DESCRIBED_BY_META_HASH`, `PARSE_META`, `SUB_PARSER_WORD_PARSERS`, `OPERAND_HANDLER_FUNCTION_POINTERS` -- From `rain.metadata`: `IDescribedByMetaV1` - -### Errors/Events/Constants -None defined in this file (all constants are imported). - -## Findings - -### A09-1: Missing contract-level NatSpec (`@title` and `@notice`) (LOW) - -**Location:** Line 69 - -`OrderBookV6SubParser` has no contract-level documentation at all. There is no `@title` or `@notice` explaining the contract's purpose as a sub-parser that makes orderbook context words (sender, order hash, vault balances, etc.) available to Rainlang expressions evaluated by the orderbook. - -**Recommendation:** Add `@title` and `@notice` NatSpec before the contract declaration explaining the contract's role in the orderbook ecosystem. - -### A09-2: `buildSubParserWordParsers` missing `@inheritdoc` or `@return` (LOW) - -**Location:** Lines 181-183 - -The function has a `@dev` comment ("Builds the packed word-parser function pointer table for all orderbook sub-parser words across every context column.") but: -- It does not use `@inheritdoc ISubParserToolingV1` even though it implements that interface. -- It has no `@return` tag describing the packed bytes format. - -The other two `build*` functions (lines 93, 98) correctly use `@inheritdoc IParserToolingV1`. - -**Recommendation:** Replace the `@dev` with `@inheritdoc ISubParserToolingV1` (optionally keeping the `@dev` as supplementary documentation). - -### A09-3: `buildOperandHandlerFunctionPointers` has no local documentation beyond `@inheritdoc` (INFO) - -**Location:** Lines 98-179 - -This is a large function (80 lines) that constructs operand handler arrays for 9 different context columns (base, calling context, calculations, vault inputs, vault outputs, signers, signed context, deposits, withdrawals). The `@inheritdoc IParserToolingV1` delegates to the interface which provides only a generic description. No local `@dev` explains the specific orderbook context column layout or the mapping between column indices and handler arrays. - -**Recommendation:** Add a `@dev` comment describing the context column layout and how each handler array maps to the orderbook's context structure. - -### A09-4: `buildSubParserWordParsers` has no local documentation for context column mapping (INFO) - -**Location:** Lines 183-300 - -Similar to `buildOperandHandlerFunctionPointers`, this function constructs parser arrays for 9 context columns but provides no documentation on the column structure or the mapping between parser functions and the words they handle. - -**Recommendation:** Add `@dev` documentation describing the context column layout and word mappings. diff --git a/audit/2026-03-14-01/pass3/A10-LibOrder.md b/audit/2026-03-14-01/pass3/A10-LibOrder.md deleted file mode 100644 index 5f23673918..0000000000 --- a/audit/2026-03-14-01/pass3/A10-LibOrder.md +++ /dev/null @@ -1,34 +0,0 @@ -# Pass 3: Documentation -- A10 LibOrder - -**File:** `src/lib/LibOrder.sol` - -## Evidence of Reading - -- **Library:** `LibOrder` (lines 10-18) -- **Import:** `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` (line 5) - -### Public/Internal Functions - -| Function | Visibility | Line | Has NatSpec | -|----------|-----------|------|-------------| -| `hash(OrderV4 memory order)` | `internal pure` | 16 | Yes | - -### Types / Errors / Constants - -None declared in this file. - -### Library-level Documentation - -- `@title LibOrder` (line 7) -- `@notice` describes purpose: consistent handling of `OrderV4` for determinism and security (lines 8-9) - -### Function-level Documentation - -**`hash`** (lines 11-18): -- `@dev`-style comment (line 11-13): explains use of `abi.encode` over `abi.encodePacked` to guard against collisions. -- `@param order` (line 14): "The order to hash." -- `@return` (line 15): "The hash of `order`." - -## Findings - -No findings. The library contains a single function that is fully documented with accurate NatSpec including `@param` and `@return` tags. The description correctly reflects the implementation (`keccak256(abi.encode(order))`), and the rationale for using `abi.encode` is documented. diff --git a/audit/2026-03-14-01/pass3/A11-LibOrderBook.md b/audit/2026-03-14-01/pass3/A11-LibOrderBook.md deleted file mode 100644 index 1a9b9658da..0000000000 --- a/audit/2026-03-14-01/pass3/A11-LibOrderBook.md +++ /dev/null @@ -1,105 +0,0 @@ -# Pass 3: Documentation -- A11 LibOrderBook - -**File:** `src/lib/LibOrderBook.sol` - -## Evidence of Reading - -- **Library:** `LibOrderBook` (lines 108-139) -- **Imports:** `CONTEXT_BASE_*` from LibContext, `TaskV2`, `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4`, `LibNamespace`, `FullyQualifiedNamespace`, `LibContext` (lines 5-19) - -### Public/Internal Functions - -| Function | Visibility | Line | Has NatSpec | -|----------|-----------|------|-------------| -| `doPost(bytes32[][] memory context, TaskV2[] memory post)` | `internal` | 111 | Partial | - -### Constants (file-level) - -| Constant | Line | Has Doc | -|----------|------|---------| -| `CALLING_CONTEXT_COLUMNS` | 28 | Yes (lines 21-27) | -| `CONTEXT_COLUMNS` | 30 | No | -| `CONTEXT_COLUMNS_EXTENDED` | 34 | Yes (lines 32-33) | -| `CONTEXT_CALLING_CONTEXT_COLUMN` | 40 | Yes (lines 36-39) | -| `CONTEXT_CALLING_CONTEXT_ROWS` | 41 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` | 43 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` | 44 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` | 45 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` | 49 | Yes (lines 47-48) | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` | 50 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` | 51 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` | 52 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` | 56 | Yes (lines 54-55) | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` | 57 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` | 58 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` | 59 | No | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` | 60 | No | -| `CONTEXT_CALCULATIONS_COLUMN` | 64 | Yes (lines 62-63) | -| `CONTEXT_CALCULATIONS_ROWS` | 65 | No | -| `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` | 67 | No | -| `CONTEXT_CALCULATIONS_ROW_IO_RATIO` | 68 | No | -| `CONTEXT_VAULT_INPUTS_COLUMN` | 74 | Yes (lines 70-73) | -| `CONTEXT_VAULT_OUTPUTS_COLUMN` | 77 | Yes (lines 75-76) | -| `CONTEXT_VAULT_IO_TOKEN` | 80 | Yes (line 79) | -| `CONTEXT_VAULT_IO_TOKEN_DECIMALS` | 82 | Yes (line 81) | -| `CONTEXT_VAULT_IO_VAULT_ID` | 84 | Yes (line 83) | -| `CONTEXT_VAULT_IO_BALANCE_BEFORE` | 87 | Yes (lines 85-86) | -| `CONTEXT_VAULT_IO_BALANCE_DIFF` | 92 | Yes (lines 88-91) | -| `CONTEXT_VAULT_IO_ROWS` | 94 | Yes (line 93) | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` | 98 | Yes (lines 96-97) | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` | 99 | No | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW` | 100 | No | -| `CONTEXT_SIGNED_CONTEXT_START_COLUMN` | 104 | Yes (lines 102-103) | -| `CONTEXT_SIGNED_CONTEXT_START_ROWS` | 105 | No | -| `CONTEXT_SIGNED_CONTEXT_START_ROW` | 106 | No | - -### Types / Errors - -None declared in this file. - -## Findings - -### A11-1: `doPost` missing `@param` tags (INFO) - -**Location:** Line 109-111 - -The `doPost` function has a `@dev` tag that describes its purpose ("Evaluates each task in `post` against the provided `context`. Tasks with empty bytecode are skipped."), but is missing explicit `@param` tags for its two parameters: - -- `context` -- the context matrix passed to each task's evaluation -- `post` -- the array of tasks to evaluate - -The `@dev` comment does mention both parameter names in prose, which provides some documentation, but formal `@param` tags would improve tooling support and consistency with Solidity NatSpec conventions. - -### A11-2: `CONTEXT_COLUMNS` missing doc comment (INFO) - -**Location:** Line 30 - -The constant `CONTEXT_COLUMNS` (value `CALLING_CONTEXT_COLUMNS + 1`) has no `@dev` comment. It is the total number of calling context columns plus the base column, but this is not documented. - -### A11-3: Several row/count constants undocumented (INFO) - -**Location:** Lines 41, 43-45, 50-52, 57-60, 65, 67-68, 99-100, 105-106 - -Multiple constants that represent row indices or row counts within context column groups lack individual `@dev` comments. The pattern is that the first constant in each group (the column identifier or the first row constant) has a block `@dev` comment, but subsequent row indices and row count values in the same group do not. - -Constants without individual documentation: -- `CONTEXT_CALLING_CONTEXT_ROWS` (line 41) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` (line 43) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` (line 44) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` (line 45) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` (line 50) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` (line 51) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` (line 52) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` (line 57) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` (line 58) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` (line 59) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` (line 60) -- `CONTEXT_CALCULATIONS_ROWS` (line 65) -- `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` (line 67) -- `CONTEXT_CALCULATIONS_ROW_IO_RATIO` (line 68) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` (line 99) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW` (line 100) -- `CONTEXT_SIGNED_CONTEXT_START_ROWS` (line 105) -- `CONTEXT_SIGNED_CONTEXT_START_ROW` (line 106) - -These constants have self-descriptive names and belong to documented groups, so the risk of misunderstanding is low. However, adding brief `@dev` comments would improve completeness. diff --git a/audit/2026-03-14-01/pass3/A12-LibOrderBookArb.md b/audit/2026-03-14-01/pass3/A12-LibOrderBookArb.md deleted file mode 100644 index 0805695b05..0000000000 --- a/audit/2026-03-14-01/pass3/A12-LibOrderBookArb.md +++ /dev/null @@ -1,63 +0,0 @@ -# Pass 3: Documentation -- A12 LibOrderBookArb - -**File:** `src/lib/LibOrderBookArb.sol` - -## Evidence of Reading - -- **Library:** `LibOrderBookArb` (lines 14-76) -- **Imports:** `TaskV2` (line 5), `IERC20` (line 6), `LibOrderBook` (line 7), `Address` (line 8), `SafeERC20` (line 9), `IERC20Metadata` (line 10), `LibDecimalFloat`, `Float` (line 11) -- **Using directive:** `SafeERC20 for IERC20` (line 15) - -### Public/Internal Functions - -| Function | Visibility | Line | Has NatSpec | -|----------|-----------|------|-------------| -| `finalizeArb(TaskV2 memory task, address ordersInputToken, uint8 inputDecimals, address ordersOutputToken, uint8 outputDecimals)` | `internal` | 20 | Partial | - -### Types / Errors / Constants - -None declared in this file. - -### Library-level Documentation - -- `@title LibOrderBookArb` (line 13) -- present but has no `@notice` or `@dev` describing the library's purpose. - -### Function-level Documentation - -**`finalizeArb`** (lines 17-75): -- `@dev` (lines 17-19): "Sends all remaining token balances and native gas to `msg.sender`, then evaluates the post-arb task with a context column containing the amounts sent as Floats." -- No `@param` tags for any of the 5 parameters. -- No `@return` tag (function returns nothing, so this is correct). -- Inline comments document each step: sending input tokens (line 31), output tokens (line 42), native gas (lines 54-59), and context assembly (line 70-74). - -### Unused Import - -- `IERC20Metadata` is imported (line 10) but never used in this file. - -## Findings - -### A12-1: `finalizeArb` missing `@param` tags (INFO) - -**Location:** Lines 17-26 - -The function has 5 parameters but no `@param` NatSpec tags: - -- `task` -- the post-arb task to evaluate after sending funds -- `ordersInputToken` -- address of the input token (from the orders' perspective) -- `inputDecimals` -- decimals of the input token for Float conversion -- `ordersOutputToken` -- address of the output token (from the orders' perspective) -- `outputDecimals` -- decimals of the output token for Float conversion - -The `@dev` comment provides a high-level description but does not describe individual parameters. Adding `@param` tags would clarify the role of each argument, especially the meaning of "input" vs "output" from the orders' perspective. - -### A12-2: Library-level `@notice` or `@dev` missing (INFO) - -**Location:** Line 13 - -The `@title` tag is present but there is no `@notice` or `@dev` tag describing the library's purpose. For consistency with `LibOrder` (which has both `@title` and `@notice`), a brief description should be added. For example: "Handles finalization of arbitrage operations by sweeping remaining balances and executing post-arb tasks." - -### A12-3: Unused import `IERC20Metadata` (INFO) - -**Location:** Line 10 - -`IERC20Metadata` is imported but never referenced in the library. This is a code hygiene issue rather than a documentation issue, but it could mislead readers into thinking the library uses metadata functionality. diff --git a/audit/2026-03-14-01/pass3/A13-LibOrderBookSubParser.md b/audit/2026-03-14-01/pass3/A13-LibOrderBookSubParser.md deleted file mode 100644 index b1d3ecf1f0..0000000000 --- a/audit/2026-03-14-01/pass3/A13-LibOrderBookSubParser.md +++ /dev/null @@ -1,119 +0,0 @@ -# Pass 3: Documentation -- A13 LibOrderBookSubParser - -**File:** `src/lib/LibOrderBookSubParser.sol` - -## Evidence of Reading - -**Library:** `LibOrderBookSubParser` (line 101) - -**File-level constants (lines 49-96):** -- `SUB_PARSER_WORD_PARSERS_LENGTH` (line 49) -- `EXTERN_PARSE_META_BUILD_DEPTH` (line 50) -- `WORD_ORDER_CLEARER` (line 52) -- `WORD_ORDERBOOK` (line 53) -- `WORD_ORDER_HASH` (line 54) -- `WORD_ORDER_OWNER` (line 55) -- `WORD_ORDER_COUNTERPARTY` (line 56) -- `WORD_CALCULATED_MAX_OUTPUT` (line 57) -- `WORD_CALCULATED_IO_RATIO` (line 58) -- `WORD_INPUT_TOKEN` (line 59) -- `WORD_INPUT_TOKEN_DECIMALS` (line 60) -- `WORD_INPUT_VAULT_ID` (line 61) -- `WORD_INPUT_VAULT_BALANCE_BEFORE` (line 62) -- `WORD_INPUT_VAULT_BALANCE_INCREASE` (line 63) -- `WORD_OUTPUT_TOKEN` (line 64) -- `WORD_OUTPUT_TOKEN_DECIMALS` (line 65) -- `WORD_OUTPUT_VAULT_ID` (line 66) -- `WORD_OUTPUT_VAULT_BALANCE_BEFORE` (line 67) -- `WORD_OUTPUT_VAULT_BALANCE_DECREASE` (line 68) -- `WORD_DEPOSITOR` (line 70) -- `WORD_DEPOSIT_TOKEN` (line 71) -- `WORD_DEPOSIT_VAULT_ID` (line 72) -- `WORD_DEPOSIT_VAULT_BEFORE` (line 73) -- `WORD_DEPOSIT_VAULT_AFTER` (line 74) -- `WORD_WITHDRAWER` (line 76) -- `WORD_WITHDRAW_TOKEN` (line 77) -- `WORD_WITHDRAW_VAULT_ID` (line 78) -- `WORD_WITHDRAW_VAULT_BEFORE` (line 79) -- `WORD_WITHDRAW_VAULT_AFTER` (line 80) -- `WORD_WITHDRAW_TARGET_AMOUNT` (line 81) -- `DEPOSIT_WORD_DEPOSITOR` through `DEPOSIT_WORDS_LENGTH` (lines 83-88) -- `WITHDRAW_WORD_WITHDRAWER` through `WITHDRAW_WORDS_LENGTH` (lines 90-96) - -**Functions (all `internal pure`):** -1. `subParserSender(uint256, uint256, OperandV2)` -- line 105, `@dev` on line 104 -2. `subParserCallingContract(uint256, uint256, OperandV2)` -- line 111, `@dev` on line 110 -3. `subParserOrderHash(uint256, uint256, OperandV2)` -- line 121, `@dev` on line 120 -4. `subParserOrderOwner(uint256, uint256, OperandV2)` -- line 131, `@dev` on line 130 -5. `subParserOrderCounterparty(uint256, uint256, OperandV2)` -- line 141, `@dev` on line 140 -6. `subParserMaxOutput(uint256, uint256, OperandV2)` -- line 152, `@dev` on line 151 -7. `subParserIORatio(uint256, uint256, OperandV2)` -- line 162, `@dev` on line 161 -8. `subParserInputToken(uint256, uint256, OperandV2)` -- line 172, `@dev` on line 171 -9. `subParserInputTokenDecimals(uint256, uint256, OperandV2)` -- line 182, `@dev` on line 181 -10. `subParserInputVaultId(uint256, uint256, OperandV2)` -- line 192, `@dev` on line 191 -11. `subParserInputBalanceBefore(uint256, uint256, OperandV2)` -- line 202, `@dev` on line 201 -12. `subParserInputBalanceDiff(uint256, uint256, OperandV2)` -- line 212, `@dev` on line 211 -13. `subParserOutputToken(uint256, uint256, OperandV2)` -- line 222, `@dev` on line 221 -14. `subParserOutputTokenDecimals(uint256, uint256, OperandV2)` -- line 232, `@dev` on line 231 -15. `subParserOutputVaultId(uint256, uint256, OperandV2)` -- line 242, `@dev` on line 241 -16. `subParserOutputBalanceBefore(uint256, uint256, OperandV2)` -- line 252, `@dev` on line 251 -17. `subParserOutputBalanceDiff(uint256, uint256, OperandV2)` -- line 262, `@dev` on line 261 -18. `subParserSigners(uint256, uint256, OperandV2)` -- line 273, `@dev` on lines 271-272 -19. `subParserDepositToken(uint256, uint256, OperandV2)` -- line 283, `@dev` on line 282 -20. `subParserDepositVaultId(uint256, uint256, OperandV2)` -- line 293, `@dev` on line 292 -21. `subParserDepositVaultBalanceBefore(uint256, uint256, OperandV2)` -- line 304, `@dev` on line 303 -22. `subParserDepositVaultBalanceAfter(uint256, uint256, OperandV2)` -- line 317, `@dev` on line 316 -23. `subParserWithdrawToken(uint256, uint256, OperandV2)` -- line 330, `@dev` on line 329 -24. `subParserWithdrawVaultId(uint256, uint256, OperandV2)` -- line 340, `@dev` on line 339 -25. `subParserWithdrawVaultBalanceBefore(uint256, uint256, OperandV2)` -- line 352, `@dev` on line 350 -26. `subParserWithdrawVaultBalanceAfter(uint256, uint256, OperandV2)` -- line 364, `@dev` on line 363 -27. `subParserWithdrawTargetAmount(uint256, uint256, OperandV2)` -- line 377, `@dev` on line 376 -28. `subParserSignedContext(uint256, uint256, OperandV2)` -- line 390, `@dev` on lines 388-389 -29. `authoringMetaV2()` -- line 406, `@dev` on lines 401-404 - -## Findings - -### A13-1: No `@param` or `@return` documentation on any function (INFO) - -**Severity:** INFO - -All 29 functions have `@dev` comments describing their purpose but none document their parameters or return values. The functions share a common signature `(uint256, uint256, OperandV2) returns (bool, bytes memory, bytes32[] memory)` dictated by the sub-parser interface, and the first two `uint256` parameters are unnamed/unused throughout. While the interface-driven nature makes the parameters somewhat self-documenting, the return tuple `(bool, bytes memory, bytes32[] memory)` is not described anywhere in this file. - -This is INFO because the `@dev` tags provide adequate context for what each function does, the signature is interface-driven, and the unnamed parameters indicate intentional disregard of those values. - -### A13-2: File-level constants lack NatSpec documentation (INFO) - -**Severity:** INFO - -34 file-level constants (lines 49-96) have no NatSpec comments. These include: -- `SUB_PARSER_WORD_PARSERS_LENGTH` (line 49) -- `EXTERN_PARSE_META_BUILD_DEPTH` (line 50) -- All `WORD_*` constants (lines 52-81) -- these are self-documenting string literals -- All `DEPOSIT_WORD_*` and `WITHDRAW_WORD_*` index constants (lines 83-96) - -The `WORD_*` constants are self-documenting because they are `bytes constant` whose values are the literal word strings they represent. The index constants (`DEPOSIT_WORD_*`, `WITHDRAW_WORD_*`) are straightforward enumerations. - -`SUB_PARSER_WORD_PARSERS_LENGTH` and `EXTERN_PARSE_META_BUILD_DEPTH` are less obvious in purpose and would benefit from a brief doc comment, but are clearly integration constants consumed by the sub-parser framework. - -This is INFO because the naming is highly descriptive and the values are self-evident. - -### A13-3: `authoringMetaV2()` return value not documented (LOW) - -**Severity:** LOW - -The `authoringMetaV2()` function (line 406) has a `@dev` comment that says it "Returns ABI-encoded `AuthoringMetaV2[][]`" but the actual return is `bytes memory` after a flatten-and-encode operation (lines 621-631). The doc says it returns `AuthoringMetaV2[][]` but the code actually flattens it to `AuthoringMetaV2[]` before ABI encoding. The `@dev` comment is inaccurate: it says "ABI-encoded `AuthoringMetaV2[][]`" but the code flattens the 2D array into a 1D `AuthoringMetaV2[]` (line 625-628) and then encodes that flat array (line 631: `abi.encode(metaFlattened)`). - -**Location:** Lines 401-404 vs lines 621-631. - -The comment says: -> Returns ABI-encoded `AuthoringMetaV2[][]` covering every context column - -The code does: -``` -uint256[] memory metaUint256Flattened = metaUint256.flatten(); -AuthoringMetaV2[] memory metaFlattened; -... -return abi.encode(metaFlattened); -``` - -The return is `abi.encode(AuthoringMetaV2[])`, not `abi.encode(AuthoringMetaV2[][])`. diff --git a/audit/2026-03-14-01/pass3/A14-LibOrderBookDeploy.md b/audit/2026-03-14-01/pass3/A14-LibOrderBookDeploy.md deleted file mode 100644 index 7af2862e81..0000000000 --- a/audit/2026-03-14-01/pass3/A14-LibOrderBookDeploy.md +++ /dev/null @@ -1,47 +0,0 @@ -# Pass 3: Documentation -- A14 LibOrderBookDeploy - -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` - -## Evidence of Reading - -**Library:** `LibOrderBookDeploy` (line 29) - -**Library-level NatSpec (lines 23-28):** -- `@title LibOrderBookDeploy` -- `@notice` describes that the library holds deployed addresses and code hashes for OrderBook contracts deployed via the rain standard zoltu deployer, enabling idempotent deployments. - -**Constants (all `internal` visibility via default for library constants):** -1. `ORDERBOOK_DEPLOYED_ADDRESS` (line 32) -- documented lines 30-31 -2. `ORDERBOOK_DEPLOYED_CODEHASH` (line 36) -- documented lines 34-35 -3. `SUB_PARSER_DEPLOYED_ADDRESS` (line 40) -- documented lines 38-39 -4. `SUB_PARSER_DEPLOYED_CODEHASH` (line 44) -- documented lines 42-43 -5. `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` (line 48) -- documented lines 46-47 -6. `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` (line 52) -- documented lines 50-51 - -**Functions:** -1. `etchOrderBook(Vm vm)` -- line 58, `internal` - - `@notice` on lines 54-56: "Etches the runtime bytecode of the orderbook and sub parser at their expected deterministic addresses. Skips any contract whose codehash already matches." - - `@param vm` on line 57: "The Forge `Vm` cheatcode interface." - -**Imports (lines 7-21):** -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6.pointers.sol` -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `OrderBookV6SubParser.pointers.sol` -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` from `RouteProcessor4.pointers.sol` - -## Findings - -### A14-1: `etchOrderBook` NatSpec mentions "orderbook and sub parser" but also etches RouteProcessor4 (LOW) - -**Severity:** LOW - -The `@notice` on line 54-56 says: "Etches the runtime bytecode of the orderbook and sub parser at their expected deterministic addresses." However, the function body (lines 65-67) also etches `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` with `ROUTE_PROCESSOR_RUNTIME_CODE`. The doc omits the RouteProcessor4 contract. - -**Location:** Lines 54-56 vs lines 65-67. - -### A14-2: No `@return` documentation on `etchOrderBook` (INFO) - -**Severity:** INFO - -The function returns nothing (`void`), so no `@return` is needed. This is correct and not a finding. - -No further findings. The documentation is well-structured with accurate NatSpec on all constants and the single function. diff --git a/audit/2026-03-14-01/pass3/A15-LibRouteProcessor4CreationCode.md b/audit/2026-03-14-01/pass3/A15-LibRouteProcessor4CreationCode.md deleted file mode 100644 index dfc265837c..0000000000 --- a/audit/2026-03-14-01/pass3/A15-LibRouteProcessor4CreationCode.md +++ /dev/null @@ -1,44 +0,0 @@ -# Pass 3: Documentation -- A15 LibRouteProcessor4CreationCode - -**File:** `src/lib/deploy/LibRouteProcessor4CreationCode.sol` - -## Evidence of Reading - -This file contains no library, contract, or interface. It declares a single file-level `bytes constant`. - -**File-level constant:** -1. `ROUTE_PROCESSOR_4_CREATION_CODE` (line 13) -- a large hex literal containing the full creation bytecode (including constructor args) for SushiSwap's RouteProcessor4 contract. - -**NatSpec (lines 5-12):** -- `@dev` comment explaining the provenance of the bytecode: - - Source: SushiSwap deployments list on GitHub (with URL) - - Cross-referenced against Etherscan deployment (with URL) - - Notes that constructor args translate to `address(0)` for bento (no bento) and no owner addresses - -**Pragma:** `solidity ^0.8.25` (line 3) - -**License:** `LicenseRef-DCL-1.0` (line 1) - -## Findings - -### A15-1: The `@dev` comment describes provenance but not the constant's purpose in the system (INFO) - -**Severity:** INFO - -The `@dev` comment (lines 5-12) documents where the bytecode came from and its constructor arguments, but does not describe why this constant exists, how it is used in the OrderBook deployment pipeline, or what RouteProcessor4 does in the context of this system. A reader unfamiliar with the codebase would need to trace imports to understand the role of this constant. - -This is INFO because the provenance documentation is the most important aspect for a raw bytecode constant, and the naming convention (`ROUTE_PROCESSOR_4_CREATION_CODE`) is descriptive enough for someone familiar with the codebase. - -### A15-2: External reference URLs may become stale (INFO) - -**Severity:** INFO - -The `@dev` comment includes two URLs (lines 6-7 and lines 9-10): -- `https://github.com/sushiswap/sushiswap/blob/master/protocols/route-processor/deployments/ethereum/RouteProcessor4.json#L406` -- `https://etherscan.io/address/0xe43ca1dee3f0fc1e2df73a0745674545f11a59f5#code` - -The GitHub URL points to the `master` branch which can change. A permalink to a specific commit hash would be more stable. The Etherscan link is inherently stable since it references a deployed contract address. - -This is INFO because it is a documentation quality note, not a functional concern. - -No additional findings. The file is a single constant with adequate provenance documentation for its purpose. diff --git a/audit/2026-03-14-01/pass4/A01-OrderBookV6ArbCommon.md b/audit/2026-03-14-01/pass4/A01-OrderBookV6ArbCommon.md deleted file mode 100644 index f2a9392c2d..0000000000 --- a/audit/2026-03-14-01/pass4/A01-OrderBookV6ArbCommon.md +++ /dev/null @@ -1,42 +0,0 @@ -# A01 - Pass 4 (Code Quality) - OrderBookV6ArbCommon.sol - -**File:** `src/abstract/OrderBookV6ArbCommon.sol` - -## Evidence: Full Inventory - -- **Contract:** `OrderBookV6ArbCommon` (abstract, line 29) -- **Struct:** `OrderBookV6ArbConfig` (line 13) -- **Error:** `WrongTask` (line 19) -- **Constant:** `BEFORE_ARB_SOURCE_INDEX` (line 23) -- **Event:** `Construct(address, OrderBookV6ArbConfig)` (line 35) -- **State variable:** `iTaskHash` (immutable, line 39) -- **Constructor:** lines 42-49 -- **Modifier:** `onlyValidTask(TaskV2)` (line 54) -- **Using directive:** `using LibEvaluable for EvaluableV4` (line 30) -- **Imports:** - - `EvaluableV4`, `SignedContextV1` from `rain.interpreter.interface/.../IInterpreterCallerV4.sol` (line 5) - - `SourceIndexV2` from `rain.interpreter.interface/.../IInterpreterV4.sol` (line 6) - - `IRaindexV6`, `TaskV2` from `rain.raindex.interface/.../IRaindexV6.sol` (line 7) - - `LibEvaluable` from `rain.interpreter.interface/.../LibEvaluable.sol` (line 8) - -## Findings - -### A01-1: Unused `using LibEvaluable for EvaluableV4` directive (LOW) - -**Line 30:** The `using LibEvaluable for EvaluableV4` directive is declared but no method from `LibEvaluable` is ever called on an `EvaluableV4` instance anywhere in this contract or its inheriting contracts (`OrderBookV6ArbOrderTaker`, `OrderBookV6FlashBorrower`, or their concrete implementations). This is dead code that adds unnecessary bytecode to deployments and obscures the actual interface surface. - -The corresponding import of `LibEvaluable` (line 8) and the import of `EvaluableV4` (line 5) are only needed for this unused directive. `EvaluableV4` is accessed at line 46 via `config.task.evaluable.bytecode.length` which is direct struct field access and does not require the `using` directive. - -### A01-2: Unused `BEFORE_ARB_SOURCE_INDEX` constant (LOW) - -**Line 23:** The file-level constant `BEFORE_ARB_SOURCE_INDEX` is defined as `SourceIndexV2.wrap(0)` but is never referenced in any production source file under `src/`. It is only imported by one test file (`test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol`). The corresponding import of `SourceIndexV2` (line 6) exists solely for this constant. - -A constant that only serves tests should live in test infrastructure, not in production code. Its presence here forces `SourceIndexV2` to be imported, increasing the conceptual surface area of the contract without providing production value. - -### A01-3: Unused `SignedContextV1` import (LOW) - -**Line 5:** `SignedContextV1` is imported alongside `EvaluableV4` but is never used in this file. It is re-exported from `OrderBookV6ArbOrderTaker.sol` (line 11) which also never uses it. This is a vestigial import from a previous version of the contract. - -### A01-4: Unused `IRaindexV6` import (LOW) - -**Line 7:** `IRaindexV6` is imported but never used directly in this file. It is not needed here -- the child contracts import it from their own direct dependency paths. diff --git a/audit/2026-03-14-01/pass4/A02-OrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass4/A02-OrderBookV6ArbOrderTaker.md deleted file mode 100644 index 95b1ce2a42..0000000000 --- a/audit/2026-03-14-01/pass4/A02-OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,50 +0,0 @@ -# A02 - Pass 4 (Code Quality) - OrderBookV6ArbOrderTaker.sol - -**File:** `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence: Full Inventory - -- **Contract:** `OrderBookV6ArbOrderTaker` (abstract, line 20) - - Inherits: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` -- **Constructor:** line 29 -- **Functions:** - - `supportsInterface(bytes4)` (line 32) -- public view virtual override - - `arb5(IRaindexV6, TakeOrdersConfigV5, TaskV2)` (line 38) -- external payable, nonReentrant, onlyValidTask - - `onTakeOrders2(address, address, Float, Float, bytes)` (line 70) -- public virtual override, no-op -- **Using directive:** `using SafeERC20 for IERC20` (line 27) -- **Imports:** - - `ERC165`, `IERC165` from `openzeppelin-contracts/.../ERC165.sol` (line 5) - - `ReentrancyGuard` from `openzeppelin-contracts/.../ReentrancyGuard.sol` (line 6) - - `IERC20`, `SafeERC20` from `openzeppelin-contracts/.../SafeERC20.sol` (line 7) - - `IRaindexV6` from `rain.raindex.interface/.../IRaindexV6.sol` (line 8) - - `IRaindexV6ArbOrderTaker`, `TaskV2` from `rain.raindex.interface/.../IRaindexV6ArbOrderTaker.sol` (line 9) - - `TakeOrdersConfigV5`, `Float` from `rain.raindex.interface/.../IRaindexV6.sol` (line 10) - - `OrderBookV6ArbConfig`, `EvaluableV4`, `OrderBookV6ArbCommon`, `SignedContextV1` from `./OrderBookV6ArbCommon.sol` (line 11) - - `LibOrderBookArb` from `../lib/LibOrderBookArb.sol` (line 12) - - `IRaindexV6OrderTaker` from `rain.raindex.interface/.../IRaindexV6OrderTaker.sol` (line 13) - - `LibTOFUTokenDecimals` from `rain.tofu.erc20-decimals/.../LibTOFUTokenDecimals.sol` (line 14) - -## Findings - -### A02-1: Unused imports `EvaluableV4` and `SignedContextV1` (LOW) - -**Line 11:** `EvaluableV4` and `SignedContextV1` are imported from `OrderBookV6ArbCommon.sol` but are never referenced in this file. They are not used in the contract body, type signatures, or re-exported to concrete inheritors (checked `GenericPoolOrderBookV6ArbOrderTaker.sol` and `RouteProcessorOrderBookV6ArbOrderTaker.sol` -- neither imports these types). These are vestigial and should be removed. - -### A02-2: Inconsistent IERC20 import style (INFO) - -**Line 7:** `IERC20` and `SafeERC20` are imported together from `SafeERC20.sol`: -``` -import {IERC20, SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -``` - -In contrast, `OrderBookV6FlashBorrower.sol` imports them separately: -``` -import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; -``` - -The `OrderBookV6FlashBorrower` style is canonical (importing types from their declaring file). The `OrderBookV6ArbOrderTaker` style relies on a re-export. Both compile, but using the canonical import path is more robust and consistent. - -### A02-3: Unused `IERC165` import (INFO) - -**Line 5:** `IERC165` is imported alongside `ERC165` but is never referenced directly in this file. The `supportsInterface` override signature comes from `ERC165` which already inherits `IERC165`. This is harmless but unnecessary. diff --git a/audit/2026-03-14-01/pass4/A03-OrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass4/A03-OrderBookV6FlashBorrower.md deleted file mode 100644 index 2d237b0ccf..0000000000 --- a/audit/2026-03-14-01/pass4/A03-OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,56 +0,0 @@ -# A03 - Pass 4 (Code Quality) - OrderBookV6FlashBorrower.sol - -**File:** `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence: Full Inventory - -- **Contract:** `OrderBookV6FlashBorrower` (abstract, line 60) - - Inherits: `IERC3156FlashBorrower`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` -- **Errors:** - - `BadInitiator(address)` (line 20) - - `BadLender(address)` (line 25) - - `FlashLoanFailed()` (line 28) -- **Constructor:** line 63 -- **Functions:** - - `supportsInterface(bytes4)` (line 66) -- public view virtual override - - `_exchange(TakeOrdersConfigV5, bytes)` (line 79) -- internal virtual, no-op - - `onFlashLoan(address, address, uint256, uint256, bytes)` (line 82) -- external - - `arb4(IRaindexV6, TakeOrdersConfigV5, bytes, TaskV2)` (line 129) -- external payable, nonReentrant, onlyValidTask -- **Using directive:** `using SafeERC20 for IERC20` (line 61) -- **Imports:** - - `ERC165`, `IERC165` from `openzeppelin-contracts/.../ERC165.sol` (line 5) - - `SafeERC20` from `openzeppelin-contracts/.../SafeERC20.sol` (line 6) - - `IERC20` from `openzeppelin-contracts/.../IERC20.sol` (line 7) - - `ReentrancyGuard` from `openzeppelin-contracts/.../ReentrancyGuard.sol` (line 8) - - `ON_FLASH_LOAN_CALLBACK_SUCCESS` from `rain.raindex.interface/.../IERC3156FlashBorrower.sol` (line 9) - - `IRaindexV6`, `TakeOrdersConfigV5`, `TaskV2` from `rain.raindex.interface/.../IRaindexV6.sol` (line 10) - - `IERC3156FlashBorrower` from `rain.raindex.interface/.../IERC3156FlashBorrower.sol` (line 11) - - `OrderBookV6ArbConfig`, `OrderBookV6ArbCommon` from `./OrderBookV6ArbCommon.sol` (line 12) - - `LibOrderBookArb` from `../lib/LibOrderBookArb.sol` (line 13) - - `LibOrderBookDeploy` from `../lib/deploy/LibOrderBookDeploy.sol` (line 14) - - `LibTOFUTokenDecimals` from `rain.tofu.erc20-decimals/.../LibTOFUTokenDecimals.sol` (line 15) - - `LibDecimalFloat` from `rain.math.float/.../LibDecimalFloat.sol` (line 16) - -## Findings - -### A03-1: Production code transitively imports forge-std via `LibOrderBookDeploy` (LOW) - -**Line 14:** `OrderBookV6FlashBorrower` imports `LibOrderBookDeploy` solely to access the `ORDERBOOK_DEPLOYED_ADDRESS` constant (used at line 84 for the `BadLender` check). However, `LibOrderBookDeploy` (`src/lib/deploy/LibOrderBookDeploy.sol`) imports `{Vm} from "forge-std/Vm.sol"` (a test-only dependency) at its own line 5. - -This means production source code (`src/`) has a transitive dependency on `forge-std`, which is a test framework. While the Solidity compiler will likely not include the `Vm` interface in deployed bytecode (it's only used as a parameter type in the `etchOrderBook` function which is never called from production paths), this is a leaky abstraction: test infrastructure bleeds into the production dependency graph. - -The `ORDERBOOK_DEPLOYED_ADDRESS` constant should be either: -1. Defined directly in `OrderBookV6FlashBorrower.sol` or a minimal constants-only file that does not import `forge-std`, or -2. The `LibOrderBookDeploy` library should be split so constants live separately from the `etchOrderBook` test helper. - -### A03-2: Unused `IERC165` import (INFO) - -**Line 5:** `IERC165` is imported alongside `ERC165` but is never referenced directly. Same pattern as in `OrderBookV6ArbOrderTaker.sol`. Harmless but unnecessary. - -### A03-3: NatSpec references outdated contract name `OrderBookFlashBorrower` (INFO) - -**Line 44:** The contract-level NatSpec comment says: -``` -/// The `OrderBookFlashBorrower` can: -``` -The actual contract name is `OrderBookV6FlashBorrower`. This is a minor documentation drift. diff --git a/audit/2026-03-14-01/pass4/A04-OrderBookV6FlashLender.md b/audit/2026-03-14-01/pass4/A04-OrderBookV6FlashLender.md deleted file mode 100644 index e4f10eb42d..0000000000 --- a/audit/2026-03-14-01/pass4/A04-OrderBookV6FlashLender.md +++ /dev/null @@ -1,50 +0,0 @@ -# A04 — Pass 4 (Code Quality) — `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence Inventory - -**Contract:** `OrderBookV6FlashLender` (abstract), lines 29–80 -**Inherits:** `IERC3156FlashLender`, `ERC165` -**Using:** `SafeERC20 for IERC20` (line 30) - -| Item | Kind | Line | -|------|------|------| -| `FlashLenderCallbackFailed` | error | 18 | -| `FLASH_FEE` | constant | 23 | -| `supportsInterface` | function | 33 | -| `flashLoan` | function | 38 | -| `flashFee` | function | 70 | -| `maxFlashLoan` | function | 77 | - -## Findings - -### A04-1 — Pragma version inconsistency with concrete contracts [LOW] - -`OrderBookV6FlashLender.sol` uses `pragma solidity ^0.8.19;` (line 3) while all concrete contracts that inherit from it (e.g., `OrderBookV6.sol`) use `pragma solidity =0.8.25;`. The abstract contracts in `src/abstract/` consistently use `^0.8.19` while concrete contracts use `=0.8.25`. - -This is an intentional pattern: abstract/library files use a floating pragma so they can be consumed by downstream projects at any compatible version, while concrete (deployable) files pin the exact compiler. This is a recognized Solidity convention. - -**Verdict:** Intentional two-tier pragma strategy. No fix needed — demoting to INFO. - -**Severity revised: INFO** - -### A04-2 — NatSpec typo: "its" should be "it's" [INFO] - -Line 22: `"...and its more important anyway..."` should be `"...and it's more important anyway..."`. - -Minor grammatical issue in a dev comment. No functional impact. - -### A04-3 — No commented-out code [INFO] - -No commented-out code found in this file. The `//slither-disable-next-line` directive (line 63) is a tooling annotation, not commented-out code. - -### A04-4 — No bare `src/` imports [INFO] - -All imports in this file use remapped paths (`openzeppelin-contracts/...`, `rain.raindex.interface/...`). No bare `src/` import paths that would break under git submodule usage. - -### A04-5 — Style consistency: import grouping matches codebase convention [INFO] - -Imports are grouped with OpenZeppelin first, then rain ecosystem — consistent with other abstract files in the codebase. - -## Summary - -No LOW or higher findings. The file is clean, well-documented (especially the slither rationale at lines 50–62), and follows codebase conventions. The two-tier pragma strategy (`^0.8.19` for abstract, `=0.8.25` for concrete) is intentional and consistent. diff --git a/audit/2026-03-14-01/pass4/A05-GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass4/A05-GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index dab6121ea8..0000000000 --- a/audit/2026-03-14-01/pass4/A05-GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,60 +0,0 @@ -# A05 — Pass 4 (Code Quality) — `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` - -## Evidence Inventory - -**Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (concrete), lines 14–47 -**Inherits:** `OrderBookV6ArbOrderTaker` -**Using:** `SafeERC20 for IERC20` (line 15), `Address for address` (line 16) - -| Item | Kind | Line | -|------|------|------| -| `constructor` | function | 18 | -| `onTakeOrders2` | function (override) | 21 | -| `receive` | function | 45 | -| `fallback` | function | 46 | - -## Findings - -### A05-1 — Duplicated exchange pattern across GenericPool arb contracts [LOW] - -The approve-call-revoke pattern in `onTakeOrders2` (lines 35–40) is nearly identical to the pattern in `GenericPoolOrderBookV6FlashBorrower._exchange` (lines 42–46): - -``` -GenericPoolOrderBookV6ArbOrderTaker.onTakeOrders2 (lines 35-40): - IERC20(inputToken).forceApprove(spender, type(uint256).max); - pool.functionCallWithValue(encodedFunctionCall, address(this).balance); - IERC20(inputToken).forceApprove(spender, 0); - -GenericPoolOrderBookV6FlashBorrower._exchange (lines 42-46): - IERC20(borrowedToken).forceApprove(spender, type(uint256).max); - pool.functionCallWithValue(encodedFunctionCall, address(this).balance); - IERC20(borrowedToken).forceApprove(spender, 0); -``` - -Both also share identical `receive()` and `fallback()` functions with the same NatSpec comment. The ABI decode logic `(address spender, address pool, bytes memory encodedFunctionCall) = abi.decode(...)` is also duplicated. - -This duplication means any future change to the generic pool exchange logic must be applied in two places. A shared internal helper (e.g., in a library or common base) would reduce maintenance burden. - -**Fix:** See `.fixes/A05-1.md` - -### A05-2 — Unused import: `IERC20` imported directly but already available via `SafeERC20` [INFO] - -Line 5 imports `IERC20` directly from OpenZeppelin, and line 6 imports `SafeERC20`. The `using SafeERC20 for IERC20;` declaration needs the `IERC20` type, so this import is necessary. However, `IERC20` could be imported via the parent `OrderBookV6ArbOrderTaker` re-export chain. This is a stylistic choice — explicit imports are arguably clearer. - -**Verdict:** No issue. Explicit imports are the preferred style in this codebase. - -### A05-3 — No bare `src/` imports [INFO] - -All imports use relative paths (`../../abstract/...`) or remapped paths (`openzeppelin-contracts/...`). This is correct and will not break under git submodule usage. - -### A05-4 — No commented-out code [INFO] - -The `//slither-disable-next-line` on line 38 is a tooling annotation. No actual commented-out code. - -### A05-5 — Pragma style consistent with concrete contract convention [INFO] - -Uses `pragma solidity =0.8.25;` — matches all other concrete contracts. - -## Summary - -One LOW finding (A05-1) for duplicated exchange logic across the two GenericPool arb contracts. Otherwise the file is clean, well-structured, and consistent with codebase conventions. diff --git a/audit/2026-03-14-01/pass4/A06-GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass4/A06-GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index f5642ffa88..0000000000 --- a/audit/2026-03-14-01/pass4/A06-GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,59 +0,0 @@ -# A06 — Pass 4 (Code Quality) — `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` - -## Evidence Inventory - -**Contract:** `GenericPoolOrderBookV6FlashBorrower` (concrete), lines 26–53 -**Inherits:** `OrderBookV6FlashBorrower` -**Using:** `SafeERC20 for IERC20` (line 27), `Address for address` (line 28) - -| Item | Kind | Line | -|------|------|------| -| `constructor` | function | 30 | -| `_exchange` | function (internal, override) | 33 | -| `receive` | function | 51 | -| `fallback` | function | 52 | - -## Findings - -### A06-1 — Duplicated exchange pattern with GenericPoolOrderBookV6ArbOrderTaker [LOW] - -Cross-reference with A05-1. The approve-call-revoke + ABI-decode + `receive`/`fallback` pattern in `_exchange` (lines 34–46) is nearly identical to `GenericPoolOrderBookV6ArbOrderTaker.onTakeOrders2` (lines 29–40). Both contracts: - -1. Decode `(address spender, address pool, bytes memory encodedFunctionCall)` from calldata/memory -2. `forceApprove(spender, type(uint256).max)` -3. `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -4. `forceApprove(spender, 0)` -5. Declare identical `receive() external payable {}` and `fallback() external payable {}` - -A shared library function (e.g., `LibGenericPoolExchange.exchange(token, spender, pool, encodedFunctionCall)`) would eliminate this duplication. - -**Fix:** See `.fixes/A06-1.md` (combined with A05-1) - -### A06-2 — Deep indexing into `takeOrders` to extract borrowed token [INFO] - -Line 37: -```solidity -address borrowedToken = takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token; -``` - -This is a long chain of nested accesses. However, it is the same pattern used in `OrderBookV6FlashBorrower.arb4` (lines 144–145) and `OrderBookV6ArbOrderTaker.arb5` (lines 49–50) for extracting token addresses from orders. This is consistent across the codebase — not a finding, just noting the pattern. - -### A06-3 — Re-exported imports from parent are clean [INFO] - -Line 7–13 imports `SafeERC20`, `IERC20`, `TakeOrdersConfigV5`, and `OrderBookV6ArbConfig` via the parent `OrderBookV6FlashBorrower.sol` re-export. Only `Address` is imported directly from OpenZeppelin. This is consistent with how `GenericPoolOrderBookV6ArbOrderTaker` handles its imports. - -### A06-4 — No bare `src/` imports [INFO] - -All imports use relative paths (`../../abstract/...`) or remapped paths (`openzeppelin-contracts/...`). Correct for git submodule compatibility. - -### A06-5 — No commented-out code [INFO] - -The `//slither-disable-next-line` on line 44 is a tooling annotation, not commented-out code. - -### A06-6 — Pragma style consistent with concrete contract convention [INFO] - -Uses `pragma solidity =0.8.25;` — matches all other concrete contracts. - -## Summary - -One LOW finding (A06-1) shared with A05-1 regarding duplicated generic pool exchange logic. Otherwise the file is clean and well-structured. diff --git a/audit/2026-03-14-01/pass4/A07-RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass4/A07-RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 5b9c2da53a..0000000000 --- a/audit/2026-03-14-01/pass4/A07-RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,49 +0,0 @@ -# A07 - Pass 4: Code Quality - RouteProcessorOrderBookV6ArbOrderTaker - -**File:** `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` - -## Evidence inventory - -**Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (lines 15-56) -- Inherits: `OrderBookV6ArbOrderTaker` -- State variable: `iRouteProcessor` (line 19, immutable) -- Constructor (line 21) -- Function: `onTakeOrders2` (line 27, public virtual override) -- `receive()` (line 54, external payable) -- `fallback()` (line 55, external payable) - -**Imports (lines 5-11):** -- `IRouteProcessor` from `sushixswap-v2/src/interfaces/IRouteProcessor.sol` -- `IERC20` from `openzeppelin-contracts/contracts/token/ERC20/IERC20.sol` -- `SafeERC20` from `openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol` -- `OrderBookV6ArbOrderTaker, OrderBookV6ArbConfig, Float` from `../../abstract/OrderBookV6ArbOrderTaker.sol` -- `LibDecimalFloat` from `rain.math.float/lib/LibDecimalFloat.sol` -- `IERC20Metadata` from `openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol` - -**Constants/Errors:** None defined locally. - -**Pragma:** `=0.8.25` - -## Findings - -### A07-1: Missing `sushixswap-v2` remapping in `foundry.toml` (LOW) - -**Severity:** LOW - -The import `"sushixswap-v2/src/interfaces/IRouteProcessor.sol"` on line 5 relies on Foundry's auto-detection of `lib/sushixswap-v2` rather than an explicit remapping in `foundry.toml`. All other major dependencies (`openzeppelin-contracts`, `rain.interpreter`, `rain.metadata`, `rain.interpreter.interface`, `rain.solmem`, `rain.math.float`, etc.) have explicit remappings. This is inconsistent and fragile -- if the lib directory layout changes or this project is consumed as a dependency, the implicit resolution may break. - -**Location:** `foundry.toml` (remappings section, line 39-51) and `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol:5` - -**Proposed fix:** Add an explicit remapping `"sushixswap-v2/=lib/sushixswap-v2/"` to `foundry.toml`. - -### A07-2: Stale `IOrderBookV1` reference in `OrderBookV6.sol` NatDoc (INFO) - -**Severity:** INFO - -This finding is reported here because it was observed during contextual review of the arb contract's parent chain, though the location is in `OrderBookV6.sol` line 211. The comment references `IOrderBookV1` which no longer exists in the codebase. The current interface is `IRaindexV6`. This is an informational note only; the primary report is in A08. - ---- - -No commented-out code found. -No bare `src/` import paths found in this file. -No build warnings expected from this file. diff --git a/audit/2026-03-14-01/pass4/A08-OrderBookV6.md b/audit/2026-03-14-01/pass4/A08-OrderBookV6.md deleted file mode 100644 index c374c3c26a..0000000000 --- a/audit/2026-03-14-01/pass4/A08-OrderBookV6.md +++ /dev/null @@ -1,123 +0,0 @@ -# A08 - Pass 4: Code Quality - OrderBookV6 - -**File:** `src/concrete/ob/OrderBookV6.sol` - -## Evidence inventory - -**Errors (lines 69-125):** -- `ReentrancyGuardReentrantCall` (line 69) -- `NotOrderOwner(address)` (line 73) -- `TokenMismatch` (line 76) -- `TokenSelfTrade` (line 79) -- `TokenDecimalsMismatch` (line 83) -- `MinimumIO(Float, Float)` (line 88) -- `SameOwner` (line 91) -- `UnsupportedCalculateInputs(uint256)` (line 95) -- `UnsupportedCalculateOutputs(uint256)` (line 98) -- `NegativeInput` (line 102) -- `NegativeOutput` (line 105) -- `NegativeVaultBalance(Float)` (line 109) -- `NegativeVaultBalanceChange(Float)` (line 113) -- `NegativePull` (line 116) -- `NegativePush` (line 118) -- `NegativeBounty` (line 122) -- `ClearZeroAmount` (line 125) - -**Constants (lines 129-150):** -- `ORDER_LIVE` (line 129) -- `ORDER_DEAD` (line 134) -- `CALCULATE_ORDER_ENTRYPOINT` (line 137) -- `HANDLE_IO_ENTRYPOINT` (line 140) -- `CALCULATE_ORDER_MIN_OUTPUTS` (line 143) -- `CALCULATE_ORDER_MAX_OUTPUTS` (line 145) -- `HANDLE_IO_MIN_OUTPUTS` (line 148) -- `HANDLE_IO_MAX_OUTPUTS` (line 150) - -**Struct:** `OrderIOCalculationV4` (lines 178-187) - -**Contract:** `OrderBookV6 is IRaindexV6, IMetaV1_2, ReentrancyGuard, Multicall, OrderBookV6FlashLender` (line 191) -- Storage: `sOrders` (line 208), `sVaultBalances` (line 215-216) -- Functions: - - `vaultBalance2` (line 219, external view) - - `_vaultBalance` (line 226, internal view) - - `orderExists` (line 244, external view) - - `entask2` (line 249, external nonReentrant) - - `deposit4` (line 254, external nonReentrant) - - `withdraw4` (line 289, external nonReentrant) - - `addOrder4` (line 328, external nonReentrant) - - `removeOrder3` (line 378, external nonReentrant) - - `checkTokenSelfTrade` (line 403, internal pure) - - `quote2` (line 410, external view) - - `takeOrders4` (line 433, external nonReentrant) - - `clear3` (line 593, external nonReentrant) - - `calculateOrderIO` (line 698, internal view) - - `increaseVaultBalance` (line 822, internal) - - `decreaseVaultBalance` (line 855, internal) - - `recordVaultIO` (line 893, internal) - - `handleIO` (line 919, internal) - - `calculateClearStateChange` (line 971, internal pure) - - `calculateClearStateAlice` (line 987, internal pure) - - `pullTokens` (line 1008, internal) - - `pushTokens` (line 1032, internal) - - `_nonZeroVaultId` (line 1052, internal pure) - - Modifier: `nonZeroVaultId` (line 1058) - -**Imports (lines 4-65):** All use remapped paths (`openzeppelin-contracts/`, `rain.interpreter.interface/`, `rain.solmem/`, `rain.metadata/`, `rain.math.float/`, `rain.tofu.erc20-decimals/`, `rain.raindex.interface/`) or relative paths (`../../lib/`, `../../abstract/`). - -**Pragma:** `=0.8.25` - -## Findings - -### A08-1: Stale `IOrderBookV1` reference in NatDoc comment (LOW) - -**Severity:** LOW - -Line 211 contains the comment: -``` -/// This gives 1:1 parity with the `IOrderBookV1` interface but keeping the -``` - -`IOrderBookV1` does not exist in the current codebase. The contract implements `IRaindexV6`. This is a stale documentation reference from a prior version that should be updated or removed to avoid confusion for auditors and integrators. - -**Location:** `src/concrete/ob/OrderBookV6.sol:211` - -### A08-2: Unused errors `TokenDecimalsMismatch`, `NegativeInput`, `NegativeOutput`, `UnsupportedCalculateInputs` (LOW) - -**Severity:** LOW - -The following errors are declared at file scope but never used anywhere in `OrderBookV6.sol` or its parent contracts: -- `TokenDecimalsMismatch` (line 83) -- `NegativeInput` (line 102) -- `NegativeOutput` (line 105) -- `UnsupportedCalculateInputs` (line 95) - -These appear to be vestiges from a prior version. Unused error declarations bloat the ABI and can mislead integrators into thinking these conditions are checked. They should be removed unless they are part of a public interface contract. - -**Location:** `src/concrete/ob/OrderBookV6.sol:83,95,102,105` - -### A08-3: `ReentrancyGuardReentrantCall` error shadows OpenZeppelin (INFO) - -**Severity:** INFO - -Line 69 declares `error ReentrancyGuardReentrantCall()` with the comment "This will exist in a future version of Open Zeppelin if their main branch is to be believed." Since the project uses OpenZeppelin via git submodule, this is either already provided by the OZ version in use (making it a duplicate) or not yet provided (making it a forward declaration). This is noted for awareness -- it is not a bug, but the comment should be verified against the actual OZ version in `lib/` and updated or removed accordingly. - -**Location:** `src/concrete/ob/OrderBookV6.sol:67-69` - -### A08-4: Commented-out optimizer settings in `foundry.toml` (INFO) - -**Severity:** INFO - -Lines 12-16 of `foundry.toml` contain commented-out optimizer settings: -```toml -# via_ir = false -# optimizer = false -# optimizer_runs = 0 -# optimizer_steps = 0 -``` - -These are clearly development/debugging toggles with a comment explaining their purpose ("optimizer settings for debugging"), which is acceptable. Noted for completeness. - ---- - -No bare `src/` import paths found in this file. -No commented-out Solidity code found in this file. diff --git a/audit/2026-03-14-01/pass4/A09-OrderBookV6SubParser.md b/audit/2026-03-14-01/pass4/A09-OrderBookV6SubParser.md deleted file mode 100644 index 5e65ed981e..0000000000 --- a/audit/2026-03-14-01/pass4/A09-OrderBookV6SubParser.md +++ /dev/null @@ -1,68 +0,0 @@ -# A09 - Pass 4: Code Quality - OrderBookV6SubParser - -**File:** `src/concrete/parser/OrderBookV6SubParser.sol` - -## Evidence inventory - -**Contract:** `OrderBookV6SubParser is BaseRainterpreterSubParser` (line 69) -- Using: `LibUint256Matrix for uint256[][]` (line 70) -- Functions: - - `describedByMetaV1` (line 73, external pure) -- returns `DESCRIBED_BY_META_HASH` - - `subParserParseMeta` (line 78, internal pure virtual override) -- returns `SUB_PARSER_PARSE_META` - - `subParserWordParsers` (line 83, internal pure virtual override) -- returns `SUB_PARSER_WORD_PARSERS` - - `subParserOperandHandlers` (line 88, internal pure virtual override) -- returns `SUB_PARSER_OPERAND_HANDLERS` - - `buildLiteralParserFunctionPointers` (line 93, external pure) -- returns empty bytes - - `buildOperandHandlerFunctionPointers` (line 98, external pure) -- builds operand handler table - - `buildSubParserWordParsers` (line 183, external pure) -- builds word parser table - -**Imports (lines 5-66):** -- `LibParseOperand, BaseRainterpreterSubParser, OperandV2, IParserToolingV1` from `rain.interpreter/abstract/BaseRainterpreterSubParser.sol` -- `LibConvert` from `rain.lib.typecast/LibConvert.sol` -- `LibUint256Matrix` from `rain.solmem/lib/LibUint256Matrix.sol` -- `LibOrderBookSubParser, ...constants...` from `../../lib/LibOrderBookSubParser.sol` -- `...CONTEXT constants...` from `../../lib/LibOrderBook.sol` -- `DESCRIBED_BY_META_HASH, PARSE_META, SUB_PARSER_WORD_PARSERS, OPERAND_HANDLER_FUNCTION_POINTERS` from `../../generated/OrderBookV6SubParser.pointers.sol` -- `IDescribedByMetaV1` from `rain.metadata/interface/IDescribedByMetaV1.sol` - -**Pragma:** `=0.8.25` - -## Findings - -### A09-1: Missing `rain.lib.typecast` remapping in `foundry.toml` (LOW) - -**Severity:** LOW - -The import `"rain.lib.typecast/LibConvert.sol"` on line 11 relies on Foundry's auto-detection rather than an explicit remapping. The `rain.lib.typecast` package lives at `lib/rain.raindex.interface/lib/rain.interpreter.interface/lib/rain.lib.typecast` -- a deeply nested transitive dependency. There is no explicit remapping for it in `foundry.toml`, unlike the other rain libraries which all have explicit remappings. This is inconsistent and fragile: if the auto-resolution order changes or a different version of the library appears elsewhere in the dependency tree, the import may silently resolve to the wrong copy. - -**Location:** `foundry.toml` (remappings section) and `src/concrete/parser/OrderBookV6SubParser.sol:11` - -**Proposed fix:** Add `"rain.lib.typecast/=lib/rain.raindex.interface/lib/rain.interpreter.interface/lib/rain.lib.typecast/src/"` to the remappings in `foundry.toml`. - -### A09-2: Bare `src/` import paths in test and script files referencing this contract's siblings (LOW) - -**Severity:** LOW - -While `OrderBookV6SubParser.sol` itself uses correct relative paths, its related test and script files use bare `src/` import paths extensively. Per the audit instructions, bare `src/` paths break when the project is used as a git submodule. Examples from the broader codebase affecting the SubParser ecosystem: - -- `script/BuildPointers.sol:9`: `import {OrderBookV6SubParser} from "src/concrete/parser/OrderBookV6SubParser.sol";` -- `script/BuildPointers.sol:10`: `import {LibOrderBookSubParser, ...} from "src/lib/LibOrderBookSubParser.sol";` - -These are not in the audited source file itself but are noted because they directly reference the SubParser contract and would break submodule usage. - -**Location:** `script/BuildPointers.sol:8-10` and many files under `test/` - -### A09-3: Inline assembly blocks lack `"memory-safe"` annotation in `buildOperandHandlerFunctionPointers` (INFO) - -**Severity:** INFO - -Line 174 uses `assembly ("memory-safe")` which is correct. The sibling function `buildSubParserWordParsers` at line 295 also correctly uses `assembly ("memory-safe")`. Both are consistent. - -However, note that in the library file `LibOrderBookSubParser.sol` at line 622, the assembly block for `authoringMetaV2()` uses bare `assembly` without the `"memory-safe"` annotation. This is inconsistent with the pattern used in the concrete contract. - -**Location:** `src/lib/LibOrderBookSubParser.sol:622` (contextual, not in audited file) - ---- - -No commented-out code found. -No bare `src/` import paths found in the audited file itself. -No build warnings expected from this file. diff --git a/audit/2026-03-14-01/pass4/A10-LibOrder.md b/audit/2026-03-14-01/pass4/A10-LibOrder.md deleted file mode 100644 index 6ee1d25189..0000000000 --- a/audit/2026-03-14-01/pass4/A10-LibOrder.md +++ /dev/null @@ -1,37 +0,0 @@ -# A10 - LibOrder.sol - Pass 4 (Code Quality) - -**File:** `src/lib/LibOrder.sol` -**Lines:** 19 - -## Evidence Inventory - -### Contract/Library -- `LibOrder` (library) - line 10 - -### Functions -- `hash(OrderV4 memory order) -> bytes32` (internal pure) - line 16 - -### Imports -- `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` - line 5 - -### Constants / Types / Errors -- (none) - -## Findings - -### A10-1: Inconsistent Pragma Version [LOW] - -`LibOrder.sol` uses `pragma solidity ^0.8.18` (line 3), while the other library files in the same directory use `^0.8.19`: -- `LibOrderBook.sol` - `^0.8.19` -- `LibOrderBookArb.sol` - `^0.8.19` -- `LibOrderBookSubParser.sol` - `^0.8.19` - -The concrete contracts pin to `=0.8.25` and the deploy libs use `^0.8.25`. - -The `^0.8.18` pragma in `LibOrder.sol` is the only file in `src/lib/` that uses this version. While it compiles fine alongside the rest, it is inconsistent and makes the minimum version expectation unclear. All library files in the same directory should share the same minimum version. - -**Recommendation:** Bump to `^0.8.19` to match sibling library files. - ---- - -**No other findings.** The file is concise, well-documented, uses `abi.encode` (not `abi.encodePacked`) as documented, and the single function is correct. No commented-out code, no bare `src/` imports, no leaky abstractions. diff --git a/audit/2026-03-14-01/pass4/A11-LibOrderBook.md b/audit/2026-03-14-01/pass4/A11-LibOrderBook.md deleted file mode 100644 index 32deb872ee..0000000000 --- a/audit/2026-03-14-01/pass4/A11-LibOrderBook.md +++ /dev/null @@ -1,78 +0,0 @@ -# A11 - LibOrderBook.sol - Pass 4 (Code Quality) - -**File:** `src/lib/LibOrderBook.sol` -**Lines:** 139 - -## Evidence Inventory - -### Library -- `LibOrderBook` (library) - line 108 - -### Functions -- `doPost(bytes32[][] memory context, TaskV2[] memory post)` (internal) - line 111 - -### Imports (lines 5-19) -- `CONTEXT_BASE_ROWS`, `CONTEXT_BASE_ROW_SENDER`, `CONTEXT_BASE_ROW_CALLING_CONTRACT`, `CONTEXT_BASE_COLUMN` from `rain.interpreter.interface/lib/caller/LibContext.sol` - lines 6-10 -- `TaskV2` from `rain.raindex.interface/interface/IRaindexV6.sol` - line 11 -- `SourceIndexV2`, `StateNamespace`, `StackItem`, `EvalV4` from `rain.interpreter.interface/interface/IInterpreterV4.sol` - lines 13-17 -- `LibNamespace`, `FullyQualifiedNamespace` from `rain.interpreter.interface/lib/ns/LibNamespace.sol` - line 18 -- `LibContext` from `rain.interpreter.interface/lib/caller/LibContext.sol` - line 19 - -### Constants (file-level, lines 28-106) -- `CALLING_CONTEXT_COLUMNS` = 4 (line 28) -- `CONTEXT_COLUMNS` = CALLING_CONTEXT_COLUMNS + 1 (line 30) -- `CONTEXT_COLUMNS_EXTENDED` = CONTEXT_COLUMNS + 2 + 1 + 1 (line 34) -- `CONTEXT_CALLING_CONTEXT_COLUMN` = 1 (line 40) -- `CONTEXT_CALLING_CONTEXT_ROWS` = 3 (line 41) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` = 0 (line 43) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` = 1 (line 44) -- `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` = 2 (line 45) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` = 0 (line 49) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` = 1 (line 50) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` = 2 (line 51) -- `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` = 3 (line 52) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` = 0 (line 54) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` = 1 (line 55) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` = 2 (line 56) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` = 3 (line 57) -- `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` = 4 (line 60) -- `CONTEXT_CALCULATIONS_COLUMN` = 2 (line 64) -- `CONTEXT_CALCULATIONS_ROWS` = 2 (line 65) -- `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` = 0 (line 67) -- `CONTEXT_CALCULATIONS_ROW_IO_RATIO` = 1 (line 68) -- `CONTEXT_VAULT_INPUTS_COLUMN` = 3 (line 74) -- `CONTEXT_VAULT_OUTPUTS_COLUMN` = 4 (line 77) -- `CONTEXT_VAULT_IO_TOKEN` = 0 (line 80) -- `CONTEXT_VAULT_IO_TOKEN_DECIMALS` = 1 (line 82) -- `CONTEXT_VAULT_IO_VAULT_ID` = 2 (line 84) -- `CONTEXT_VAULT_IO_BALANCE_BEFORE` = 3 (line 86) -- `CONTEXT_VAULT_IO_BALANCE_DIFF` = 4 (line 92) -- `CONTEXT_VAULT_IO_ROWS` = 5 (line 94) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` = 5 (line 98) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` = 1 (line 99) -- `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW` = 0 (line 100) -- `CONTEXT_SIGNED_CONTEXT_START_COLUMN` = 6 (line 104) -- `CONTEXT_SIGNED_CONTEXT_START_ROWS` = 1 (line 105) -- `CONTEXT_SIGNED_CONTEXT_START_ROW` = 0 (line 106) - -## Findings - -### A11-1: Unused Imports from LibContext.sol [LOW] - -Lines 6-10 import four symbols from `rain.interpreter.interface/lib/caller/LibContext.sol`: -- `CONTEXT_BASE_ROWS` -- `CONTEXT_BASE_ROW_SENDER` -- `CONTEXT_BASE_ROW_CALLING_CONTRACT` -- `CONTEXT_BASE_COLUMN` - -These four constants are **not used within `LibOrderBook.sol` itself**. They are only consumed by `LibOrderBookSubParser.sol`, which imports them transitively via `"./LibOrderBook.sol"` (LibOrderBookSubParser.sol line 9). - -Re-exporting symbols through a file that does not use them is a leaky abstraction. It couples `LibOrderBookSubParser` to `LibOrderBook` for symbols that `LibOrderBook` neither defines nor consumes. If these constants were removed from the import in LibOrderBook.sol, the downstream consumer would need to import them directly from their source, which is the correct dependency. - -Similarly, `LibContext` is imported on line 19 but is only used in `doPost` (line 128 via `LibContext.build`). This import is legitimately used, so it is fine. - -**Recommendation:** Move the four `CONTEXT_BASE_*` imports out of `LibOrderBook.sol`. Update `LibOrderBookSubParser.sol` to import them directly from `rain.interpreter.interface/lib/caller/LibContext.sol`. - ---- - -**No other findings.** No commented-out code, no bare `src/` imports (all imports use remapped or relative paths), no style inconsistencies within the file. The `doPost` function is clean and well-structured. The pragma `^0.8.19` is consistent with sibling files. diff --git a/audit/2026-03-14-01/pass4/A12-LibOrderBookArb.md b/audit/2026-03-14-01/pass4/A12-LibOrderBookArb.md deleted file mode 100644 index 74cb56215b..0000000000 --- a/audit/2026-03-14-01/pass4/A12-LibOrderBookArb.md +++ /dev/null @@ -1,39 +0,0 @@ -# A12 - LibOrderBookArb.sol - Pass 4 (Code Quality) - -**File:** `src/lib/LibOrderBookArb.sol` -**Lines:** 77 - -## Evidence Inventory - -### Library -- `LibOrderBookArb` (library) - line 14 - -### Functions -- `finalizeArb(TaskV2 memory task, address ordersInputToken, uint8 inputDecimals, address ordersOutputToken, uint8 outputDecimals)` (internal) - line 20 - -### Imports (lines 5-11) -- `TaskV2` from `rain.raindex.interface/interface/IRaindexV6.sol` - line 5 -- `IERC20` from `openzeppelin-contracts/contracts/token/ERC20/IERC20.sol` - line 6 -- `LibOrderBook` from `./LibOrderBook.sol` - line 7 -- `Address` from `openzeppelin-contracts/contracts/utils/Address.sol` - line 8 -- `SafeERC20` from `openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol` - line 9 -- **`IERC20Metadata`** from `openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol` - line 10 -- `LibDecimalFloat`, `Float` from `rain.math.float/lib/LibDecimalFloat.sol` - line 11 - -### Using-for -- `SafeERC20 for IERC20` - line 15 - -### Constants / Types / Errors -- (none) - -## Findings - -### A12-1: Unused Import `IERC20Metadata` [LOW] - -Line 10 imports `IERC20Metadata` from OpenZeppelin, but it is never referenced in the file body. The `finalizeArb` function receives token decimals as pre-resolved `uint8` parameters rather than calling `IERC20Metadata.decimals()` on-chain. This is dead code that will generate a compiler warning in Solidity 0.8.25+ (the version used by the concrete contracts that compile this library). - -**Recommendation:** Remove the unused import on line 10. - ---- - -**No other findings.** No commented-out code (the `//slither-disable` and `// forge-lint:` annotations are legitimate suppression directives, not commented-out code). No bare `src/` imports. The pragma `^0.8.19` matches sibling library files. The internal structure is clean: scoped blocks keep local variables tight, and the post-task delegation to `LibOrderBook.doPost` is a well-chosen abstraction boundary. diff --git a/audit/2026-03-14-01/pass4/A13-LibOrderBookSubParser.md b/audit/2026-03-14-01/pass4/A13-LibOrderBookSubParser.md deleted file mode 100644 index 0f73498a3b..0000000000 --- a/audit/2026-03-14-01/pass4/A13-LibOrderBookSubParser.md +++ /dev/null @@ -1,108 +0,0 @@ -# A13 - LibOrderBookSubParser.sol - Pass 4 (Code Quality) - -**File:** `src/lib/LibOrderBookSubParser.sol` - -## Evidence - -**Contract/Library:** `LibOrderBookSubParser` (library) - -**Pragma:** `^0.8.19` (line 3) - -**Imports (lines 5-47):** -- `AuthoringMetaV2`, `OperandV2` from `rain.interpreter.interface/interface/ISubParserV4.sol` -- `LibUint256Matrix` from `rain.solmem/lib/LibUint256Matrix.sol` -- `LibSubParse` from `rain.interpreter/lib/parse/LibSubParse.sol` -- 40+ context constants from `./LibOrderBook.sol` - -**File-level constants (lines 49-96):** -- `SUB_PARSER_WORD_PARSERS_LENGTH` (line 49) = 2 -- `EXTERN_PARSE_META_BUILD_DEPTH` (line 50) = 1 -- `WORD_ORDER_CLEARER` through `WORD_WITHDRAW_TARGET_AMOUNT` (lines 52-81) -- `DEPOSIT_WORD_*` constants (lines 83-88) -- `WITHDRAW_WORD_*` constants (lines 90-96) - -**Functions (all `internal pure`):** -- `subParserSender` (line 105) -- `subParserCallingContract` (line 111) -- `subParserOrderHash` (line 121) -- `subParserOrderOwner` (line 130) -- `subParserOrderCounterparty` (line 140) -- `subParserMaxOutput` (line 152) -- `subParserIORatio` (line 161) -- `subParserInputToken` (line 171) -- `subParserInputTokenDecimals` (line 182) -- `subParserInputVaultId` (line 191) -- `subParserInputBalanceBefore` (line 202) -- `subParserInputBalanceDiff` (line 211) -- `subParserOutputToken` (line 222) -- `subParserOutputTokenDecimals` (line 231) -- `subParserOutputVaultId` (line 241) -- `subParserOutputBalanceBefore` (line 251) -- `subParserOutputBalanceDiff` (line 261) -- `subParserSigners` (line 273) -- `subParserDepositToken` (line 283) -- `subParserDepositVaultId` (line 293) -- `subParserDepositVaultBalanceBefore` (line 304) -- `subParserDepositVaultBalanceAfter` (line 317) -- `subParserWithdrawToken` (line 330) -- `subParserWithdrawVaultId` (line 340) -- `subParserWithdrawVaultBalanceBefore` (line 351) -- `subParserWithdrawVaultBalanceAfter` (line 364) -- `subParserWithdrawTargetAmount` (line 377) -- `subParserSignedContext` (line 390) -- `authoringMetaV2` (line 406) - -## Findings - -### A13-1: Pragma version inconsistency (LOW) - -**Location:** Line 3 - -This file uses `pragma solidity ^0.8.19` while the concrete contracts that consume it (e.g., `OrderBookV6SubParser.sol`) pin `=0.8.25`, and the project-wide `foundry.toml` specifies `solc = "0.8.25"`. Other library files in `src/lib/` also vary: `LibOrder.sol` uses `^0.8.18`, `LibOrderBook.sol` uses `^0.8.19`, and `src/lib/deploy/` files use `^0.8.25`. - -While floating pragmas on library files are acceptable when they truly need backward compatibility, having three different minimum versions (`^0.8.18`, `^0.8.19`, `^0.8.25`) across `src/lib/` is an inconsistency that makes it harder to reason about which compiler features are available in each file. - -### A13-2: Unused constant `SUB_PARSER_WORD_PARSERS_LENGTH` (INFO) - -**Location:** Line 49 - -The constant `SUB_PARSER_WORD_PARSERS_LENGTH = 2` is defined here and imported by `OrderBookV6SubParser.sol`, but it is imported only -- it does not appear to be used in the body of `OrderBookV6SubParser.sol`. The value `2` also does not correspond to any obvious count of parsers in the current code (the file defines 29 sub-parser functions). This constant may be vestigial. Flagged as INFO because it compiles without warnings and does not affect behavior. - -### A13-3: Inconsistent indexing style in `authoringMetaV2` for deposit metadata (LOW) - -**Location:** Lines 558-579 - -The deposit metadata array is indexed using a mixture of named constants and offset arithmetic: - -```solidity -depositMeta[0] = ... // uses literal 0 for DEPOSIT_WORD_DEPOSITOR -depositMeta[CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN + 1] = ... -depositMeta[CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID + 1] = ... -``` - -In contrast, the withdraw metadata (lines 584-617) uses the dedicated `WITHDRAW_WORD_*` constants consistently: - -```solidity -withdrawMeta[WITHDRAW_WORD_WITHDRAWER] = ... -withdrawMeta[WITHDRAW_WORD_TOKEN] = ... -``` - -The deposit section should use the `DEPOSIT_WORD_*` constants (`DEPOSIT_WORD_DEPOSITOR`, `DEPOSIT_WORD_TOKEN`, etc.) that already exist (lines 83-88) for the same reason the withdraw section does -- readability and single-source-of-truth indexing. The `+ 1` offset pattern is fragile if the calling-context row constants ever change independently. - -### A13-4: No commented-out code found (INFO) - -No commented-out code was found in this file. All `//` comments are either slither/forge-lint directives or documentation. - -### A13-5: No bare `src/` imports (INFO) - -All imports in this file use remapped paths (e.g., `rain.interpreter.interface/...`) or relative paths (`./LibOrderBook.sol`). No bare `src/` imports that would break submodule usage. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| A13-1 | LOW | Pragma version inconsistency across `src/lib/` files | -| A13-2 | INFO | `SUB_PARSER_WORD_PARSERS_LENGTH` appears unused in consuming contract | -| A13-3 | LOW | Deposit metadata uses `CONTEXT_*_ROW + 1` offsets instead of `DEPOSIT_WORD_*` constants | -| A13-4 | INFO | No commented-out code | -| A13-5 | INFO | No bare `src/` imports | diff --git a/audit/2026-03-14-01/pass4/A14-LibOrderBookDeploy.md b/audit/2026-03-14-01/pass4/A14-LibOrderBookDeploy.md deleted file mode 100644 index 29228f8750..0000000000 --- a/audit/2026-03-14-01/pass4/A14-LibOrderBookDeploy.md +++ /dev/null @@ -1,63 +0,0 @@ -# A14 - LibOrderBookDeploy.sol - Pass 4 (Code Quality) - -**File:** `src/lib/deploy/LibOrderBookDeploy.sol` - -## Evidence - -**Contract/Library:** `LibOrderBookDeploy` (library) - -**Pragma:** `^0.8.25` (line 3) - -**Imports (lines 5-21):** -- `Vm` from `forge-std/Vm.sol` (line 5) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` (as `ORDERBOOK_HASH`, `ORDERBOOK_ADDR`, `ORDERBOOK_RUNTIME_CODE`) from `../../generated/OrderBookV6.pointers.sol` (lines 7-11) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` (as `SUB_PARSER_HASH`, `SUB_PARSER_ADDR`, `SUB_PARSER_RUNTIME_CODE`) from `../../generated/OrderBookV6SubParser.pointers.sol` (lines 12-16) -- `BYTECODE_HASH`, `DEPLOYED_ADDRESS`, `RUNTIME_CODE` (as `ROUTE_PROCESSOR_HASH`, `ROUTE_PROCESSOR_ADDR`, `ROUTE_PROCESSOR_RUNTIME_CODE`) from `../../generated/RouteProcessor4.pointers.sol` (lines 17-21) - -**Constants (lines 32-52):** -- `ORDERBOOK_DEPLOYED_ADDRESS` (line 32) -- `ORDERBOOK_DEPLOYED_CODEHASH` (line 36) -- `SUB_PARSER_DEPLOYED_ADDRESS` (line 40) -- `SUB_PARSER_DEPLOYED_CODEHASH` (line 44) -- `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` (line 48) -- `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` (line 52) - -**Functions:** -- `etchOrderBook(Vm vm)` internal (line 58) - -## Findings - -### A14-1: Production library depends on forge-std/Vm.sol (MEDIUM) - -**Location:** Line 5 - -`LibOrderBookDeploy.sol` lives under `src/lib/deploy/` (not `test/` or `script/`) and imports `Vm` from `forge-std/Vm.sol`. This is a test/script-only type -- `Vm` is the Forge cheatcode interface. Placing this in `src/` means: - -1. **Leaky abstraction:** Production source code (`src/`) depends on a test framework type, blurring the boundary between production and test concerns. -2. **Submodule/library consumers** who import this project's `src/` tree will pull in a transitive dependency on `forge-std` even if they only want production contracts. -3. **Foundry convention:** The standard convention is that `src/` contains only production code. Files that depend on `Vm` belong in `test/` or `script/`. - -The `etchOrderBook` function is only used in test and script contexts. This library should either be moved to `test/` or `script/`, or the `etchOrderBook` function should be extracted to a test helper, leaving only the constants in `src/`. - -### A14-2: Redundant constant aliases (INFO) - -**Location:** Lines 32-52 - -The six constants (`ORDERBOOK_DEPLOYED_ADDRESS`, `ORDERBOOK_DEPLOYED_CODEHASH`, etc.) are direct aliases of the imported values (`ORDERBOOK_ADDR`, `ORDERBOOK_HASH`, etc.) with no transformation. This is a stylistic choice that provides slightly more descriptive names at the cost of adding indirection. It is not a defect but adds cognitive overhead because a reader must trace through two layers of naming to find the actual values. - -### A14-3: No commented-out code found (INFO) - -No commented-out code in this file. - -### A14-4: No bare `src/` imports (INFO) - -All imports use relative paths (`../../generated/...`) or remapped paths (`forge-std/`). No bare `src/` imports. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| A14-1 | MEDIUM | Production `src/` library imports forge-std `Vm` -- test dependency leaks into production source tree | -| A14-2 | INFO | Constants are redundant aliases of imported values | -| A14-3 | INFO | No commented-out code | -| A14-4 | INFO | No bare `src/` imports | diff --git a/audit/2026-03-14-01/pass4/A15-LibRouteProcessor4CreationCode.md b/audit/2026-03-14-01/pass4/A15-LibRouteProcessor4CreationCode.md deleted file mode 100644 index bee6272e2c..0000000000 --- a/audit/2026-03-14-01/pass4/A15-LibRouteProcessor4CreationCode.md +++ /dev/null @@ -1,56 +0,0 @@ -# A15 - LibRouteProcessor4CreationCode.sol - Pass 4 (Code Quality) - -**File:** `src/lib/deploy/LibRouteProcessor4CreationCode.sol` - -## Evidence - -**Contract/Library:** File-level constant only (no library/contract defined) - -**Pragma:** `^0.8.25` (line 3) - -**Imports:** None - -**Constants:** -- `ROUTE_PROCESSOR_4_CREATION_CODE` (line 13) -- a `bytes constant` containing the full creation bytecode of SushiSwap's RouteProcessor4, including constructor args. The hex literal is approximately 16KB. - -**Functions:** None - -## Findings - -### A15-1: Large inline hex literal is not practically auditable (INFO) - -**Location:** Line 13 - -The file contains a single ~16KB hex literal representing the full creation bytecode of an external (SushiSwap) contract. The NatSpec (lines 5-12) cites two sources for verification: -1. The SushiSwap GitHub deployments JSON -2. Etherscan deployment at `0xe43ca1dee3f0fc1e2df73a0745674545f11a59f5` - -This is the correct approach for embedding third-party bytecode. The provenance is documented and cross-referenceable. Flagged as INFO only because the hex blob is inherently not human-reviewable; the trust model relies on verifying against the cited sources. - -### A15-2: No commented-out code (INFO) - -No commented-out code in this file. - -### A15-3: No bare `src/` imports (INFO) - -This file has no imports at all. - -### A15-4: Constructor args embedded in creation code lack separate documentation (INFO) - -**Location:** Line 12 - -The NatSpec mentions that constructor args are appended and translate to `address(0)` for bento and no owner addresses, but the actual constructor arg bytes are not separated from the main bytecode in the hex literal. If the constructor args ever need to change (e.g., different owner or bento address for a different deployment), the entire constant must be replaced. This is an acceptable design given the intent is to deploy an exact replica, but worth noting for maintainability. - -### A15-5: Pragma and style consistent with sibling file (INFO) - -This file uses `^0.8.25`, matching its sibling `LibOrderBookDeploy.sol` in the same directory. No style inconsistencies within the `deploy/` directory. - -## Summary - -| ID | Severity | Description | -|----|----------|-------------| -| A15-1 | INFO | Large hex literal is not practically auditable; provenance is documented | -| A15-2 | INFO | No commented-out code | -| A15-3 | INFO | No bare `src/` imports | -| A15-4 | INFO | Constructor args embedded inline without separate documentation of the arg boundary | -| A15-5 | INFO | Pragma and style consistent with sibling | diff --git a/audit/2026-03-14-01/pass5/A01-OrderBookV6ArbCommon.md b/audit/2026-03-14-01/pass5/A01-OrderBookV6ArbCommon.md deleted file mode 100644 index fe3d9a90c7..0000000000 --- a/audit/2026-03-14-01/pass5/A01-OrderBookV6ArbCommon.md +++ /dev/null @@ -1,67 +0,0 @@ -# A01 - Pass 5: Correctness / Intent Verification -## File: `src/abstract/OrderBookV6ArbCommon.sol` - -## Evidence: Source Inventory - -**Contract**: `OrderBookV6ArbCommon` (abstract, lines 29-60) - -| Item | Kind | Line | -|------|------|------| -| `OrderBookV6ArbConfig` | struct | 13-16 | -| `WrongTask` | error | 19 | -| `BEFORE_ARB_SOURCE_INDEX` | constant | 23 | -| `Construct` | event | 35 | -| `iTaskHash` | immutable | 39 | -| `constructor` | function | 42-49 | -| `onlyValidTask` | modifier | 54-59 | - -## Analysis - -### Constants and Magic Numbers - -**BEFORE_ARB_SOURCE_INDEX (line 23)** -- Declared as `SourceIndexV2.wrap(0)`. -- NatSpec says: "Before arb" is evaluated before the arb is executed. -- **Problem**: This constant is declared but never referenced in any production code. It is imported by one test file (`GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol`) but even there it is unused -- only `WrongTask` from that import line is actually used. The `doPost` function in `LibOrderBook` hardcodes `SourceIndexV2.wrap(0)` directly rather than using this constant. The constant's NatSpec describes "before arb" semantics, but the actual usage context is "post arb" task evaluation in `doPost`. The name and documentation are misleading: there is no "before arb" evaluation in the current codebase. - -### NatSpec vs. Implementation - -1. **Struct `OrderBookV6ArbConfig` (line 10-16)**: NatSpec says `task` is "The task to run as post for each arb" and `implementationData` is "The constructor data for the specific implementation." Both match the constructor behavior. Correct. - -2. **Error `WrongTask` (line 18-19)**: NatSpec says "Thrown when the task does not match the expected hash." The modifier `onlyValidTask` (line 55) reverts with `WrongTask` when `iTaskHash != bytes32(0) && iTaskHash != keccak256(abi.encode(task))`. This matches -- the error is thrown exactly when a non-zero task hash does not match the provided task. Correct. - -3. **Event `Construct` (line 33-35)**: NatSpec says "Emitted on construction with the full config" with sender and config params. The constructor (line 44) emits `Construct(msg.sender, config)`. Correct. - -4. **`iTaskHash` (line 37-39)**: NatSpec says "Hash of the configured task, or `bytes32(0)` if no task was set." The constructor sets it to `keccak256(abi.encode(config.task))` when bytecode is non-empty, and leaves it as the default `0` otherwise. Correct. - -5. **`onlyValidTask` (line 51-58)**: NatSpec says "Reverts with `WrongTask` if `iTaskHash` is nonzero and does not match the hash of the provided task. Passes through if no task was configured." The implementation at line 55 checks `iTaskHash != bytes32(0) && iTaskHash != keccak256(abi.encode(task))`, which matches exactly: when iTaskHash is zero (no task configured), the first condition is false and execution passes through; when non-zero and mismatched, it reverts. Correct. - -### Tests vs. Claims - -1. **`testITaskHashNonEmpty`**: Claims iTaskHash equals keccak256 of the task when constructed with non-empty bytecode. Creates a task with `hex"deadbeef"` bytecode, deploys, and asserts equality. Correctly exercises the claim. - -2. **`testITaskHashEmpty`**: Claims iTaskHash is bytes32(0) when constructed with empty bytecode. Creates a task with `hex""` bytecode, deploys, and asserts zero. Correctly exercises the claim. - -3. **`testFallbackAcceptsCalldata` / `testFallbackAcceptsEmptyCalldata` / `testReceiveAcceptsETH` / `testFallbackAcceptsETHWithCalldata`** (in `OrderBookV6ArbCommon.fallback.t.sol`): These test the fallback behavior of the concrete `GenericPoolOrderBookV6ArbOrderTaker`, not `OrderBookV6ArbCommon` itself. The file is named `OrderBookV6ArbCommon.fallback.t.sol` but also contains `OrderBookV6FlashBorrowerFallbackTest`. The tests correctly exercise fallback/receive behavior on both contract types. Tests match their names. - -### Interface Conformance - -`OrderBookV6ArbCommon` does not claim to implement any interface. Correct. - -### Error Conditions vs. Triggers - -**WrongTask**: Triggered when `iTaskHash != bytes32(0) && iTaskHash != keccak256(abi.encode(task))`. The name "WrongTask" accurately describes this: the provided task is wrong (doesn't match). Correct. - -## Findings - -### A01-1: Unused constant `BEFORE_ARB_SOURCE_INDEX` with misleading NatSpec - -**Severity**: LOW - -`BEFORE_ARB_SOURCE_INDEX` at line 23 is declared as `SourceIndexV2.wrap(0)` with NatSpec describing "before arb" evaluation semantics. However: - -1. The constant is never used in any production code. The only reference is an unused import in a test file. -2. The name and NatSpec describe "before arb" evaluation, but no such evaluation exists in the current codebase. The task evaluation in `LibOrderBook.doPost` happens *after* the arb, and it hardcodes `SourceIndexV2.wrap(0)` directly rather than referencing this constant. -3. This is dead code with misleading documentation that could confuse future developers or auditors into believing a "before arb" access control mechanism exists. - -**Location**: `src/abstract/OrderBookV6ArbCommon.sol:21-23` diff --git a/audit/2026-03-14-01/pass5/A02-OrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass5/A02-OrderBookV6ArbOrderTaker.md deleted file mode 100644 index 7fcc5083da..0000000000 --- a/audit/2026-03-14-01/pass5/A02-OrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,75 +0,0 @@ -# A02 - Pass 5: Correctness / Intent Verification -## File: `src/abstract/OrderBookV6ArbOrderTaker.sol` - -## Evidence: Source Inventory - -**Contract**: `OrderBookV6ArbOrderTaker` (abstract, lines 20-71) - -| Item | Kind | Line | -|------|------|------| -| `supportsInterface` | function | 32-35 | -| `arb5` | function | 38-64 | -| `onTakeOrders2` | function | 70 | - -**Inheritance**: `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -## Analysis - -### Interface Conformance - -1. **IRaindexV6ArbOrderTaker**: Requires `arb5(IRaindexV6, TakeOrdersConfigV5 calldata, TaskV2 calldata) external payable`. The implementation at line 38 matches this signature exactly. Correct. - -2. **IRaindexV6OrderTaker**: Requires `onTakeOrders2(address, address, Float, Float, bytes calldata) external`. The implementation at line 70 matches. However, the interface NatSpec states "Implementations MUST validate that `msg.sender` is the trusted Raindex contract." The implementation is a deliberate empty no-op with a dev comment (line 67-69) explaining: "Empty no-op. The contract holds no value between operations and the caller chooses which orderbook to interact with, so there is nothing to protect via `msg.sender` validation here." This is a design decision documented in-code -- the abstract contract intentionally does not validate `msg.sender` because the contract is stateless between arb operations and there is nothing to extract. The concrete `GenericPoolOrderBookV6ArbOrderTaker` overrides `onTakeOrders2` to do approve-call-revoke on caller-controlled addresses, which is also safe because the caller controls the data anyway. This design is intentional and documented. - -3. **IRaindexV6ArbOrderTaker** NatSpec says "Implementations MUST validate that `raindex` is a trusted contract." The `arb5` implementation does NOT validate that the `orderBook` parameter is a trusted contract. However, since the contract holds no persistent value and the caller controls which orderbook to interact with, a malicious orderbook can only cause the transaction to revert or succeed -- the caller is the one at risk, and they chose the orderbook. This appears to be an intentional design decision consistent with the `onTakeOrders2` reasoning. - -4. **IERC165**: `supportsInterface` reports `IRaindexV6OrderTaker`, `IRaindexV6ArbOrderTaker`, and delegates to `super.supportsInterface` (which covers `IERC165`). Correct. - -### NatSpec vs. Implementation - -1. **`@inheritdoc IERC165` on `supportsInterface` (line 31)**: Implementation checks three interface IDs. Matches the inheritance chain. Correct. - -2. **`@inheritdoc IRaindexV6ArbOrderTaker` on `arb5` (line 37)**: The function takes orders from the orderbook and finalizes the arb. The implementation: - - Reverts with `NoOrders` if empty (line 45-47). This matches the comment "Mimic what OB would do anyway." - - Reads `ordersInputToken` and `ordersOutputToken` from the first order (lines 49-50). - - Approves the orderbook for inputToken, calls `takeOrders4`, then revokes approval (lines 52-55). - - Calls `finalizeArb` to sweep balances to `msg.sender` (lines 57-63). - All correct. - -3. **`@inheritdoc IRaindexV6OrderTaker` on `onTakeOrders2` (line 66)**: Dev comment says "Empty no-op." The function body is empty. Correct. - -### Algorithms and Formulas - -The `arb5` flow: -1. Approve `ordersInputToken` to orderbook (max). -2. Call `orderBook.takeOrders4(takeOrders)` -- this sends `ordersOutputToken` to the contract and pulls `ordersInputToken` via the `onTakeOrders2` callback. -3. Revoke approval to 0. -4. `finalizeArb` sweeps remaining balances to `msg.sender`. - -The approval is on `ordersInputToken` because that is what the orderbook will pull from this contract. The orderbook sends `ordersOutputToken` to this contract. This is correct per the orderbook's perspective: the taker's input is what the taker sends to the orderbook. - -### Tests vs. Claims - -1. **`testOrderBookV6ArbOrderTakerIERC165`** (ierc165.t.sol): Fuzz tests that the three expected interface IDs return true and any other ID returns false. Uses `vm.assume` to exclude the three known IDs. Correctly exercises the claim. - -2. **`testArb5NoOrders`** (noOrders.t.sol): Tests that `arb5` with empty orders reverts with `NoOrders`. Sets up the call and expects the revert. Correctly exercises the claim. - -3. **`testArb5Reentrancy`** (reentrancy.t.sol): Tests that re-entering `arb5` from a `takeOrders4` callback reverts with `ReentrancyGuardReentrantCall`. Uses a `ReentrantMockOrderBook` that calls `arb5` inside its `takeOrders4`. Correctly exercises the claim. - -4. **`testOnTakeOrders2DirectCallSucceeds`** (onTakeOrders2Direct.t.sol): Tests that calling `onTakeOrders2` directly from an arbitrary address succeeds (no-op) and the contract remains empty. Correctly exercises the claim that there's no `msg.sender` validation. - -5. **`testArb5RealTokenTransfers`** (onTakeOrders2.t.sol): Tests a full arb cycle with real ERC20 transfers using `RealisticOrderTakerMockOrderBook` and `MockExchange`. Verifies tokens end up in the right places and the arb contract is empty afterward. Correctly exercises the full flow. - -6. **`testOrderBookV6ArbOrderTakerContext`** (context.t.sol): Tests that the task context column contains the correct values (input balance, output balance, gas balance as Floats). Uses a `ChildOrderBookV6ArbOrderTaker` with a Rain expression that asserts on context values. The mock balances are `3e12` and `4e12` with 12 decimals, and the expression checks `context<1 0>() == 3`, `context<1 1>() == 4`, `context<1 2>() == 5` (from `5e18` wei / 18 decimals = 5). Correctly exercises the context passing claim. - -7. **`testGenericPoolTakeOrdersWrongExpression`** (expression.t.sol): Fuzz tests that `arb5` reverts with `WrongTask` when the provided task doesn't match construction. Correctly exercises the claim. - -8. **`testGenericPoolTakeOrdersExpression`** (expression.t.sol): Tests that a matching task causes the expression to be evaluated. Uses mock calls to verify the interpreter's `eval4` is called. Correctly exercises the claim. - -### Error Conditions vs. Triggers - -1. **`IRaindexV6.NoOrders`** (line 46): Triggered when `takeOrders.orders.length == 0`. The error name accurately describes the condition. Correct. - -## Findings - -No findings. All NatSpec matches implementation, all tests correctly exercise their stated claims, interface conformance is satisfied (with documented intentional deviation from MUST requirements in the interface), and all error conditions match their names. diff --git a/audit/2026-03-14-01/pass5/A03-OrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass5/A03-OrderBookV6FlashBorrower.md deleted file mode 100644 index aaef4164d4..0000000000 --- a/audit/2026-03-14-01/pass5/A03-OrderBookV6FlashBorrower.md +++ /dev/null @@ -1,120 +0,0 @@ -# A03 - Pass 5: Correctness / Intent Verification -## File: `src/abstract/OrderBookV6FlashBorrower.sol` - -## Evidence: Source Inventory - -**Contract**: `OrderBookV6FlashBorrower` (abstract, lines 60-167) - -| Item | Kind | Line | -|------|------|------| -| `BadInitiator` | error | 20 | -| `BadLender` | error | 25 | -| `FlashLoanFailed` | error | 28 | -| `supportsInterface` | function | 66-68 | -| `_exchange` | function (virtual) | 79 | -| `onFlashLoan` | function | 82-108 | -| `arb4` | function | 129-166 | - -**Inheritance**: `IERC3156FlashBorrower`, `ReentrancyGuard`, `ERC165`, `OrderBookV6ArbCommon` - -## Analysis - -### Interface Conformance - -1. **IERC3156FlashBorrower**: Requires `onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32)`. The implementation at line 82 matches this signature. The return value is `ON_FLASH_LOAN_CALLBACK_SUCCESS` which is `keccak256("ERC3156FlashBorrower.onFlashLoan")` as specified by ERC-3156. Correct. - -2. **IERC165**: `supportsInterface` reports `IERC3156FlashBorrower` and delegates to `super.supportsInterface` (covering `IERC165`). Correct. - -### NatSpec vs. Implementation - -1. **Error `BadInitiator` (line 18-20)**: NatSpec says "Thrown when the flash loan initiator is not this contract." The `onFlashLoan` at line 88-89 checks `initiator != address(this)` and reverts with `BadInitiator(initiator)`. Matches exactly. - -2. **Error `BadLender` (line 23-25)**: NatSpec says "Thrown when onFlashLoan is called by an address other than the deterministic orderbook deployment." The `onFlashLoan` at line 84-86 checks `msg.sender != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS` and reverts with `BadLender(msg.sender)`. Matches exactly. - -3. **Error `FlashLoanFailed` (line 27-28)**: NatSpec says "Thrown when the flash loan fails somehow." The `arb4` at line 159-161 checks `!orderBook.flashLoan(...)` and reverts with `FlashLoanFailed()`. Matches. - -4. **`_exchange` hook (line 70-79)**: NatSpec says it is "responsible for converting the flash loaned assets into the assets required to fill the orders." The default implementation is an empty no-op with a comment about "raising the ambient temperature of the room." The `SHOULD override` language is appropriate for an abstract contract with a virtual hook. Correct. - -5. **`onFlashLoan` (line 81-108)**: NatSpec is `@inheritdoc IERC3156FlashBorrower`. The implementation: - - Validates `msg.sender` is the deterministic orderbook (line 84-86). - - Validates `initiator` is `address(this)` (line 88-89). - - Decodes `data` as `(TakeOrdersConfigV5, bytes)` (line 92-93). - - Calls `_exchange` hook (line 97). - - Calls `takeOrders4` on the lender/orderbook (line 105). - - Returns `ON_FLASH_LOAN_CALLBACK_SUCCESS` (line 107). - All correct per ERC-3156 and the contract's documented intent. - -6. **`arb4` (line 110-166)**: NatSpec describes the full flash loan arbitrage flow. The implementation: - - Checks empty orders (line 136-138). Matches "Mimic what OB would do anyway." - - Encodes data for flash loan callback (line 141). - - Reads `ordersOutputToken` and `ordersInputToken` from first order (lines 144-145). - - Gets decimals for both tokens (lines 147-148). - - Computes flash loan amount from `takeOrders.minimumIO` using output decimals (line 152). The NatSpec says "We can't repay more than the minimum that the orders are going to give us and there's no reason to borrow less." This is correct: `minimumIO` is the minimum amount the taker expects to receive (in output tokens from orders), and the flash loan should borrow exactly that amount since it will be repaid from the order outputs. - - Approves both tokens to orderbook (lines 157-158). - - Calls `flashLoan` and checks return value (lines 159-161). - - Revokes approvals (lines 162-163). - - Calls `finalizeArb` (line 165). - All matches the documented intent. - -### Algorithms and Formulas - -**Flash loan amount calculation (line 152)**: -```solidity -uint256 flashLoanAmount = LibDecimalFloat.toFixedDecimalLossless(takeOrders.minimumIO, outputDecimals); -``` -`minimumIO` is a Float representing the minimum amount the taker will receive from the orders (in output token terms). The `toFixedDecimalLossless` converts this Float to a fixed-decimal integer using `outputDecimals`. This is correct because: -- The flash loan borrows the output token (what orders give us). -- We need to repay it, so we can't borrow more than we'll get. -- Borrowing exactly the minimum ensures we have enough to repay even if orders give us exactly the minimum. - -**Approval pattern (lines 157-163)**: -Both `ordersInputToken` and `ordersOutputToken` are approved to the orderbook: -- `ordersInputToken` approval: needed because inside `onFlashLoan`, `takeOrders4` is called which will pull `ordersInputToken` from this contract (the taker sends input to the orderbook). -- `ordersOutputToken` approval: needed for flash loan repayment -- the orderbook's `flashLoan` will pull back the borrowed output tokens. -Both approvals are revoked to 0 after the flash loan completes. Correct. - -### Tests vs. Claims - -1. **`testOrderBookV5FlashBorrowerIERC165`** (ierc165.t.sol): Note the test contract is named `OrderBookV5FlashBorrowerIERC165Test` but tests V6 functionality. This is a minor naming inconsistency (V5 vs V6), but the test correctly verifies that `IERC165` and `IERC3156FlashBorrower` interface IDs are supported and a random bad ID is not. The test function correctly exercises the claim. - -2. **`testOnFlashLoanBadInitiator`** (badInitiator.t.sol): Fuzz tests that `onFlashLoan` reverts with `BadInitiator` when called with any initiator other than the arb contract. Pranks as the deterministic orderbook address to isolate the initiator check. Correctly exercises the claim. - -3. **`testMaliciousLenderCannotExploitOnFlashLoan`** (lenderValidation.t.sol): Tests that a `MaliciousLender` calling `onFlashLoan` directly reverts with `BadLender` because `msg.sender` is not the deterministic orderbook. Correctly exercises the claim. - -4. **`testBadLenderRevertsWithApproval`** (badLenderApproval.t.sol): Tests that when `arb4` is called with a malicious orderbook, the entire tx reverts with `BadLender` and no approvals persist afterward. The `MaliciousOrderBook` records allowances during `flashLoan` before the `BadLender` check fires. After the revert, approvals are confirmed to be zero. Correctly exercises the claim that approvals don't persist on revert. - -5. **`testFlashLoanFailed`** (flashLoanFailed.t.sol): Tests that `arb4` reverts with `FlashLoanFailed` when the orderbook's `flashLoan` returns false. Uses a `FalseFlashLoanMockOrderBook` (inherits `MockOrderBookBase` default which returns false). Correctly exercises the claim. - -6. **`testArb4NoOrders`** (noOrders.t.sol): Tests that `arb4` with empty orders reverts with `NoOrders`. Correctly exercises the claim. - -7. **`testArb4WrongTask`** (wrongTask.t.sol): Fuzz tests that `arb4` reverts with `WrongTask` when the provided task doesn't match the construction task. Uses `vm.assume` to ensure at least one field differs. Correctly exercises the claim. - -8. **`testArb4RealTokenTransfers`** (realTokenTransfers.t.sol): Tests a full flash loan cycle with real ERC20 transfers. Verifies the orderbook receives input tokens, exchange receives output tokens, and arb contract is empty afterward. Correctly exercises the full flow. - -9. **`testArb4MixedDecimals`** (mixedDecimals.t.sol): Tests with 6-decimal output (USDT-like) and 18-decimal input (DAI-like) tokens. Verifies the flash loan amount uses output decimals correctly. The test passes without assertion failures, meaning the `toFixedDecimalLossless` conversion correctly handles mixed decimals. Correctly exercises the mixed-decimal claim. - -10. **`testExchangeRevertPropagates`** (exchangeRevert.t.sol): Tests that if the exchange reverts, the entire `arb4` reverts with the exchange's error message ("exchange failed"). Correctly exercises error propagation. - -11. **`testApprovalRevokedAfterExchange`** (approvalRevoked.t.sol): Tests that after a successful `arb4`, the spender's allowance is revoked to zero (approve-call-revoke pattern). Also verifies the exchange saw max approval during the call. Correctly exercises the claim. - -12. **`testEthForwardedToExchangeDuringExchange`** (ethForwarded.t.sol): Tests that ETH held by the arb contract is forwarded to the exchange pool via `functionCallWithValue` during `_exchange`, and that the arb contract has no remaining ETH afterward (swept by `finalizeArb`). Correctly exercises the claim. - -### Error Conditions vs. Triggers - -1. **`BadInitiator(address)`**: Triggered when `initiator != address(this)` in `onFlashLoan`. Name accurately describes: the initiator is bad (not this contract). Correct. - -2. **`BadLender(address)`**: Triggered when `msg.sender != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS` in `onFlashLoan`. Name accurately describes: the lender (caller) is bad (not the trusted orderbook). Correct. - -3. **`FlashLoanFailed()`**: Triggered when `orderBook.flashLoan(...)` returns false. Name accurately describes: the flash loan failed. Correct. - -4. **`IRaindexV6.NoOrders()`**: Triggered when `takeOrders.orders.length == 0`. Correct. - -## Findings - -### A03-1: Test contract name uses "V5" instead of "V6" - -**Severity**: INFO - -In `test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol`, the test contract is named `OrderBookV5FlashBorrowerIERC165Test` and the test function is named `testOrderBookV5FlashBorrowerIERC165`, despite testing `OrderBookV6FlashBorrower` functionality. This is a cosmetic naming inconsistency that could cause confusion when reading test output. - -**Location**: `test/abstract/OrderBookV6FlashBorrower.ierc165.t.sol:31,34` diff --git a/audit/2026-03-14-01/pass5/A04-OrderBookV6FlashLender.md b/audit/2026-03-14-01/pass5/A04-OrderBookV6FlashLender.md deleted file mode 100644 index f8bbf37a81..0000000000 --- a/audit/2026-03-14-01/pass5/A04-OrderBookV6FlashLender.md +++ /dev/null @@ -1,88 +0,0 @@ -# A04 -- Pass 5 (Correctness / Intent Verification) -- `src/abstract/OrderBookV6FlashLender.sol` - -## Evidence Inventory - -**Contract:** `OrderBookV6FlashLender` (abstract), lines 29-80 -**Inherits:** `IERC3156FlashLender`, `ERC165` -**Using:** `SafeERC20 for IERC20` (line 30) - -| Item | Kind | Line | -|------|------|------| -| `FlashLenderCallbackFailed` | error | 18 | -| `FLASH_FEE` | constant (`uint256`) | 23 | -| `supportsInterface` | function | 33 | -| `flashLoan` | function | 38 | -| `flashFee` | function | 70 | -| `maxFlashLoan` | function | 77 | - -### Test Files Reviewed - -| Test File | Tests | -|-----------|-------| -| `test/abstract/OrderBookV6FlashLender.fee.t.sol` | `testFlashFee` | -| `test/abstract/OrderBookV6FlashLender.griefRecipient.t.sol` | `testFlashLoanToNonReceiver` | -| `test/abstract/OrderBookV6FlashLender.ierc165.t.sol` | `testOrderBookV6FlashLenderIERC165` | -| `test/abstract/OrderBookV6FlashLender.maxFlashLoan.t.sol` | `testFlashMaxLoan` | -| `test/abstract/OrderBookV6FlashLender.mockSuccess.t.sol` | `testFlashLoanToReceiver` | -| `test/abstract/OrderBookV6FlashLender.reentrant.t.sol` | 7 reentrant tests | -| `test/abstract/OrderBookV6FlashLender.transfers.t.sol` | `testFlashLoanTransferSuccess`, `testFlashLoanTransferFail` | - -## Verification - -### Constants and Magic Numbers - -- **`FLASH_FEE = 0` (line 23):** The NatSpec at line 20-22 says the flash fee is always 0 because there is no entity to take revenue and it is more important that flash loans happen to connect external liquidity. The constant is `0`, the `flashFee` function returns `FLASH_FEE` (0), and `flashLoan` uses `amount + FLASH_FEE` (i.e., `amount + 0 = amount`). Intent matches behavior. - -- **`ON_FLASH_LOAN_CALLBACK_SUCCESS`:** Defined in the interface as `keccak256("ERC3156FlashBorrower.onFlashLoan")`. This matches the ERC-3156 specification exactly. - -### NatSpec vs. Implementation - -- **`flashLoan` (line 38):** The `@inheritdoc IERC3156FlashLender` correctly delegates documentation to the interface. The implementation sends `amount` tokens to `receiver`, calls `onFlashLoan`, checks the callback return, and pulls `amount + FLASH_FEE` back. This matches the ERC-3156 reference implementation. Correct. - -- **`flashFee` (line 70):** The `@inheritdoc IERC3156FlashLender` is present. Returns `FLASH_FEE` (0) for any token. See A04-1 for ERC-3156 conformance note. - -- **`maxFlashLoan` (line 77):** NatSpec says "There's no limit to the size of a flash loan from Orderbook other than the current tokens deposited in Orderbook." Implementation returns `IERC20(token).balanceOf(address(this))`. This accurately reflects the described behavior -- the maximum loanable amount is whatever the contract holds. - -- **Comment block lines 50-62:** The slither rationale explains why `safeTransferFrom` is safe here despite the `arbitrary-send-erc20` pattern. The reasoning is correct: (1) the tokens were just sent as part of the loan so pulling them back is net neutral, and (2) the receiver explicitly opted in by implementing `IERC3156FlashBorrower` and returning the success hash. - -### Error Conditions vs. Triggers - -- **`FlashLenderCallbackFailed(bytes32 result)` (line 18):** NatSpec says "Thrown when the `onFlashLoan` callback returns anything other than `ON_FLASH_LOAN_CALLBACK_SUCCESS`." The trigger at line 46-47 checks exactly `result != ON_FLASH_LOAN_CALLBACK_SUCCESS` and reverts with the bad `result`. Correct -- name, documentation, and trigger all align. - -### Interface Conformance: ERC-3156 - -- **`IERC3156FlashLender` interface satisfaction:** All three required functions (`flashLoan`, `flashFee`, `maxFlashLoan`) are implemented with matching signatures. The contract declares `is IERC3156FlashLender` (line 29). - -- **ERC-165 `supportsInterface`:** Returns true for `type(IERC3156FlashLender).interfaceId` and delegates to `super.supportsInterface` (which covers `IERC165` itself). Correct. - -- **`flashFee` spec deviation:** The ERC-3156 spec states "If the token is not supported `flashFee` MUST revert." This implementation returns 0 for all tokens unconditionally. However, in the context of OrderBook, all ERC20 tokens are "supported" -- the orderbook is token-agnostic and will lend any token it holds. The `maxFlashLoan` function correctly returns 0 for tokens not held by the contract (since `balanceOf` will return 0). The `flashLoan` function would simply transfer 0 tokens for a 0-amount loan. Since OrderBook intentionally supports all ERC20 tokens, always returning 0 from `flashFee` is consistent with the design intent. - -### Tests vs. Claims - -- **`testFlashFee` (fee.t.sol):** Fuzz-tests that `flashFee` returns 0 for any `(token, amount)`. Correctly exercises the claim that the fee is always 0. - -- **`testFlashLoanToNonReceiver` (griefRecipient.t.sol):** Tests three grief scenarios: (1) calling with an EOA receiver reverts, (2) calling with a contract returning wrong `bytes32` reverts with `FlashLenderCallbackFailed`, (3) calling with a contract returning non-`bytes32` data reverts. All three correctly verify the error path. The `vm.assume` on line 26 correctly excludes the ABI encoding of the success hash from the non-success bytes. - -- **`testOrderBookV6FlashLenderIERC165` (ierc165.t.sol):** Tests that both `IERC165` and `IERC3156FlashLender` interface IDs are supported, and that a fuzzed `badInterfaceId` (excluded from both valid IDs) returns false. Correct exercise of ERC-165. - -- **`testFlashMaxLoan` (maxFlashLoan.t.sol):** Mocks `balanceOf` to return `amount`, verifies `maxFlashLoan` returns the same. Correctly exercises the "max loan = balance" claim. - -- **`testFlashLoanToReceiver` (mockSuccess.t.sol):** Tests that a receiver returning `ON_FLASH_LOAN_CALLBACK_SUCCESS` causes `flashLoan` to return `true`. All token calls are mocked. Correctly exercises the success path. - -- **`testReenter*` (reentrant.t.sol):** Seven tests verify that various orderbook operations (read vault, check order exists, deposit, withdraw, add order, remove order, take orders, clear) can be reentered from within a flash loan callback. This correctly verifies that `flashLoan` does not use a reentrancy guard, allowing legitimate reentrant calls back into the orderbook. - -- **`testFlashLoanTransferSuccess` (transfers.t.sol):** Tests with real ERC20 tokens. Alice borrows, sends tokens to Bob who returns them, then loan repays. Also tests the failure path where Alice's callback returns the wrong value. Correctly exercises real token flows. The `bool success` parameter correctly toggles between success and failure paths. - -- **`testFlashLoanTransferFail` (transfers.t.sol):** Carol withholds some tokens, so Alice cannot repay the loan. When `success=false`, the callback failure error is caught first (before the transfer failure). When `success=true`, the callback succeeds but the `safeTransferFrom` reverts with `ERC20InsufficientBalance`. Correctly exercises the token shortfall path. - -## Findings - -No findings of severity LOW or higher. The implementation correctly matches the ERC-3156 specification and all NatSpec/comments accurately describe the code behavior. Tests are well-structured and exercise both success and failure paths. - -### A04-1 -- `flashFee` does not revert for unsupported tokens per ERC-3156 [INFO] - -The ERC-3156 spec says `flashFee` MUST revert if the token is not supported. This implementation returns 0 for all tokens. However, since OrderBook is designed to be token-agnostic (any ERC20 can be deposited and thus lent), all tokens are conceptually "supported." The behavioral impact is nil -- a caller querying `flashFee` for a token the orderbook does not hold would get 0 fee, and `maxFlashLoan` would correctly return 0 balance, preventing any actual loan. No fix needed. - -## Summary - -The `OrderBookV6FlashLender` implementation faithfully follows the ERC-3156 reference implementation. All NatSpec matches behavior. Constants are correct. Error conditions trigger appropriately. Tests comprehensively cover success paths, failure paths, grief attempts, and reentrancy scenarios with both mocked and real tokens. No correctness issues found. diff --git a/audit/2026-03-14-01/pass5/A05-GenericPoolOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass5/A05-GenericPoolOrderBookV6ArbOrderTaker.md deleted file mode 100644 index 53ccacf0d6..0000000000 --- a/audit/2026-03-14-01/pass5/A05-GenericPoolOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,90 +0,0 @@ -# A05 -- Pass 5 (Correctness / Intent Verification) -- `src/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sol` - -## Evidence Inventory - -**Contract:** `GenericPoolOrderBookV6ArbOrderTaker` (concrete), lines 14-47 -**Inherits:** `OrderBookV6ArbOrderTaker` -**Using:** `SafeERC20 for IERC20` (line 15), `Address for address` (line 16) - -| Item | Kind | Line | -|------|------|------| -| `constructor` | function | 18 | -| `onTakeOrders2` | function (override) | 21 | -| `receive` | function | 45 | -| `fallback` | function | 46 | - -### Parent Contract: `OrderBookV6ArbOrderTaker` (lines 20-71) - -| Item | Kind | Line | -|------|------|------| -| `constructor` | function | 29 | -| `supportsInterface` | function | 32 | -| `arb5` | function | 38 | -| `onTakeOrders2` | function (virtual, no-op) | 70 | - -### Test Files Reviewed - -| Test File | Tests | -|-----------|-------| -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.sender.t.sol` | `testGenericPoolTakeOrdersSender` | -| `test/concrete/arb/GenericPoolOrderBookV6ArbOrderTaker.expression.t.sol` | `testGenericPoolTakeOrdersWrongExpression`, `testGenericPoolTakeOrdersExpression` | -| `test/util/abstract/GenericPoolOrderBookV6ArbOrderTakerTest.sol` | test base | -| `test/util/abstract/ArbTest.sol` | shared test harness | - -## Verification - -### NatSpec vs. Implementation - -- **Contract NatSpec (lines 11-13):** "Order-taker arb that swaps via an arbitrary external pool call. The `takeOrdersData` is decoded as `(spender, pool, encodedFunctionCall)`." The implementation at lines 29-30 does exactly `abi.decode(takeOrdersData, (address, address, bytes))` decoding into `(spender, pool, encodedFunctionCall)`. Correct. - -- **`onTakeOrders2` override (line 21):** The `@inheritdoc OrderBookV6ArbOrderTaker` directive is correct. The function calls `super.onTakeOrders2(...)` first (the parent no-op at line 70 of `OrderBookV6ArbOrderTaker`), then executes the exchange logic. The `super` call is harmless (no-op) but ensures the override chain is respected. - -- **Approve-call-revoke comment (lines 32-34):** "the caller controls spender and pool, which is safe because the contract holds no tokens or ETH between arb operations -- there is nothing for a malicious caller to extract." This is correct: `finalizeArb` in `LibOrderBookArb` sweeps all tokens and ETH to `msg.sender` at the end of every `arb5` call, so the contract is empty between calls. The `nonReentrant` modifier on `arb5` prevents reentrancy that could exploit mid-transaction state. - -- **`receive()` / `fallback()` NatSpec (lines 43-44):** "Allow arbitrary calls and ETH transfers to this contract without reverting. Any ETH received is swept to msg.sender by finalizeArb." This is correct -- `LibOrderBookArb.finalizeArb` sends `address(this).balance` to `msg.sender` via `Address.sendValue`. - -### Parent `OrderBookV6ArbOrderTaker.arb5` (lines 38-64) - -- **Zero-order check (lines 45-47):** NatSpec says "Mimic what OB would do anyway if called with zero orders." Reverts with `IRaindexV6.NoOrders()`. This correctly pre-validates before making external calls. - -- **Token extraction (lines 49-50):** `ordersInputToken` is `takeOrders.orders[0].order.validInputs[takeOrders.orders[0].inputIOIndex].token` and `ordersOutputToken` is the corresponding output token. These are the tokens from the perspective of the ORDER, not the taker. The input token (what the order expects to receive) is what the taker needs to provide, so approving `ordersInputToken` to the orderbook (line 52) is correct -- the taker is giving `ordersInputToken` to fill the order. - -- **`onTakeOrders2` no-op (line 70):** The NatSpec says "Empty no-op. The contract holds no value between operations and the caller chooses which orderbook to interact with, so there is nothing to protect via `msg.sender` validation here." This is accurate -- the `onTakeOrders2` callback fires during `takeOrders4`, between token sends. The parent no-op is intentionally empty because the concrete `GenericPoolOrderBookV6ArbOrderTaker` overrides it to do the actual exchange. - -### Interface Conformance - -- **`IRaindexV6OrderTaker`:** The `onTakeOrders2` function signature matches the interface at `IRaindexV6OrderTaker.sol` line 37-43: `function onTakeOrders2(address inputToken, address outputToken, Float inputAmountSent, Float totalOutputAmount, bytes calldata takeOrdersData) external`. The override in `GenericPoolOrderBookV6ArbOrderTaker` has the same parameter types. Correct. - -- **`IRaindexV6ArbOrderTaker`:** The `arb5` function signature matches the interface: `function arb5(IRaindexV6 raindex, TakeOrdersConfigV5 calldata takeOrders, TaskV2 calldata task) external payable`. The implementation adds `nonReentrant` and `onlyValidTask(task)` modifiers. Correct. - -- **ERC-165:** `supportsInterface` returns true for both `IRaindexV6OrderTaker` and `IRaindexV6ArbOrderTaker` interface IDs plus `super` (which covers `IERC165`). Correct. - -### Algorithms: Approve-Call-Revoke in `onTakeOrders2` - -1. `IERC20(inputToken).forceApprove(spender, type(uint256).max)` -- Approves spender to spend the arb contract's input tokens. -2. `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` -- Calls the pool with the encoded function and forwards all ETH. -3. `IERC20(inputToken).forceApprove(spender, 0)` -- Revokes approval. - -This is a standard approve-call-revoke. The token being approved is `inputToken` which is the token the arb contract received from taking orders (the order's output token from the OB perspective). After the pool call, this token should have been swapped into the order's input token. The revoke on line 40 ensures no lingering approvals. Correct. - -### Tests vs. Claims - -- **`testGenericPoolTakeOrdersSender` (sender.t.sol):** Constructs a fuzzed order, builds take config via `buildTakeOrderConfig`, and calls `arb5`. The `takeOrdersData` is `abi.encode(iRefundoor, iRefundoor, "")` -- the pool is `Refundoor` which just sends back any ETH to `msg.sender`. The `FlashLendingMockOrderBook` processes the flash loan callback in the mock (for flash borrower tests) or `takeOrders4` for order taker tests. The test exercises the happy path with mocked OB interactions. It correctly validates that the call completes without reverting. - -- **`testGenericPoolTakeOrdersWrongExpression` (expression.t.sol):** Fuzz-tests that calling `arb5` with a task whose evaluable doesn't match the configured task hash reverts with `WrongTask`. The `vm.assume` correctly ensures at least one field differs. Correct exercise of the access control mechanism. - -- **`testGenericPoolTakeOrdersExpression` (expression.t.sol):** Tests that when the correct expression is provided, `eval4` is called on the interpreter with the expected parameters, and `set` is called on the store if `kvs.length > 0`. This verifies the post-arb task execution path. Correct. - -- **`ArbTest.buildTakeOrderConfig` (ArbTest.sol, lines 91-111):** The helper ensures `order.validInputs[inputIOIndex].token = address(iTakerOutput)` and `order.validOutputs[outputIOIndex].token = address(iTakerInput)`. Note the apparent swap: the ORDER's input is the TAKER's output (what the taker sends to fill the order), and the ORDER's output is the TAKER's input (what the taker receives). This is correct from the order's perspective. The naming `iTakerInput`/`iTakerOutput` is from the taker's perspective. - -### Test Coverage Observation - -- **No test for `receive()` / `fallback()` in the ArbOrderTaker context:** The `receive()` and `fallback()` functions are tested indirectly via the `FlashBorrower` variants (see `ethForwarded.t.sol`). For the `ArbOrderTaker`, ETH forwarding happens via `functionCallWithValue` to the pool, and the `Refundoor` mock sends ETH back. The test coverage is indirect but adequate since the `receive`/`fallback` are trivially empty payable functions. - -## Findings - -No findings of severity LOW or higher. The implementation correctly matches all documented intent. The approve-call-revoke pattern is correctly implemented. Interface conformance is complete. Tests exercise both the success path and the access control revert path. - -## Summary - -`GenericPoolOrderBookV6ArbOrderTaker` is a thin concrete implementation that adds generic pool exchange logic to the `OrderBookV6ArbOrderTaker` abstract base. The `onTakeOrders2` callback correctly decodes `(spender, pool, encodedFunctionCall)` as documented, implements approve-call-revoke correctly, and the `receive`/`fallback` functions enable ETH handling as documented. All tests accurately exercise the behaviors their names describe. diff --git a/audit/2026-03-14-01/pass5/A06-GenericPoolOrderBookV6FlashBorrower.md b/audit/2026-03-14-01/pass5/A06-GenericPoolOrderBookV6FlashBorrower.md deleted file mode 100644 index bcd0b78618..0000000000 --- a/audit/2026-03-14-01/pass5/A06-GenericPoolOrderBookV6FlashBorrower.md +++ /dev/null @@ -1,123 +0,0 @@ -# A06 -- Pass 5 (Correctness / Intent Verification) -- `src/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sol` - -## Evidence Inventory - -**Contract:** `GenericPoolOrderBookV6FlashBorrower` (concrete), lines 26-53 -**Inherits:** `OrderBookV6FlashBorrower` -**Using:** `SafeERC20 for IERC20` (line 27), `Address for address` (line 28) - -| Item | Kind | Line | -|------|------|------| -| `constructor` | function | 30 | -| `_exchange` | function (internal, override) | 33 | -| `receive` | function | 51 | -| `fallback` | function | 52 | - -### Parent Contract: `OrderBookV6FlashBorrower` (lines 60-167) - -| Item | Kind | Line | -|------|------|------| -| `BadInitiator` | error | 20 | -| `BadLender` | error | 25 | -| `FlashLoanFailed` | error | 28 | -| `constructor` | function | 63 | -| `supportsInterface` | function | 66 | -| `_exchange` | function (virtual, no-op) | 79 | -| `onFlashLoan` | function | 82 | -| `arb4` | function | 129 | - -### Test Files Reviewed - -| Test File | Tests | -|-----------|-------| -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.sender.t.sol` | `testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender` | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.exchangeRevert.t.sol` | `testExchangeRevertPropagates` | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.approvalRevoked.t.sol` | `testApprovalRevokedAfterExchange` | -| `test/concrete/arb/GenericPoolOrderBookV6FlashBorrower.ethForwarded.t.sol` | `testEthForwardedToExchangeDuringExchange` | -| `test/abstract/OrderBookV6FlashBorrower.flashLoanFailed.t.sol` | `testFlashLoanFailed` | - -## Verification - -### NatSpec vs. Implementation - -- **Contract NatSpec (lines 15-25):** "Flash-loan arb that swaps via an arbitrary external pool call... The `exchangeData` from `arb` is decoded into a spender, pool and callData. The `callData` is literally the encoded function call to the pool." The implementation at lines 34-35 does exactly `abi.decode(exchangeData, (address, address, bytes))`. Correct. - -- **Contract NatSpec (lines 24-25):** "The `spender` is the address that will be approved to spend the input token on `takeOrders`, which is almost always going to be the pool itself." The implementation approves `spender` at line 42: `IERC20(borrowedToken).forceApprove(spender, type(uint256).max)`. Note: the comment says "input token on `takeOrders`" but the code approves `borrowedToken` which is the output token from the order's perspective (the token the flash loan provides). This is correct because from the exchange's perspective, the "input" to the exchange is the borrowed token (order output), which needs to be swapped into the order input token. The NatSpec could be clearer but is not incorrect -- the "input" refers to the exchange's input (= the borrowed token). - -- **`_exchange` override (line 33):** The `@inheritdoc OrderBookV6FlashBorrower` is correct. The parent's NatSpec (lines 70-77) says this hook is "responsible for converting the flash loaned assets into the assets required to fill the orders." The implementation borrows the output token, approves a spender, calls a pool to swap, and revokes. This correctly converts flash-loaned assets. Correct. - -- **Approve-call-revoke comment (lines 39-41):** Same rationale as in the ArbOrderTaker variant. The contract holds no tokens between arb operations. Correct. - -- **`receive()` / `fallback()` NatSpec (lines 49-50):** "Allow arbitrary calls and ETH transfers to this contract without reverting. Any ETH received is swept to msg.sender by finalizeArb." This is correct -- `arb4` calls `LibOrderBookArb.finalizeArb` at line 165 which sweeps all balances. - -### Parent `OrderBookV6FlashBorrower` Verification - -#### Error Conditions vs. Triggers - -- **`BadInitiator(address badInitiator)` (line 20):** NatSpec says "Thrown when the flash loan initiator is not this contract." Trigger at line 88-89: `if (initiator != address(this)) revert BadInitiator(initiator)`. Correct -- the ERC-3156 spec passes the initiator (caller of `flashLoan`) through to the callback; only this contract should initiate its own loans. - -- **`BadLender(address badLender)` (line 25):** NatSpec says "Thrown when onFlashLoan is called by an address other than the deterministic orderbook deployment." Trigger at line 84-85: `if (msg.sender != LibOrderBookDeploy.ORDERBOOK_DEPLOYED_ADDRESS) revert BadLender(msg.sender)`. Correct -- only the trusted orderbook should call `onFlashLoan`. - -- **`FlashLoanFailed()` (line 28):** NatSpec says "Thrown when the flash loan fails somehow." Trigger at line 159-161: `if (!orderBook.flashLoan(...)) revert FlashLoanFailed()`. Correct -- if `flashLoan` returns false (rather than reverting), this catches it. - -#### `onFlashLoan` (lines 82-108) - -1. Validates `msg.sender` is the deterministic orderbook (line 84). Correct per ERC-3156 security. -2. Validates `initiator` is `address(this)` (line 88). Correct per ERC-3156 reference implementation. -3. Decodes `(TakeOrdersConfigV5, bytes)` from `data` (line 92-93). Matches the encoding at `arb4` line 141. -4. Calls `_exchange(takeOrders, exchangeData)` to swap borrowed tokens (line 97). -5. Calls `IRaindexV6(msg.sender).takeOrders4(takeOrders)` (line 105). Uses `msg.sender` which is the validated orderbook. Correct. -6. Returns `ON_FLASH_LOAN_CALLBACK_SUCCESS` (line 107). Required by ERC-3156. - -#### `arb4` (lines 129-166) - -1. Zero-order check (line 136-138): Same pattern as `arb5`. Correct. -2. Encodes `(takeOrders, exchangeData)` into `data` (line 141). Matches decode in `onFlashLoan`. -3. Extracts `ordersOutputToken` (what the order gives = what we borrow) and `ordersInputToken` (what the order takes = what we need after exchange) (lines 144-145). -4. Computes `flashLoanAmount` from `takeOrders.minimumIO` converted to fixed decimal (line 152). The comment says "We can't repay more than the minimum that the orders are going to give us and there's no reason to borrow less." This is correct -- `minimumIO` is the minimum output from taking orders, which equals the amount needed to repay the flash loan. -5. Approves both tokens to the orderbook (lines 157-158). The input token approval is needed for `takeOrders4` (sending input to the order); the output token approval is needed for the flash loan repayment (`safeTransferFrom` in `OrderBookV6FlashLender.flashLoan`). Correct. -6. Calls `flashLoan` and checks result (lines 159-161). -7. Revokes both approvals (lines 162-163). Correct approve-call-revoke. -8. Calls `finalizeArb` (line 165). Sweeps all remaining tokens and ETH to `msg.sender`. - -### Interface Conformance - -- **`IERC3156FlashBorrower`:** `onFlashLoan` signature matches the interface: `function onFlashLoan(address initiator, address token, uint256 amount, uint256 fee, bytes calldata data) external returns (bytes32)`. The implementation at line 82 matches. Correct. - -- **ERC-165:** `supportsInterface` returns true for `type(IERC3156FlashBorrower).interfaceId` plus `super`. Correct. - -### `_exchange` Algorithm Verification - -1. Decode `(spender, pool, encodedFunctionCall)` from `exchangeData` (line 34-35). -2. Extract `borrowedToken` from `takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token` (line 37). This is the token received from the flash loan. -3. `forceApprove(spender, type(uint256).max)` (line 42) -- approve the exchange to spend the borrowed token. -4. `pool.functionCallWithValue(encodedFunctionCall, address(this).balance)` (line 45) -- execute the swap, forwarding any ETH. -5. `forceApprove(spender, 0)` (line 46) -- revoke approval. - -The token used in step 2 must match what was borrowed in `arb4`. In `arb4`, the borrowed token is `ordersOutputToken = takeOrders.orders[0].order.validOutputs[takeOrders.orders[0].outputIOIndex].token` (line 144). In `_exchange`, `borrowedToken` is extracted with the same expression from the same `takeOrders` struct (passed through encoding/decoding). These match. Correct. - -### Tests vs. Claims - -- **`testGenericPoolOrderBookV6FlashBorrowerTakeOrdersSender` (sender.t.sol):** Fuzz-tests the happy path. Constructs a fuzzed order, calls `arb4` with `exchangeData = abi.encode(iRefundoor, iRefundoor, "")`. The `FlashLendingMockOrderBook` calls `onFlashLoan` which validates lender/initiator, calls `_exchange` (Refundoor just returns ETH), then calls `takeOrders4` (no-op mock), returns success. The test name says "sender" but it is really testing the basic end-to-end flow. The test correctly validates the call completes without reverting. - -- **`testExchangeRevertPropagates` (exchangeRevert.t.sol):** Uses a `RevertingExchange` that always reverts with "exchange failed". Uses `RealisticFlashLendingMockOrderBook` which does real token transfers for the flash loan. The test expects `arb4` to revert with the exchange's error. This correctly verifies that revert reasons from the pool call bubble up through `functionCallWithValue` -> `_exchange` -> `onFlashLoan` -> `flashLoan` -> `arb4`. - -- **`testApprovalRevokedAfterExchange` (approvalRevoked.t.sol):** Uses `AllowanceCheckingExchange` which records the allowance it sees during `swap`. After `arb4` completes, asserts: (1) `exchange.lastAllowance() == type(uint256).max` (spender saw max approval during the call), (2) `outputToken.allowance(address(arb), address(exchange)) == 0` (approval revoked after). This correctly verifies the approve-call-revoke pattern for the borrowed token (output token from order perspective). - -- **`testEthForwardedToExchangeDuringExchange` (ethForwarded.t.sol):** Deals 1 ether to the arb contract, runs `arb4`, asserts `exchange.lastEthReceived() == 1 ether` and `address(arb).balance == 0`. This correctly verifies that `functionCallWithValue(encodedFunctionCall, address(this).balance)` forwards all ETH to the pool, and `finalizeArb` sweeps remaining ETH (which was returned by the AllowanceCheckingExchange). - -- **`testFlashLoanFailed` (flashLoanFailed.t.sol):** Uses `FalseFlashLoanMockOrderBook` (extends `MockOrderBookBase`) whose `flashLoan` returns `false`. Expects `arb4` to revert with `FlashLoanFailed`. This correctly verifies the error path where `flashLoan` returns false rather than reverting. - -### Test Correctness Notes - -- **`RealisticFlashLendingMockOrderBook.takeOrders4` (lines 34-41):** This mock takes ALL of `msg.sender`'s input token balance and returns the same amount of output token. This is a simplification -- real orderbook `takeOrders4` would use the order's IO ratio. For testing the exchange/approval pattern, this simplification is adequate. - -- **`FlashLendingMockOrderBook.flashLoan` (lines 22-28):** This mock calls `onFlashLoan` with `msg.sender` as initiator (rather than the original caller of `flashLoan`). Since the mock is etched at the deterministic orderbook address, `msg.sender` in `onFlashLoan` will be the mock's address = the orderbook address. The `initiator` parameter is `msg.sender` of `flashLoan`, which is the arb contract (it calls `orderBook.flashLoan(this, ...)`). The `initiator` check (`initiator != address(this)`) passes because the arb contract passed `this` as the borrower. Correct. - -## Findings - -No findings of severity LOW or higher. The implementation correctly matches all documented intent. Error conditions trigger as described. The flash loan flow is correctly implemented with proper security checks. Tests exercise the success path, exchange revert propagation, approval revocation, ETH forwarding, and flash loan failure. - -## Summary - -`GenericPoolOrderBookV6FlashBorrower` correctly implements a flash-loan-based arbitrage contract that borrows from the orderbook, swaps via an arbitrary external pool, and takes orders to repay the loan. The `_exchange` hook correctly extracts the borrowed token and implements approve-call-revoke. The parent `OrderBookV6FlashBorrower.onFlashLoan` correctly validates both the lender address (deterministic orderbook) and the initiator (self). The `arb4` flow correctly sequences: flash loan -> exchange -> take orders -> repay -> finalize. All five test files accurately exercise the behaviors their names describe, covering success, revert propagation, approval hygiene, ETH forwarding, and flash loan failure. diff --git a/audit/2026-03-14-01/pass5/A07-RouteProcessorOrderBookV6ArbOrderTaker.md b/audit/2026-03-14-01/pass5/A07-RouteProcessorOrderBookV6ArbOrderTaker.md deleted file mode 100644 index c9c7cd3ebf..0000000000 --- a/audit/2026-03-14-01/pass5/A07-RouteProcessorOrderBookV6ArbOrderTaker.md +++ /dev/null @@ -1,66 +0,0 @@ -# A07 - Pass 5: Correctness / Intent Verification -## File: `src/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sol` - -## Source File Evidence - -**Contract:** `RouteProcessorOrderBookV6ArbOrderTaker` (inherits `OrderBookV6ArbOrderTaker`) -- Line 15: contract declaration -- Line 19: `iRouteProcessor` immutable (line 19) -- Line 21-24: `constructor(OrderBookV6ArbConfig memory config)` - decodes `routeProcessor` address from `config.implementationData` -- Line 27-50: `onTakeOrders2(...)` override - approves route processor, decodes route, converts float amounts, calls `processRoute`, revokes approval -- Line 54: `receive() external payable {}` - allows receiving ETH -- Line 55: `fallback() external payable {}` - allows arbitrary calls - -**Parent: `OrderBookV6ArbOrderTaker`** (`src/abstract/OrderBookV6ArbOrderTaker.sol`) -- Line 38-64: `arb5(...)` - takes orders from orderbook, calls `finalizeArb` -- Line 70: `onTakeOrders2(...)` - base is a no-op - -**Parent: `OrderBookV6ArbCommon`** (`src/abstract/OrderBookV6ArbCommon.sol`) -- Line 39: `iTaskHash` immutable -- Line 42-49: constructor stores task hash -- Line 54-59: `onlyValidTask` modifier - -## Test Files Reviewed - -1. `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2.t.sol` -2. `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.onTakeOrders2Direct.t.sol` -3. `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.sender.t.sol` -4. `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.expression.t.sol` -5. `test/concrete/arb/RouteProcessorOrderBookV6ArbOrderTaker.invalidConstructor.t.sol` -6. `test/util/abstract/RouteProcessorOrderBookV6ArbOrderTakerTest.sol` - -## Findings - -### No findings at LOW or above. - -All named items match their documented behavior: - -1. **NatSpec vs. Implementation**: The `@title` says "Order-taker arb that swaps via a Sushi RouteProcessor" and the implementation does exactly that. The `@inheritdoc OrderBookV6ArbOrderTaker` on `onTakeOrders2` correctly delegates to the parent's no-op first, then performs the route processor swap. The `@dev` comment on `iRouteProcessor` accurately describes its role. - -2. **Constructor**: Correctly decodes the `routeProcessor` address from `config.implementationData` via `abi.decode`. Test `testConstructorRevertsEmptyImplementationData` and `testConstructorRevertsMalformedImplementationData` verify invalid data handling. - -3. **`onTakeOrders2` Logic**: - - Calls `super.onTakeOrders2` first (correct delegation). - - Approves `type(uint256).max` to route processor, then revokes to 0 after the call (correct approval pattern). - - Uses `toFixedDecimalLossy` for `inputAmountSent` -- the comment on line 37-38 accurately notes "precision loss is acceptable" for the route. - - For `totalOutputAmount`, rounds up (`outputTokenAmount++`) when conversion is lossy. This is correct: the output token amount is the minimum the route must produce, so rounding up protects the arb contract. - - The `processRoute` call parameters map correctly: input token, amount, output token, minimum output amount, recipient, route bytes. - -4. **`receive()` / `fallback()`**: The NatSpec (line 52-53) says "Allow arbitrary calls and ETH transfers to this contract without reverting. Any ETH received is swept to msg.sender by finalizeArb." The `finalizeArb` in the parent (`LibOrderBookArb`) does indeed sweep remaining balances, making this claim accurate. - -5. **Tests vs. Claims**: - - `testRouteProcessorArb5`: Full integration test verifying the complete arb cycle. Assertions check all balances are correct after the flow. - - `testOnTakeOrders2DirectCallByAttacker`: Tests that direct calls by an arbitrary address succeed but gain nothing (stateless contract). This matches the documented intent that there's "nothing to protect via `msg.sender` validation." - - `testRouteProcessorTakeOrdersSender`: Fuzz test exercising the sender path through the arb. - - `testRouteProcessorTakeOrdersWrongExpression`: Verifies `WrongTask` revert when task doesn't match. - - `testRouteProcessorTakeOrdersExpression`: Verifies the expression is evaluated and kvs are persisted when provided. - -6. **Interface Conformance**: The contract correctly implements `IRaindexV6OrderTaker` (via `onTakeOrders2`) and `IRaindexV6ArbOrderTaker` (via `arb5`), with ERC165 `supportsInterface` coverage verified in abstract tests. - -7. **Error Conditions**: `WrongTask` is triggered when the task hash doesn't match (tested in expression test). Constructor reverts on malformed data (tested). - -8. **Constants**: `type(uint256).max` used for approval is correct (maximum allowance). Revoking to 0 after use is correct. - -### INFO-level Notes - -**A07-INFO-1**: The `super.onTakeOrders2` call on line 34 invokes the parent's no-op implementation. While this is a valid pattern for extensibility, it has no functional effect currently. No action needed. diff --git a/audit/2026-03-14-01/pass5/A08-OrderBookV6.md b/audit/2026-03-14-01/pass5/A08-OrderBookV6.md deleted file mode 100644 index d7eb30ef28..0000000000 --- a/audit/2026-03-14-01/pass5/A08-OrderBookV6.md +++ /dev/null @@ -1,181 +0,0 @@ -# A08 - Pass 5: Correctness / Intent Verification -## File: `src/concrete/ob/OrderBookV6.sol` - -## Source File Evidence - -**Contract:** `OrderBookV6` (inherits `IRaindexV6`, `IMetaV1_2`, `ReentrancyGuard`, `Multicall`, `OrderBookV6FlashLender`) - -### Errors (lines 69-125) -- Line 69: `ReentrancyGuardReentrantCall()` - reentrancy guard error -- Line 73: `NotOrderOwner(address owner)` - wrong sender for order modification -- Line 76: `TokenMismatch()` - input/output tokens don't match across orders -- Line 79: `TokenSelfTrade()` - input token == output token -- Line 83: `TokenDecimalsMismatch()` - decimals mismatch -- Line 88: `MinimumIO(Float minimumIO, Float actualIO)` - minimum input not met -- Line 91: `SameOwner()` - two orders have same owner in clear -- Line 95: `UnsupportedCalculateInputs(uint256 inputs)` - calc expression wants inputs -- Line 99: `UnsupportedCalculateOutputs(uint256 outputs)` - calc expression has too few outputs -- Line 102: `NegativeInput()` - negative input against vault balances -- Line 105: `NegativeOutput()` - negative output against vault balances -- Line 109: `NegativeVaultBalance(Float vaultBalance)` - vault balance would go negative -- Line 113: `NegativeVaultBalanceChange(Float amount)` - negative amount applied -- Line 116: `NegativePull()` - negative pull attempted -- Line 119: `NegativePush()` - negative push attempted -- Line 122: `NegativeBounty()` - negative bounty calculated -- Line 125: `ClearZeroAmount()` - both clear output amounts zero - -### Constants (lines 128-150) -- Line 129: `ORDER_LIVE = 1` -- Line 134: `ORDER_DEAD = 0` -- Line 137: `CALCULATE_ORDER_ENTRYPOINT = SourceIndexV2.wrap(0)` -- Line 140: `HANDLE_IO_ENTRYPOINT = SourceIndexV2.wrap(1)` -- Line 143: `CALCULATE_ORDER_MIN_OUTPUTS = 2` -- Line 145: `CALCULATE_ORDER_MAX_OUTPUTS = 2` -- Line 148: `HANDLE_IO_MIN_OUTPUTS = 0` -- Line 150: `HANDLE_IO_MAX_OUTPUTS = 0` - -### Functions -- Line 219: `vaultBalance2(address, address, bytes32)` external view -- Line 226: `_vaultBalance(address, address, bytes32)` internal view -- Line 244: `orderExists(bytes32)` external view -- Line 249: `entask2(TaskV2[])` external nonReentrant -- Line 254: `deposit4(address, bytes32, Float, TaskV2[])` external nonReentrant -- Line 289: `withdraw4(address, bytes32, Float, TaskV2[])` external nonReentrant -- Line 328: `addOrder4(OrderConfigV4, TaskV2[])` external nonReentrant -- Line 378: `removeOrder3(OrderV4, TaskV2[])` external nonReentrant -- Line 401: `checkTokenSelfTrade(OrderV4, uint256, uint256)` internal pure -- Line 410: `quote2(QuoteV2)` external view -- Line 433: `takeOrders4(TakeOrdersConfigV5)` external nonReentrant -- Line 593: `clear3(...)` external nonReentrant -- Line 698: `calculateOrderIO(...)` internal view -- Line 822: `increaseVaultBalance(...)` internal -- Line 855: `decreaseVaultBalance(...)` internal -- Line 893: `recordVaultIO(...)` internal -- Line 919: `handleIO(...)` internal -- Line 971: `calculateClearStateChange(...)` internal pure -- Line 987: `calculateClearStateAlice(...)` internal pure -- Line 1008: `pullTokens(address, address, Float)` internal -- Line 1032: `pushTokens(address, address, Float)` internal -- Line 1052: `_nonZeroVaultId(address, address, bytes32)` internal pure -- Line 1058: `nonZeroVaultId` modifier - -## Test Files Reviewed - -1. `test/concrete/ob/OrderBookV6.addOrder.t.sol` -2. `test/concrete/ob/OrderBookV6.takeOrder.noop.t.sol` -3. `test/concrete/ob/OrderBookV6.takeOrder.tokenMismatch.t.sol` -4. `test/concrete/ob/OrderBookV6.takeOrder.precision.t.sol` -5. `test/concrete/ob/OrderBookV6.takeOrder.maximumInput.t.sol` -6. `test/concrete/ob/OrderBookV6.takeOrder.sameToken.t.sol` -7. `test/concrete/ob/OrderBookV6.clear.mock.t.sol` -8. `test/concrete/ob/OrderBookV6.clear.zeroAmount.t.sol` -9. `test/concrete/ob/OrderBookV6.clear.sameToken.t.sol` -10. `test/concrete/ob/OrderBookV6.deposit.t.sol` -11. `test/concrete/ob/OrderBookV6.withdraw.t.sol` - -## Findings - -### A08-1: NatSpec on `calculateOrderIO` says amounts are "always treated as 18 decimal fixed point" but uses Floats (INFO) - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 687-689 - -**Description:** The NatSpec comment for `calculateOrderIO` states: "Both are always treated as 18 decimal fixed point values and then rescaled according to the order's definition of each token's actual fixed point decimals." However, the implementation uses `Float` type throughout (not 18-decimal fixed point). The Float system handles decimal scaling internally. This NatSpec appears to be a leftover from an older version that used 18-decimal fixed-point integers. - -**Impact:** Documentation only. No functional issue, but could confuse developers reading the code. - ---- - -### A08-2: `UnsupportedCalculateInputs` error is declared but never thrown (INFO) - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 95 - -**Description:** The error `UnsupportedCalculateInputs(uint256 inputs)` is declared with NatSpec "Thrown when calculate order expression wants inputs." However, this error is never used in the contract. In `calculateOrderIO` (line 777-778), the `inputs` parameter to `eval4` is always `new StackItem[](0)` -- there is no check that the expression does not request inputs, and therefore this error is dead code. The test `testAddOrderRealCalculateInputsReverts1` deploys without error because "this is a runtime check" (per comments), but no runtime path throws this error. - -**Impact:** Dead code. The error declaration is unused, possibly a vestige from an older design. If the intent is to guard against expression inputs, the check is missing. - ---- - -### A08-3: `NegativeInput` and `NegativeOutput` errors are declared but never thrown (INFO) - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` lines 102, 105 - -**Description:** The errors `NegativeInput()` and `NegativeOutput()` are declared but never used in the contract. The only negative-value guards are `NegativeVaultBalanceChange` (in `increaseVaultBalance`/`decreaseVaultBalance`), `NegativePull` (in `pullTokens`), `NegativePush` (in `pushTokens`), and `NegativeBounty` (in `clear3`). No path in the code throws `NegativeInput` or `NegativeOutput`. - -**Impact:** Dead code. These appear to be vestiges from an older design. - ---- - -### A08-4: `TokenDecimalsMismatch` error is declared but never thrown (INFO) - -**Severity:** INFO - -**Location:** `src/concrete/ob/OrderBookV6.sol` line 83 - -**Description:** The error `TokenDecimalsMismatch()` is declared with NatSpec "Thrown when the input and output token decimals don't match, in either direction." However, this error is never used in the contract. The Float-based architecture handles decimal differences internally, making this check unnecessary. - -**Impact:** Dead code. - ---- - -### Verified Correct Behavior - -1. **Error Conditions vs. Triggers:** - - `NotOrderOwner`: Triggered at line 383 in `removeOrder3` when `msg.sender != order.owner`. Correctly guards owner-only removal. Tested in `OrderBookV6.removeOrder.owner.t.sol`. - - `TokenMismatch`: Triggered at line 479 in `takeOrders4` when input/output tokens differ across orders, and at line 610 in `clear3` for cross-order token mismatches. Tested extensively in `tokenMismatch.t.sol`. - - `TokenSelfTrade`: Triggered at line 405 in `checkTokenSelfTrade` when input and output tokens are the same address. Tested in `sameToken.t.sol`. - - `SameOwner`: Triggered at line 602 in `clear3` when both orders have the same owner. Tested in `clear.mock.t.sol`. - - `MinimumIO`: Triggered at line 561 when `actualRelevantTakerIO < config.minimumIO`. The selection of relevant IO via `IOIsInput` flag is correct. - - `ClearZeroAmount`: Triggered at line 683 after both outputs are confirmed zero. Tested in `clear.zeroAmount.t.sol`. - - `NegativeBounty`: Triggered at lines 655-657 when bounty would be negative (spread between orders). This is correctly guarded. - - `NegativeVaultBalance`: Triggered in `decreaseVaultBalance` line 878-879 when subtraction would produce negative balance. Correctly prevents vault underflow. - - `ZeroMaximumIO`: Triggered at line 466 when `maximumIO` is not positive. Tested. - - `ZeroDepositAmount`: Triggered at line 260 when deposit amount is not positive. Tested. - - `ZeroWithdrawTargetAmount`: Triggered at line 299-300 when withdraw target is not positive. Tested. - -2. **Constants Match Definitions:** - - `ORDER_LIVE = 1` and `ORDER_DEAD = 0`: Documented meanings match usage. `0` is the default mapping value, so all orders start dead. - - `CALCULATE_ORDER_ENTRYPOINT = SourceIndexV2.wrap(0)`: Source index 0 for calculate order. Matches usage at line 776. - - `HANDLE_IO_ENTRYPOINT = SourceIndexV2.wrap(1)`: Source index 1 for handle IO. Matches usage at line 945. - - `CALCULATE_ORDER_MIN_OUTPUTS = 2`: Two outputs required (amount and ratio). Matches check at line 785 and stack reading at lines 792-793. - - `FLASH_FEE = 0`: Zero flash loan fee. Correctly used throughout `OrderBookV6FlashLender`. - -3. **Algorithm: `calculateClearStateAlice` (line 987-1003):** - - Alice's input = alice's outputMax * alice's IORatio (line 992). Correct: the input she demands for her output. - - Alice's output = alice's outputMax (line 994). Correct: starts at her maximum. - - If alice's input > bob's outputMax, cap alice's input at bob's outputMax (line 998-999). Then recalculate alice's output = cappedInput / alice's IORatio (line 1002). Correct: if bob can't provide enough input to alice, alice's output is proportionally reduced. - - The symmetry via `calculateClearStateChange` (lines 976-981) correctly flips alice/bob to compute bob's values. - -4. **Algorithm: `takeOrders4` IOIsInput branching (lines 507-530):** - - When `IOIsInput = true`: `takerInput = min(outputMax, remainingTakerIO)`, `takerOutput = IORatio * takerInput`. Correctly implements market buying where taker limits their input. - - When `IOIsInput = false`: `orderMaxInput = IORatio * outputMax`, `takerOutput = min(orderMaxInput, remainingTakerIO)`, `takerInput = takerOutput / IORatio`. Correctly implements market selling where taker limits their output. - -5. **Token Transfer Rounding:** - - `pullTokens` (line 1017-1023): Rounds UP truncation when pulling. This is correct as the orderbook should never receive fewer tokens than the float represents. - - `pushTokens` (line 1043): Rounds DOWN (lossy, no increment). Correct: the orderbook should never send more tokens than the float represents. This favors the protocol. - -6. **Vault ID 0 Special Behavior:** - - `_vaultBalance` for vault 0 reads `balanceOf` and `allowance` directly, returns min. Correct for "vaultless" orders. - - `increaseVaultBalance` for vault 0 pushes tokens directly to owner. Correct. - - `decreaseVaultBalance` for vault 0 pulls tokens directly from owner. Correct. - - `deposit4` and `withdraw4` reject vault ID 0 via `nonZeroVaultId` modifier. Correct: direct deposits/withdrawals don't make sense for vaultless mode. - -7. **Test Correctness:** - - All test names accurately describe the behavior they exercise. - - Fuzz tests use appropriate `bound()` and `vm.assume()` constraints. - - The precision test suite (`OrderBookV6TakeOrderPrecisionTest`) verifies known-bad cases from older OB versions, confirming the Float system resolves them. - - The `testTakeOrderMaximumInputMultipleOrdersMultipleOwners` test correctly models the sequential consumption of orders with independent deposits. - -8. **Interface Conformance:** - - `IRaindexV6`: All interface functions (`vaultBalance2`, `orderExists`, `entask2`, `deposit4`, `withdraw4`, `addOrder4`, `removeOrder3`, `quote2`, `takeOrders4`, `clear3`) are implemented. - - `IMetaV1_2`: Inherited via events. - - `IERC3156FlashLender`: Implemented via `OrderBookV6FlashLender` parent. - - `Multicall`: Inherited from OpenZeppelin. - - `ReentrancyGuard`: All state-modifying functions use `nonReentrant`. - -9. **`clear3` Signed Context Passing (line 635-640):** Alice's order receives `bobSignedContext` and bob's order receives `aliceSignedContext`. This is intentional and consistent across all historical versions of the interface. The NatSpec "relevant to A/B" means the context that each order's expression will receive, which comes from the counterparty's perspective of the trade. The implementation is correct for the intended design. diff --git a/audit/2026-03-14-01/pass5/A09-OrderBookV6SubParser.md b/audit/2026-03-14-01/pass5/A09-OrderBookV6SubParser.md deleted file mode 100644 index d503f48bca..0000000000 --- a/audit/2026-03-14-01/pass5/A09-OrderBookV6SubParser.md +++ /dev/null @@ -1,127 +0,0 @@ -# A09 - Pass 5: Correctness / Intent Verification -## File: `src/concrete/parser/OrderBookV6SubParser.sol` - -## Source File Evidence - -**Contract:** `OrderBookV6SubParser` (inherits `BaseRainterpreterSubParser`) - -### Functions -- Line 73: `describedByMetaV1()` external pure - returns `DESCRIBED_BY_META_HASH` -- Line 78: `subParserParseMeta()` internal pure override - returns `SUB_PARSER_PARSE_META` -- Line 83: `subParserWordParsers()` internal pure override - returns `SUB_PARSER_WORD_PARSERS` -- Line 88: `subParserOperandHandlers()` internal pure override - returns `SUB_PARSER_OPERAND_HANDLERS` -- Line 93: `buildLiteralParserFunctionPointers()` external pure - returns empty bytes -- Line 98: `buildOperandHandlerFunctionPointers()` external pure - builds operand handler table -- Line 183: `buildSubParserWordParsers()` external pure - builds word parser table - -**Library:** `LibOrderBookSubParser` (`src/lib/LibOrderBookSubParser.sol`) -- 25 `subParser*` functions mapping words to context columns/rows -- `authoringMetaV2()` function building authoring metadata - -### Constants verified from `LibOrderBookSubParser` -- `SUB_PARSER_WORD_PARSERS_LENGTH = 2` (line 49) -- `EXTERN_PARSE_META_BUILD_DEPTH = 1` (line 50) -- All DEPOSIT_WORD_* and WITHDRAW_WORD_* index constants (lines 83-96) - -## Test Files Reviewed - -1. `test/concrete/parser/OrderBookV6SubParser.pointers.t.sol` -2. `test/concrete/parser/OrderBookV6SubParser.ierc165.t.sol` -3. `test/concrete/parser/OrderBookV6SubParser.describedByMeta.t.sol` -4. `test/concrete/parser/OrderBookV6SubParser.signedContext.t.sol` -5. `test/concrete/parser/OrderBookV6SubParser.signers.t.sol` -6. `test/concrete/parser/OrderBookV6SubParser.contextInputVaultBalanceIncrease.t.sol` -7. `test/concrete/parser/OrderBookV6SubParser.contextOutputVaultBalanceDecrease.t.sol` -8. `test/util/abstract/OrderBookV6SubParserContextTest.sol` -9. `test/util/fixture/LibOrderBookSubParserContextFixture.sol` - -(Also reviewed all other context*.t.sol files for completeness) - -## Findings - -### No findings at LOW or above. - -All named items match their documented behavior: - -### Verified Correct Behavior - -1. **Word-to-Context Mapping Correctness:** - - Every sub-parser word function was verified to map to the correct context column and row: - - | Word | Function | Column | Row | Correct? | - |------|----------|--------|-----|----------| - | `order-clearer` | `subParserSender` | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROW_SENDER` (0) | Yes | - | `orderbook` | `subParserCallingContract` | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROW_CALLING_CONTRACT` (1) | Yes | - | `order-hash` | `subParserOrderHash` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` (0) | Yes | - | `order-owner` | `subParserOrderOwner` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` (1) | Yes | - | `order-counterparty` | `subParserOrderCounterparty` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` (2) | Yes | - | `calculated-max-output` | `subParserMaxOutput` | `CONTEXT_CALCULATIONS_COLUMN` (2) | `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` (0) | Yes | - | `calculated-io-ratio` | `subParserIORatio` | `CONTEXT_CALCULATIONS_COLUMN` (2) | `CONTEXT_CALCULATIONS_ROW_IO_RATIO` (1) | Yes | - | `input-token` | `subParserInputToken` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_TOKEN` (0) | Yes | - | `input-token-decimals` | `subParserInputTokenDecimals` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_TOKEN_DECIMALS` (1) | Yes | - | `input-vault-id` | `subParserInputVaultId` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_VAULT_ID` (2) | Yes | - | `input-vault-before` | `subParserInputBalanceBefore` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_BALANCE_BEFORE` (3) | Yes | - | `input-vault-increase` | `subParserInputBalanceDiff` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_BALANCE_DIFF` (4) | Yes | - | `output-token` | `subParserOutputToken` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_TOKEN` (0) | Yes | - | `output-token-decimals` | `subParserOutputTokenDecimals` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_TOKEN_DECIMALS` (1) | Yes | - | `output-vault-id` | `subParserOutputVaultId` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_VAULT_ID` (2) | Yes | - | `output-vault-before` | `subParserOutputBalanceBefore` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_BALANCE_BEFORE` (3) | Yes | - | `output-vault-decrease` | `subParserOutputBalanceDiff` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_BALANCE_DIFF` (4) | Yes | - | `signer` | `subParserSigners` | `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` (5) | operand value | Yes | - | `signed-context` | `subParserSignedContext` | `CONTEXT_SIGNED_CONTEXT_START_COLUMN` (6) + low byte | high byte | Yes | - - Deposit words (column `CONTEXT_SIGNED_CONTEXT_START_COLUMN + 1` = 7 in the sub-parser table, but actual runtime context maps to `CONTEXT_CALLING_CONTEXT_COLUMN` via the sub-parser dispatch): - | Word | Function | Maps to Column | Row | Correct? | - |------|----------|---------------|-----|----------| - | `depositor` | `subParserSender` | `CONTEXT_BASE_COLUMN` (0) | 0 | Yes | - | `deposit-token` | `subParserDepositToken` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 0 | Yes | - | `deposit-vault-id` | `subParserDepositVaultId` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 1 | Yes | - | `deposit-vault-before` | `subParserDepositVaultBalanceBefore` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 2 | Yes | - | `deposit-vault-after` | `subParserDepositVaultBalanceAfter` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 3 | Yes | - - Withdraw words (column `CONTEXT_SIGNED_CONTEXT_START_COLUMN + 2` = 8): - | Word | Function | Maps to Column | Row | Correct? | - |------|----------|---------------|-----|----------| - | `withdrawer` | `subParserSender` | `CONTEXT_BASE_COLUMN` (0) | 0 | Yes | - | `withdraw-token` | `subParserWithdrawToken` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 0 | Yes | - | `withdraw-vault-id` | `subParserWithdrawVaultId` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 1 | Yes | - | `withdraw-vault-before` | `subParserWithdrawVaultBalanceBefore` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 2 | Yes | - | `withdraw-vault-after` | `subParserWithdrawVaultBalanceAfter` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 3 | Yes | - | `withdraw-target-amount` | `subParserWithdrawTargetAmount` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | 4 | Yes | - -2. **Operand Handler Correctness:** - - All standard context words use `handleOperandDisallowed` -- no operand allowed. Correct, as these are fixed column/row references. - - `signer` uses `handleOperandSingleFullNoDefault` -- requires exactly one operand (the signer index). Correct. - - `signed-context` uses `handleOperandDoublePerByteNoDefault` -- requires two operands packed into bytes (column offset and row). Correct. - -3. **`buildOperandHandlerFunctionPointers` vs. `buildSubParserWordParsers` Symmetry:** - Both functions build identically structured arrays of the same dimensions across all context columns. The operand handlers and word parsers are paired 1:1. Verified in `testWordOperandLengthEquivalence` which asserts `SUB_PARSER_WORD_PARSERS.length == SUB_PARSER_OPERAND_HANDLERS.length`. - -4. **Pointer Table Verification:** - - `testSubParserParseMeta`: Rebuilds parse meta from authoring meta and asserts it equals the pre-computed `SUB_PARSER_PARSE_META`. This ensures the generated pointers match the runtime build. - - `testSubParserFunctionPointers`: Rebuilds word parsers and asserts equality with `SUB_PARSER_WORD_PARSERS`. - - `testSubParserOperandParsers`: Rebuilds operand handlers and asserts equality with `SUB_PARSER_OPERAND_HANDLERS`. - -5. **Interface Conformance:** - - `IDescribedByMetaV1`: Implemented via `describedByMetaV1()` returning `DESCRIBED_BY_META_HASH`. Tested in `describedByMeta.t.sol` which verifies the hash matches the actual meta file. - - `IParserToolingV1`: `buildLiteralParserFunctionPointers()` returns empty bytes (no literals). `buildOperandHandlerFunctionPointers()` returns the handler table. - - `BaseRainterpreterSubParser`: All three required overrides (`subParserParseMeta`, `subParserWordParsers`, `subParserOperandHandlers`) are implemented. - - ERC165: Tested in `ierc165.t.sol` for `IERC165`, `ISubParserV4`, `IDescribedByMetaV1`, `IParserToolingV1`, `ISubParserToolingV1`. - -6. **Test Correctness:** - - Each context word test (e.g., `OrderBookV6SubParserContextInputVaultBalanceIncreaseTest`) overrides `word()` to return the word string and inherits `OrderBookV6SubParserContextTest` which: - - `testSubParserContextHappy`: Parses rainlang using the sub-parser, evaluates against a fixture context where each cell contains `keccak256(wordName)`, and checks the stack output matches the expected hash. - - `testSubParserContextUnhappyDisallowedOperand`: Verifies that adding an operand causes a parse error. - - `testSubParserContextUnhappyDisallowedInputs`: Verifies that passing an input causes a stack allocation mismatch. - - The `signer` and `signed-context` tests verify both happy paths (with correct operands) and unhappy paths (missing operands, too many operands, inputs). - -7. **`authoringMetaV2` Consistency:** - The authoring meta in `LibOrderBookSubParser.authoringMetaV2()` correctly maps every word string to its corresponding context position and provides accurate descriptions. The deposit meta uses offset indexing (`CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN + 1`) which correctly accounts for the `depositor` entry at index 0. The withdraw meta uses direct `WITHDRAW_WORD_*` indices which are already 0-based. - -8. **Assembly Safety:** - - Lines 174-176 and 294-296: The `assembly ("memory-safe")` blocks perform type-unsafe casts from function pointer arrays to `uint256[][]`. This is safe because function pointers and `uint256` have the same ABI encoding width. - - The `flatten()` call on the matrix followed by `unsafeTo16BitBytes` produces the packed function pointer table. This is validated by the pointer tests. - -9. **`CONTEXT_COLUMNS_EXTENDED` Calculation:** - `CONTEXT_COLUMNS_EXTENDED = CONTEXT_COLUMNS + 2 + 1 + 1 = 5 + 2 + 1 + 1 = 9`. This accounts for: 5 base columns + signers column + signed-context-start column + deposit column + withdraw column. The `buildOperandHandlerFunctionPointers` and `buildSubParserWordParsers` both allocate arrays of size `CONTEXT_COLUMNS_EXTENDED` (9) and populate columns 0-8. Correct. diff --git a/audit/2026-03-14-01/pass5/A10-LibOrder.md b/audit/2026-03-14-01/pass5/A10-LibOrder.md deleted file mode 100644 index 5872c39a73..0000000000 --- a/audit/2026-03-14-01/pass5/A10-LibOrder.md +++ /dev/null @@ -1,64 +0,0 @@ -# A10 - LibOrder.sol - Pass 5 (Correctness / Intent Verification) - -**Source file:** `src/lib/LibOrder.sol` (19 lines) -**Test file:** `test/lib/LibOrder.t.sol` (23 lines) - -## Evidence Inventory - -### LibOrder.sol -- **Library:** `LibOrder` (line 10) -- **Function:** `hash(OrderV4 memory order) -> bytes32` (line 16) - - Pure, internal - - Returns `keccak256(abi.encode(order))` - -### Constants / Types / Errors -- None defined in this file. - -### Imports -- `OrderV4` from `rain.raindex.interface/interface/IRaindexV6.sol` - ---- - -## NatSpec vs. Implementation - -### `LibOrder` library (line 7-9) -- **NatSpec claim:** "Consistent handling of `OrderV4` for where it matters w.r.t. determinism and security." -- **Verified:** The library provides exactly one function (`hash`) that deterministically hashes an `OrderV4`. Correct. - -### `hash` function (line 11-17) -- **NatSpec claim:** "Hashes `OrderV4` in a secure and deterministic way. Uses abi.encode rather than abi.encodePacked to guard against potential collisions where many inputs encode to the same output bytes." -- **Verified:** Uses `keccak256(abi.encode(order))`. `abi.encode` pads each field to 32 bytes, preventing the collision issue that `abi.encodePacked` can cause with adjacent dynamic-length fields. Correct. -- **NatSpec claim:** "@param order The order to hash." / "@return The hash of `order`." -- **Verified:** Single input `OrderV4 memory order`, single output `bytes32`. Correct. - ---- - -## Test Correctness - -### `testHashEqual` (line 14) -- **Claim:** "Hashing should always produce the same result for the same input." -- **Implementation:** `assertTrue(LibOrder.hash(a) == LibOrder.hash(a))` with fuzz input `a`. -- **Verified:** Correctly tests determinism by hashing the same value twice and comparing. This is a valid property test. - -### `testHashNotEqual` (line 20) -- **Claim:** "Hashing should always produce different results for different inputs." -- **Implementation:** `assertTrue(LibOrder.hash(a) != LibOrder.hash(b))` with fuzz inputs `a`, `b`. -- **Issue:** The test does not constrain `a != b`. If the fuzzer generates `a == b`, the assertion will fail. While `OrderV4` is a complex struct making collision near-impossible in 100 runs, the test does not actually verify its precondition. See finding A10-1. - ---- - -## Findings - -### A10-1: Test `testHashNotEqual` does not enforce its precondition that inputs differ (LOW) - -**File:** `test/lib/LibOrder.t.sol`, line 20-22 - -The test claims "Hashing should always produce different results for different inputs" but does not ensure `a` and `b` are actually different. If the fuzzer happens to produce identical structs, the test incorrectly fails. The correct approach is to either `vm.assume` the inputs are different or skip the assertion when they are equal. - -This is a test-only issue with no production impact, but it makes the test logically unsound -- it does not accurately test what its name describes. - ---- - -## Summary - -`LibOrder.sol` is a minimal, correct library. The single `hash` function matches its documentation exactly. The only finding is a minor test logic gap in `testHashNotEqual`. diff --git a/audit/2026-03-14-01/pass5/A11-LibOrderBook.md b/audit/2026-03-14-01/pass5/A11-LibOrderBook.md deleted file mode 100644 index 3da0563452..0000000000 --- a/audit/2026-03-14-01/pass5/A11-LibOrderBook.md +++ /dev/null @@ -1,112 +0,0 @@ -# A11 - LibOrderBook.sol - Pass 5 (Correctness / Intent Verification) - -**Source file:** `src/lib/LibOrderBook.sol` (139 lines) -**Related test files:** -- `test/lib/deploy/LibOrderBookDeploy.t.sol` (tests deploy helpers, not `LibOrderBook` logic) -- `test/lib/deploy/LibOrderBookDeployProd.t.sol` (tests production deployments, not `LibOrderBook` logic) -- No direct unit test for `doPost` exists; it is exercised indirectly through OrderBookV6 and LibOrderBookArb tests. - -## Evidence Inventory - -### Constants (file-level, lines 28-106) - -| Constant | Value | Line | -|---|---|---| -| `CALLING_CONTEXT_COLUMNS` | 4 | 28 | -| `CONTEXT_COLUMNS` | 5 (= 4 + 1) | 30 | -| `CONTEXT_COLUMNS_EXTENDED` | 9 (= 5 + 2 + 1 + 1) | 34 | -| `CONTEXT_CALLING_CONTEXT_COLUMN` | 1 | 40 | -| `CONTEXT_CALLING_CONTEXT_ROWS` | 3 | 41 | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` | 0 | 43 | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` | 1 | 44 | -| `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` | 2 | 45 | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` | 0 | 49 | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` | 1 | 50 | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` | 2 | 51 | -| `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` | 3 | 52 | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` | 0 | 56 | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` | 1 | 57 | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` | 2 | 58 | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` | 3 | 59 | -| `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` | 4 | 60 | -| `CONTEXT_CALCULATIONS_COLUMN` | 2 | 64 | -| `CONTEXT_CALCULATIONS_ROWS` | 2 | 65 | -| `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` | 0 | 67 | -| `CONTEXT_CALCULATIONS_ROW_IO_RATIO` | 1 | 68 | -| `CONTEXT_VAULT_INPUTS_COLUMN` | 3 | 74 | -| `CONTEXT_VAULT_OUTPUTS_COLUMN` | 4 | 77 | -| `CONTEXT_VAULT_IO_TOKEN` | 0 | 80 | -| `CONTEXT_VAULT_IO_TOKEN_DECIMALS` | 1 | 82 | -| `CONTEXT_VAULT_IO_VAULT_ID` | 2 | 84 | -| `CONTEXT_VAULT_IO_BALANCE_BEFORE` | 3 | 87 | -| `CONTEXT_VAULT_IO_BALANCE_DIFF` | 4 | 92 | -| `CONTEXT_VAULT_IO_ROWS` | 5 | 94 | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` | 5 | 98 | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` | 1 | 99 | -| `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROW` | 0 | 100 | -| `CONTEXT_SIGNED_CONTEXT_START_COLUMN` | 6 | 104 | -| `CONTEXT_SIGNED_CONTEXT_START_ROWS` | 1 | 105 | -| `CONTEXT_SIGNED_CONTEXT_START_ROW` | 0 | 106 | - -### Library: `LibOrderBook` (line 108) -- **Function:** `doPost(bytes32[][] memory context, TaskV2[] memory post)` (line 111) - internal - ---- - -## Constants Verification - -### Column layout -The context matrix has this column layout: -- Column 0: Base (sender, calling contract) -- from `LibContext` -- Column 1: Calling context (order hash, owner, counterparty) -- Column 2: Calculations (max output, IO ratio) -- Column 3: Vault inputs (token, decimals, vault ID, balance before, balance diff) -- Column 4: Vault outputs (same structure as inputs) -- Column 5: Signed context signers -- Column 6: Signed context data start - -**`CALLING_CONTEXT_COLUMNS = 4`** (line 28): Columns 1-4 are the calling context columns. Verified: calling(1) + calculations(2) + vault_inputs(3) + vault_outputs(4) = 4 columns. Correct. - -**`CONTEXT_COLUMNS = CALLING_CONTEXT_COLUMNS + 1 = 5`** (line 30): 4 calling columns + 1 base column = 5. Correct. - -**`CONTEXT_COLUMNS_EXTENDED = CONTEXT_COLUMNS + 2 + 1 + 1 = 9`** (line 34): The NatSpec says "base columns plus 2 for signers and signed context start, 1 for deposit, 1 for withdraw." 5 + 2 (signers col 5, signed data col 6) + 1 (deposit col 7) + 1 (withdraw col 8) = 9. Correct. Verified against `LibOrderBookSubParser.authoringMetaV2()` which allocates `CONTEXT_COLUMNS_EXTENDED` entries and fills deposit at `CONTEXT_SIGNED_CONTEXT_START_COLUMN + 1` (= 7) and withdraw at `CONTEXT_SIGNED_CONTEXT_START_COLUMN + 2` (= 8). - -### Row constants -- Vault IO rows: token(0), decimals(1), vault_id(2), balance_before(3), balance_diff(4), total = 5. `CONTEXT_VAULT_IO_ROWS = 5`. Correct. -- Calling context rows: order_hash(0), owner(1), counterparty(2), total = 3. `CONTEXT_CALLING_CONTEXT_ROWS = 3`. Correct. -- Calculations rows: max_output(0), io_ratio(1), total = 2. `CONTEXT_CALCULATIONS_ROWS = 2`. Correct. - -### Deposit/Withdraw context row naming -The deposit and withdraw row constants reuse column 1 (`CONTEXT_CALLING_CONTEXT_COLUMN`) but with different row semantics depending on the operation. The deposit rows (token=0, vault_id=1, vault_before=2, vault_after=3) and withdraw rows (token=0, vault_id=1, vault_before=2, vault_after=3, target_amount=4) are used in separate `doPost` calls for deposit and withdraw operations respectively. This is correct -- the same column index is reused with context-specific meaning. - ---- - -## NatSpec vs. Implementation - -### `doPost` function (line 109-138) -- **NatSpec claim:** "Evaluates each task in `post` against the provided `context`. Tasks with empty bytecode are skipped." -- **Verified:** The function iterates over `post` (line 117), checks `task.evaluable.bytecode.length > 0` (line 119) to skip empty bytecode, calls `eval4` with the context merged with signed context (line 128), and persists writes to the store (lines 133-135). Correct. - -### Namespace handling (lines 112-113, 125, 134) -- **`namespace`** (unqualified): `StateNamespace.wrap(uint256(uint160(msg.sender)))` -- derived from `msg.sender`. Used for `store.set()` on line 134. -- **`qualifiedNamespace`** (fully qualified): `LibNamespace.qualifyNamespace(namespace, address(this))` -- qualified with `address(this)`. Used for `eval4()` on line 125. -- **Verified:** `IInterpreterV4.eval4()` takes a `FullyQualifiedNamespace` in its `EvalV4` struct. `IInterpreterStoreV3.set()` takes an unqualified `StateNamespace` (the store qualifies it internally). Both usages are correct per their respective interface contracts. - -### Context building (line 128) -- Uses `LibContext.build(context, task.signedContext)` which merges the caller-provided context matrix with task-specific signed context. Correct. - ---- - -## Test Coverage - -There is no direct unit test file for `LibOrderBook.doPost`. The function is tested indirectly: -- Through `OrderBookV6` operations (deposit, withdraw, addOrder, removeOrder, entask, clear) which all call `doPost`. -- Through `LibOrderBookArb.finalizeArb` tests which call `doPost` with empty-bytecode tasks. - -The deploy tests (`LibOrderBookDeploy.t.sol`, `LibOrderBookDeployProd.t.sol`) test deployment constants and codehashes, not `LibOrderBook` library logic. - ---- - -## Findings - -No findings. All constants, NatSpec, and implementation logic are correct and consistent. diff --git a/audit/2026-03-14-01/pass5/A12-LibOrderBookArb.md b/audit/2026-03-14-01/pass5/A12-LibOrderBookArb.md deleted file mode 100644 index d418a42cd9..0000000000 --- a/audit/2026-03-14-01/pass5/A12-LibOrderBookArb.md +++ /dev/null @@ -1,111 +0,0 @@ -# A12 - LibOrderBookArb.sol - Pass 5 (Correctness / Intent Verification) - -**Source file:** `src/lib/LibOrderBookArb.sol` (77 lines) -**Test files:** -- `test/lib/LibOrderBookArb.finalizeArbNativeGas.t.sol` (110 lines) -- `test/lib/LibOrderBookArb.finalizeArbTokenTransfers.t.sol` (105 lines) - -## Evidence Inventory - -### LibOrderBookArb.sol -- **Library:** `LibOrderBookArb` (line 14) -- **Using:** `SafeERC20 for IERC20` (line 15) -- **Function:** `finalizeArb(TaskV2, address, uint8, address, uint8)` (line 20) - internal - -### Imports -- `TaskV2` from `rain.raindex.interface` -- `IERC20` from OpenZeppelin -- `LibOrderBook` from `./LibOrderBook.sol` -- `Address` from OpenZeppelin -- `SafeERC20` from OpenZeppelin -- `IERC20Metadata` from OpenZeppelin -- **unused import** (see A12-1) -- `LibDecimalFloat, Float` from `rain.math.float` - ---- - -## NatSpec vs. Implementation - -### `finalizeArb` function (lines 17-75) - -**NatSpec claim (line 17-19):** "Sends all remaining token balances and native gas to `msg.sender`, then evaluates the post-arb task with a context column containing the amounts sent as Floats." - -**Verification step-by-step:** - -1. **Input token transfer (lines 30-39):** - - Gets `inputBalance = IERC20(ordersInputToken).balanceOf(address(this))` (line 32) - - If > 0, transfers to `msg.sender` via `safeTransfer` (line 34) - - Converts `inputBalance` to a `Float` via `fromFixedDecimalLossyPacked` using `inputDecimals` (line 37) - - Stores in `col[0]` (line 38) - - **Correct:** Sends all remaining input tokens to sender and records the amount as a Float. - -2. **Output token transfer (lines 41-51):** - - Gets `outputBalance = IERC20(ordersOutputToken).balanceOf(address(this))` (line 43) - - If > 0, transfers to `msg.sender` via `safeTransfer` (line 45) - - Converts to Float via `fromFixedDecimalLossyPacked` using `outputDecimals` (line 49) - - Stores in `col[1]` (line 50) - - **Correct:** Sends all remaining output tokens to sender and records the amount as a Float. - -3. **Native gas transfer (lines 53-68):** - - Gets `gasBalance = address(this).balance` (line 60) - - If > 0, sends via `Address.sendValue` (line 62) - - Converts to Float via `packLossless(int256(gasBalance), -18)` (line 67) - - The `-18` exponent means the value is interpreted as having 18 decimals (native ETH convention) - - Stores in `col[2]` (line 67) - - **Correct:** Sends all remaining native gas to sender and records as a Float with 18-decimal precision. - -4. **Post-arb task evaluation (lines 70-74):** - - Creates context matrix with single column `col` (line 70) - - Wraps task into a single-element `post` array (lines 72-73) - - Calls `LibOrderBook.doPost(context, post)` (line 74) - - **Correct:** Evaluates the post-arb task with the amounts as context. - -**NatSpec accuracy:** Fully matches. The function does exactly what it claims -- sends all balances, then runs the post task with Float amounts as context. - -### `int256(gasBalance)` cast safety (line 67) -- **Comment claim:** "gasBalance can't overflow int256 because there isn't enough gas in existence for that to happen on every production chain." -- **Verified:** `int256` max is ~5.78e76. The total supply of any native gas token on production chains (including ETH at ~120M * 1e18 = ~1.2e26) is far below this. The cast is safe. - -### `packLossless` vs `fromFixedDecimalLossyPacked` (lines 37, 49, 67) -- For ERC20 tokens: uses `fromFixedDecimalLossyPacked` which accepts lossy conversion. This is appropriate because arbitrary token amounts may not fit precisely in the Float representation. -- For native gas: uses `packLossless` which reverts on lossy conversion. This is appropriate because the value and exponent are well-bounded for native gas amounts. -- Both approaches are intentional and documented. - ---- - -## Test Correctness - -### `testFinalizeArbSendsNativeGas` (lines 37-106 in finalizeArbNativeGas.t.sol) -- **Claim:** "finalizeArb MUST send native gas balance to msg.sender." -- **Setup:** Creates mock tokens, orderbook (pulls 100e18), exchange, arb contract. Sends 1 ETH with the `arb5` call. The MockExchange returns ETH back to the arb contract during the swap. -- **Assertions:** - - `address(this).balance == senderBalanceBefore` -- sender gets ETH back (net zero) - - `address(arb).balance == 0` -- arb contract is drained - - `address(exchange).balance == 0` -- exchange is drained -- **Verified:** Correctly tests that `finalizeArb` sweeps all native gas back to `msg.sender`. - -### `testFinalizeArbTransfersInputTokenProfit` (lines 33-104 in finalizeArbTokenTransfers.t.sol) -- **Claim:** "finalizeArb MUST transfer remaining input token profit to msg.sender." -- **Setup:** Creates mock tokens, orderbook (pulls only 80e18 instead of 100e18), exchange (gives 100e18 inputToken). This leaves 20e18 profit on the arb contract. -- **Assertions:** - - `inputToken.balanceOf(address(this)) == 20e18` -- 20e18 profit swept to sender - - `inputToken.balanceOf(address(arb)) == 0` -- arb contract is empty - - `outputToken.balanceOf(address(arb)) == 0` -- arb contract is empty - - `inputToken.balanceOf(address(orderBook)) == 80e18` -- OB got what it pulled - - `outputToken.balanceOf(address(exchange)) == 100e18` -- exchange got its swap -- **Verified:** Correctly tests that `finalizeArb` sweeps all input token profit. - -### Test coverage gaps -- No test verifies that `col[0]`, `col[1]`, `col[2]` context values are correctly passed to the post-arb task. The tests use empty-bytecode tasks (no interpreter), so the context contents are never asserted. -- No test covers the case where `ordersInputToken == ordersOutputToken` (same token for input and output). In this case, `finalizeArb` would transfer the full balance on the first `safeTransfer` call, then `balanceOf` returns 0 for the second check, which is correct behavior but untested. - ---- - -## Findings - -### A12-1: Unused import `IERC20Metadata` (INFO) - -**File:** `src/lib/LibOrderBookArb.sol`, line 10 - -`IERC20Metadata` is imported but never referenced in the library. It was likely needed in a previous version that called `decimals()` directly, but the current code receives decimals as a parameter. - -No production impact; purely a code hygiene issue. diff --git a/audit/2026-03-14-01/pass5/A13-LibOrderBookSubParser.md b/audit/2026-03-14-01/pass5/A13-LibOrderBookSubParser.md deleted file mode 100644 index a924bd7b3f..0000000000 --- a/audit/2026-03-14-01/pass5/A13-LibOrderBookSubParser.md +++ /dev/null @@ -1,181 +0,0 @@ -# A13 - Pass 5: Correctness / Intent Verification -## File: `src/lib/LibOrderBookSubParser.sol` - -### Evidence: Contract Inventory - -**Library**: `LibOrderBookSubParser` - -**Constants** (lines 49-96): -- `SUB_PARSER_WORD_PARSERS_LENGTH = 2` (line 49) -- `EXTERN_PARSE_META_BUILD_DEPTH = 1` (line 50) -- `WORD_ORDER_CLEARER = "order-clearer"` (line 52) -- `WORD_ORDERBOOK = "orderbook"` (line 53) -- `WORD_ORDER_HASH = "order-hash"` (line 54) -- `WORD_ORDER_OWNER = "order-owner"` (line 55) -- `WORD_ORDER_COUNTERPARTY = "order-counterparty"` (line 56) -- `WORD_CALCULATED_MAX_OUTPUT = "calculated-max-output"` (line 57) -- `WORD_CALCULATED_IO_RATIO = "calculated-io-ratio"` (line 58) -- `WORD_INPUT_TOKEN = "input-token"` (line 59) -- `WORD_INPUT_TOKEN_DECIMALS = "input-token-decimals"` (line 60) -- `WORD_INPUT_VAULT_ID = "input-vault-id"` (line 61) -- `WORD_INPUT_VAULT_BALANCE_BEFORE = "input-vault-before"` (line 62) -- `WORD_INPUT_VAULT_BALANCE_INCREASE = "input-vault-increase"` (line 63) -- `WORD_OUTPUT_TOKEN = "output-token"` (line 64) -- `WORD_OUTPUT_TOKEN_DECIMALS = "output-token-decimals"` (line 65) -- `WORD_OUTPUT_VAULT_ID = "output-vault-id"` (line 66) -- `WORD_OUTPUT_VAULT_BALANCE_BEFORE = "output-vault-before"` (line 67) -- `WORD_OUTPUT_VAULT_BALANCE_DECREASE = "output-vault-decrease"` (line 68) -- `WORD_DEPOSITOR = "depositor"` (line 70) -- `WORD_DEPOSIT_TOKEN = "deposit-token"` (line 71) -- `WORD_DEPOSIT_VAULT_ID = "deposit-vault-id"` (line 72) -- `WORD_DEPOSIT_VAULT_BEFORE = "deposit-vault-before"` (line 73) -- `WORD_DEPOSIT_VAULT_AFTER = "deposit-vault-after"` (line 74) -- `WORD_WITHDRAWER = "withdrawer"` (line 76) -- `WORD_WITHDRAW_TOKEN = "withdraw-token"` (line 77) -- `WORD_WITHDRAW_VAULT_ID = "withdraw-vault-id"` (line 78) -- `WORD_WITHDRAW_VAULT_BEFORE = "withdraw-vault-before"` (line 79) -- `WORD_WITHDRAW_VAULT_AFTER = "withdraw-vault-after"` (line 80) -- `WORD_WITHDRAW_TARGET_AMOUNT = "withdraw-target-amount"` (line 81) -- `DEPOSIT_WORD_DEPOSITOR = 0` (line 83) -- `DEPOSIT_WORD_TOKEN = 1` (line 84) -- `DEPOSIT_WORD_VAULT_ID = 2` (line 85) -- `DEPOSIT_WORD_VAULT_BEFORE = 3` (line 86) -- `DEPOSIT_WORD_VAULT_AFTER = 4` (line 87) -- `DEPOSIT_WORDS_LENGTH = 5` (line 88) -- `WITHDRAW_WORD_WITHDRAWER = 0` (line 90) -- `WITHDRAW_WORD_TOKEN = 1` (line 91) -- `WITHDRAW_WORD_VAULT_ID = 2` (line 92) -- `WITHDRAW_WORD_VAULT_BEFORE = 3` (line 93) -- `WITHDRAW_WORD_VAULT_AFTER = 4` (line 94) -- `WITHDRAW_WORD_TARGET_AMOUNT = 5` (line 95) -- `WITHDRAW_WORDS_LENGTH = 6` (line 96) - -**Functions** (lines 105-632): -- `subParserSender` (line 105) -- maps "sender" word to base context column sender row -- `subParserCallingContract` (line 111) -- maps "calling-contract" word to base context column -- `subParserOrderHash` (line 121) -- maps "order-hash" word to calling context column -- `subParserOrderOwner` (line 131) -- maps "order-owner" word to calling context column -- `subParserOrderCounterparty` (line 140) -- maps "order-counterparty" word -- `subParserMaxOutput` (line 152) -- maps "max-output" word to calculations column -- `subParserIORatio` (line 162) -- maps "io-ratio" word to calculations column -- `subParserInputToken` (line 172) -- maps "input-token" word to vault inputs column -- `subParserInputTokenDecimals` (line 182) -- maps "input-token-decimals" word -- `subParserInputVaultId` (line 191) -- maps "input-vault-id" word -- `subParserInputBalanceBefore` (line 201) -- maps "input-balance-before" word -- `subParserInputBalanceDiff` (line 211) -- maps "input-balance-diff" word -- `subParserOutputToken` (line 221) -- maps "output-token" word -- `subParserOutputTokenDecimals` (line 231) -- maps "output-token-decimals" word -- `subParserOutputVaultId` (line 241) -- maps "output-vault-id" word -- `subParserOutputBalanceBefore` (line 251) -- maps "output-balance-before" word -- `subParserOutputBalanceDiff` (line 261) -- maps "output-balance-diff" word -- `subParserSigners` (line 273) -- maps "signers" word, uses operand for row selection -- `subParserDepositToken` (line 283) -- maps "deposit-token" word -- `subParserDepositVaultId` (line 293) -- maps "deposit-vault-id" word -- `subParserDepositVaultBalanceBefore` (line 304) -- maps "deposit-vault-balance-before" word -- `subParserDepositVaultBalanceAfter` (line 317) -- maps "deposit-vault-balance-after" word -- `subParserWithdrawToken` (line 330) -- maps "withdraw-token" word -- `subParserWithdrawVaultId` (line 340) -- maps "withdraw-vault-id" word -- `subParserWithdrawVaultBalanceBefore` (line 351) -- maps "withdraw-vault-balance-before" word -- `subParserWithdrawVaultBalanceAfter` (line 364) -- maps "withdraw-vault-balance-after" word -- `subParserWithdrawTargetAmount` (line 377) -- maps "withdraw-target-amount" word -- `subParserSignedContext` (line 390) -- maps "signed-context" word, operand encodes column+row -- `authoringMetaV2` (line 406) -- builds complete authoring metadata - -### Verification: Sub-parser function column/row mappings - -Every sub-parser function was verified against the context constants in `LibOrderBook.sol`: - -| Function | Column | Row | Correct? | -|---|---|---|---| -| `subParserSender` | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROW_SENDER` (0) | Yes | -| `subParserCallingContract` | `CONTEXT_BASE_COLUMN` (0) | `CONTEXT_BASE_ROW_CALLING_CONTRACT` (1) | Yes | -| `subParserOrderHash` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_HASH` (0) | Yes | -| `subParserOrderOwner` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_OWNER` (1) | Yes | -| `subParserOrderCounterparty` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_ORDER_COUNTERPARTY` (2) | Yes | -| `subParserMaxOutput` | `CONTEXT_CALCULATIONS_COLUMN` (2) | `CONTEXT_CALCULATIONS_ROW_MAX_OUTPUT` (0) | Yes | -| `subParserIORatio` | `CONTEXT_CALCULATIONS_COLUMN` (2) | `CONTEXT_CALCULATIONS_ROW_IO_RATIO` (1) | Yes | -| `subParserInputToken` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_TOKEN` (0) | Yes | -| `subParserInputTokenDecimals` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_TOKEN_DECIMALS` (1) | Yes | -| `subParserInputVaultId` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_VAULT_ID` (2) | Yes | -| `subParserInputBalanceBefore` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_BALANCE_BEFORE` (3) | Yes | -| `subParserInputBalanceDiff` | `CONTEXT_VAULT_INPUTS_COLUMN` (3) | `CONTEXT_VAULT_IO_BALANCE_DIFF` (4) | Yes | -| `subParserOutputToken` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_TOKEN` (0) | Yes | -| `subParserOutputTokenDecimals` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_TOKEN_DECIMALS` (1) | Yes | -| `subParserOutputVaultId` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_VAULT_ID` (2) | Yes | -| `subParserOutputBalanceBefore` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_BALANCE_BEFORE` (3) | Yes | -| `subParserOutputBalanceDiff` | `CONTEXT_VAULT_OUTPUTS_COLUMN` (4) | `CONTEXT_VAULT_IO_BALANCE_DIFF` (4) | Yes | -| `subParserSigners` | `CONTEXT_SIGNED_CONTEXT_SIGNERS_COLUMN` (5) | operand (dynamic) | Yes | -| `subParserDepositToken` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_TOKEN` (0) | Yes | -| `subParserDepositVaultId` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_ID` (1) | Yes | -| `subParserDepositVaultBalanceBefore` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_BEFORE` (2) | Yes | -| `subParserDepositVaultBalanceAfter` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_VAULT_AFTER` (3) | Yes | -| `subParserWithdrawToken` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TOKEN` (0) | Yes | -| `subParserWithdrawVaultId` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_ID` (1) | Yes | -| `subParserWithdrawVaultBalanceBefore` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_BEFORE` (2) | Yes | -| `subParserWithdrawVaultBalanceAfter` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_VAULT_AFTER` (3) | Yes | -| `subParserWithdrawTargetAmount` | `CONTEXT_CALLING_CONTEXT_COLUMN` (1) | `CONTEXT_CALLING_CONTEXT_ROW_WITHDRAW_TARGET_AMOUNT` (4) | Yes | -| `subParserSignedContext` | `CONTEXT_SIGNED_CONTEXT_START_COLUMN` (6) + low byte | row from bits 8-15 | Yes | - -### Verification: `authoringMetaV2()` array indexing - -- Array size = `CONTEXT_COLUMNS_EXTENDED` = 9. Correct (columns 0-8 are all populated). -- `contextBaseMeta` size = `CONTEXT_BASE_ROWS` (2). Indices 0 and 1 populated. Correct. -- `contextCallingContextMeta` size = `CONTEXT_CALLING_CONTEXT_ROWS` (3). Indices 0, 1, 2 populated. Correct. -- `contextCalculationsMeta` size = `CONTEXT_CALCULATIONS_ROWS` (2). Indices 0 and 1 populated. Correct. -- `contextVaultInputsMeta` size = `CONTEXT_VAULT_IO_ROWS` (5). Indices 0-4 populated. Correct. -- `contextVaultOutputsMeta` size = `CONTEXT_VAULT_IO_ROWS` (5). Indices 0-4 populated. Correct. -- `contextSignersMeta` size = `CONTEXT_SIGNED_CONTEXT_SIGNERS_ROWS` (1). Index 0 populated. Correct. -- `contextSignedMeta` size = `CONTEXT_SIGNED_CONTEXT_START_ROWS` (1). Index 0 populated. Correct. -- `depositMeta` size = `DEPOSIT_WORDS_LENGTH` (5). Indices 0-4 populated. Correct. -- `withdrawMeta` size = `WITHDRAW_WORDS_LENGTH` (6). Indices 0-5 populated. Correct. - -### Verification: Word constants match authoring metadata - -All `WORD_*` constants correctly correspond to the bytes32-casted values in the authoring metadata. Each constant string is under 32 bytes, making the `bytes32()` cast safe. - -### Verification: Tests vs Claims - -Tests exercise 17 context words via `OrderBookV6SubParserContextTest`: -- `order-clearer`, `orderbook`, `order-hash`, `order-owner`, `order-counterparty`, `calculated-max-output`, `calculated-io-ratio`, `input-token`, `input-token-decimals`, `input-vault-id`, `input-vault-before`, `input-vault-increase`, `output-token`, `output-token-decimals`, `output-vault-id`, `output-vault-before`, `output-vault-decrease` - -Each test verifies: (1) happy path produces correct context value, (2) operand is disallowed, (3) inputs are disallowed. - -Signer tests: verify operand-based row selection with `signer<0>()` and `signer<1>()`. -Signed context tests: verify two-byte operand selection with all four combinations of column 0-1, row 0-1. - -Tests correctly match behavior described in NatSpec. - -### Verification: `EXTERN_PARSE_META_BUILD_DEPTH` usage - -The constant is defined as `1` at line 50. It is used in `script/BuildPointers.sol` line 75 when calling `LibGenParseMeta.parseMetaConstantString`. However, the test in `OrderBookV6SubParser.pointers.t.sol` line 24 hardcodes `2` instead of using the constant: -```solidity -bytes memory expected = LibGenParseMeta.buildParseMetaV2(authoringMeta, 2); -``` - -### Findings - -#### A13-1: Test uses hardcoded depth `2` instead of `EXTERN_PARSE_META_BUILD_DEPTH` (value `1`) -**Severity**: LOW - -**Location**: `test/concrete/parser/OrderBookV6SubParser.pointers.t.sol`, line 24 - -**Description**: `testSubParserParseMeta()` calls `LibGenParseMeta.buildParseMetaV2(authoringMeta, 2)` with a hardcoded depth of `2`, while the build script (`script/BuildPointers.sol` line 75) uses `EXTERN_PARSE_META_BUILD_DEPTH` which equals `1`. The test compares the result against the pre-generated `SUB_PARSER_PARSE_META` constant (which was built with depth `1`). - -If both depth values happen to produce the same bloom filter for this set of words, the test passes coincidentally. If they produce different results, the test would fail and catch the inconsistency. In either case, the test intent does not match the production build parameter: it should use the same constant to verify the build is reproducible. - -**Impact**: The test does not faithfully verify the production build configuration. A future change to the word set could cause the two depths to diverge silently, and this test would fail for reasons unrelated to the change, or worse, pass when it should fail. - -#### A13-2: `SUB_PARSER_WORD_PARSERS_LENGTH` imported but unused in `OrderBookV6SubParser.sol` -**Severity**: INFO - -**Location**: `src/concrete/parser/OrderBookV6SubParser.sol`, line 16 - -**Description**: The constant `SUB_PARSER_WORD_PARSERS_LENGTH` is imported from `LibOrderBookSubParser.sol` but never referenced in the body of `OrderBookV6SubParser.sol`. This is a dead import. - -**Impact**: No functional impact. Minor code hygiene issue. - -### No Missing Test Coverage for Core Logic - -All 17 standard context words, the signer word, and the signed-context word have dedicated happy-path and unhappy-path tests. The `authoringMetaV2()` function is indirectly tested via `testSubParserParseMeta` (pointers test). The `describedByMeta` test verifies meta hash consistency. IERC165 interface conformance is tested. - -Deposit and withdraw context words (`depositor`, `deposit-token`, `deposit-vault-id`, `deposit-vault-before`, `deposit-vault-after`, `withdrawer`, `withdraw-token`, `withdraw-vault-id`, `withdraw-vault-before`, `withdraw-vault-after`, `withdraw-target-amount`) do not have dedicated sub-parser context tests of the same form as the core 17 words. This is noted but not flagged as a finding since the word-parser pointer and operand-handler tables are verified in the pointers test, and the underlying `subParser*` functions are trivial delegations to `LibSubParse.subParserContext`. diff --git a/audit/2026-03-14-01/pass5/A14-LibOrderBookDeploy.md b/audit/2026-03-14-01/pass5/A14-LibOrderBookDeploy.md deleted file mode 100644 index 482cd0a4f0..0000000000 --- a/audit/2026-03-14-01/pass5/A14-LibOrderBookDeploy.md +++ /dev/null @@ -1,94 +0,0 @@ -# A14 - Pass 5: Correctness / Intent Verification -## File: `src/lib/deploy/LibOrderBookDeploy.sol` - -### Evidence: Contract Inventory - -**Library**: `LibOrderBookDeploy` - -**Constants** (lines 32-52): -- `ORDERBOOK_DEPLOYED_ADDRESS` (line 32) -- aliased from generated `ORDERBOOK_ADDR` -- `ORDERBOOK_DEPLOYED_CODEHASH` (line 36) -- aliased from generated `ORDERBOOK_HASH` -- `SUB_PARSER_DEPLOYED_ADDRESS` (line 40) -- aliased from generated `SUB_PARSER_ADDR` -- `SUB_PARSER_DEPLOYED_CODEHASH` (line 44) -- aliased from generated `SUB_PARSER_HASH` -- `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` (line 48) -- aliased from generated `ROUTE_PROCESSOR_ADDR` -- `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` (line 52) -- aliased from generated `ROUTE_PROCESSOR_HASH` - -**Functions** (lines 58-68): -- `etchOrderBook(Vm vm)` (line 58) -- etches runtime bytecode of OrderBook, SubParser, and RouteProcessor4 - -### Verification: NatSpec vs Implementation - -#### Library-level NatSpec (lines 23-28) -NatSpec: "A library containing the deployed address and code hash of the OrderBook contracts when deployed with the rain standard zoltu deployer." - -Implementation: The library also contains address/hash constants for RouteProcessor4, which is not an "OrderBook contract" -- it is a Sushi RouteProcessor. The NatSpec is slightly incomplete but not materially misleading, as RouteProcessor4 is part of the OrderBook deployment. - -#### `etchOrderBook` NatSpec (lines 54-57) -NatSpec: "Etches the runtime bytecode of the orderbook and sub parser at their expected deterministic addresses. Skips any contract whose codehash already matches." - -Implementation: The function etches **three** contracts -- OrderBook, SubParser, **and RouteProcessor4** (lines 65-67). The NatSpec omits RouteProcessor4. - -### Verification: `etchOrderBook` logic - -The skip logic is correct for each contract: -1. If `ORDERBOOK_DEPLOYED_CODEHASH != ORDERBOOK_DEPLOYED_ADDRESS.codehash` -> etch OrderBook. Correct: skip if already deployed with matching code. -2. Same pattern for SubParser. Correct. -3. Same pattern for RouteProcessor4. Correct. - -The `.codehash` of an address with no code is `bytes32(0)`, which will not equal the expected hash, so the etch proceeds on fresh addresses. Correct. - -### Verification: Tests vs Claims - -**`LibOrderBookDeployTest`** (`test/lib/deploy/LibOrderBookDeploy.t.sol`): - -| Test | Claim | Exercises? | -|---|---|---| -| `testDeployAddressOrderBook` | "Deploying OrderBookV6 via Zoltu MUST produce the expected address and codehash" | Yes -- deploys via Zoltu factory and checks both address and codehash | -| `testDeployAddressSubParser` | Same for SubParser | Yes | -| `testExpectedCodeHashOrderBook` | "The codehash of a freshly deployed OrderBookV6 MUST match the expected codehash constant" | Yes -- deploys with `new` and checks codehash | -| `testExpectedCodeHashSubParser` | Same for SubParser | Yes | -| `testCreationCodeOrderBook` | "The precompiled creation code constant MUST match the compiler's creation code" | Yes | -| `testCreationCodeSubParser` | Same for SubParser | Yes | -| `testRuntimeCodeOrderBook` | "The precompiled runtime code constant MUST match the deployed runtime bytecode" | Yes | -| `testRuntimeCodeSubParser` | Same for SubParser | Yes | -| `testGeneratedDeployedAddressOrderBook` | "The generated deployed address MUST match the deploy library constant" | Yes | -| `testGeneratedDeployedAddressSubParser` | Same for SubParser | Yes | -| `testEtchOrderBook` | "After calling etchOrderBook, both contracts MUST have the expected codehash" | Partially -- only checks OrderBook and SubParser, not RouteProcessor4 | -| `testEtchOrderBookIdempotent` | "Calling etchOrderBook twice MUST be idempotent" | Partially -- same omission | - -**`LibOrderBookDeployProdTest`** (`test/lib/deploy/LibOrderBookDeployProd.t.sol`): -- `_checkAllContracts()` checks code exists and codehash matches for OrderBook and SubParser only. -- Does not verify RouteProcessor4 on any production network. - -### Verification: Constants match generated pointers - -All six constants are direct aliases of the imported generated values. No transformation or transcription errors are possible since they are compile-time assignments. - -### Findings - -#### A14-1: `etchOrderBook` NatSpec omits RouteProcessor4 -**Severity**: LOW - -**Location**: `src/lib/deploy/LibOrderBookDeploy.sol`, lines 54-57 - -**Description**: The `@notice` for `etchOrderBook` says "Etches the runtime bytecode of the orderbook and sub parser" but the function also etches `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` with `ROUTE_PROCESSOR_RUNTIME_CODE` (lines 65-67). The NatSpec should mention all three contracts. - -**Impact**: Developers relying on the NatSpec alone will not know that RouteProcessor4 is also etched, which could cause confusion about test setup side effects. - -#### A14-2: `testEtchOrderBook` and `testEtchOrderBookIdempotent` do not verify RouteProcessor4 -**Severity**: LOW - -**Location**: `test/lib/deploy/LibOrderBookDeploy.t.sol`, lines 100-119 - -**Description**: Both tests call `LibOrderBookDeploy.etchOrderBook(vm)` but only assert the codehashes for `ORDERBOOK_DEPLOYED_ADDRESS` and `SUB_PARSER_DEPLOYED_ADDRESS`. They do not assert that `ROUTE_PROCESSOR_DEPLOYED_ADDRESS.codehash == ROUTE_PROCESSOR_DEPLOYED_CODEHASH`. The tests do not fully verify the behavior of the function they claim to test. - -**Impact**: If the RouteProcessor4 etching broke (e.g., wrong runtime code constant), these tests would not catch it. The `LibRouteProcessor4CreationCode.t.sol` test partially covers this by verifying the codehash of a freshly deployed instance, but does not test the `etchOrderBook` path specifically. - -#### A14-3: `LibOrderBookDeployProdTest` does not verify RouteProcessor4 on production networks -**Severity**: LOW - -**Location**: `test/lib/deploy/LibOrderBookDeployProd.t.sol`, lines 13-21 - -**Description**: `_checkAllContracts()` checks existence and codehash for OrderBook and SubParser on each forked network but does not verify RouteProcessor4. The library exposes `ROUTE_PROCESSOR_DEPLOYED_ADDRESS` and `ROUTE_PROCESSOR_DEPLOYED_CODEHASH` as public constants, implying they should be verified in production the same way. - -**Impact**: If RouteProcessor4 is not deployed on a target network, or is deployed with different bytecode, the production test suite will not catch it. diff --git a/audit/2026-03-14-01/pass5/A15-LibRouteProcessor4CreationCode.md b/audit/2026-03-14-01/pass5/A15-LibRouteProcessor4CreationCode.md deleted file mode 100644 index 6647745b6e..0000000000 --- a/audit/2026-03-14-01/pass5/A15-LibRouteProcessor4CreationCode.md +++ /dev/null @@ -1,62 +0,0 @@ -# A15 - Pass 5: Correctness / Intent Verification -## File: `src/lib/deploy/LibRouteProcessor4CreationCode.sol` - -### Evidence: Contract Inventory - -**Constants** (line 13): -- `ROUTE_PROCESSOR_4_CREATION_CODE` (line 13) -- hex literal containing the full creation bytecode including constructor arguments - -No library, no functions. This file is a pure data file. - -### Verification: NatSpec vs Content - -**NatSpec** (lines 5-12): -- Claims bytecode is "Exact bytecode taken from sushiswap deployments list in github" with link to the SushiSwap RouteProcessor4 deployment JSON. -- Cross-referenced against Etherscan deployment at `0xe43ca1dee3f0fc1e2df73a0745674545f11a59f5`. -- Notes that constructor args are included, translating to `address(0)` for bento (no bento) and no owner addresses. - -**Verification of constructor args**: -The creation code hex ends with: -``` -000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000 -``` -This is ABI-encoded constructor arguments: -- First parameter (address): `address(0)` -- 32 bytes of zeros. This is the "bento" address. -- Second parameter offset: `0x40` (64) pointing to the dynamic array. -- Array length: `0` -- empty array. This is the "owner" privileged addresses list. - -This matches the NatSpec claim of `address(0)` for bento and no owner addresses. - -### Verification: Test vs Claims - -**`LibRouteProcessor4CreationCodeTest`** (`test/lib/deploy/LibRouteProcessor4CreationCode.t.sol`): - -| Test | Claim | Exercises? | -|---|---|---| -| `testRouteProcessor4Codehash` | "Deploying the stored creation code MUST produce runtime bytecode whose hash matches the known Sushi RouteProcessor4 codehash" | Yes | - -The test: -1. Loads the creation code constant. -2. Deploys it using inline assembly `create`. -3. Asserts the deployed address is non-zero (deployment succeeded). -4. Asserts the deployed runtime codehash equals `KNOWN_ROUTE_PROCESSOR_4_CODEHASH`. - -The `KNOWN_ROUTE_PROCESSOR_4_CODEHASH` in the test file: -``` -0xeb3745a79c6ba48e8767b9c355b8e7b79f9d6edeca004e4bb91be4de515a7eeb -``` - -This matches the `BYTECODE_HASH` in `src/generated/RouteProcessor4.pointers.sol`: -``` -bytes32 constant BYTECODE_HASH = bytes32(0xeb3745a79c6ba48e8767b9c355b8e7b79f9d6edeca004e4bb91be4de515a7eeb); -``` - -The runtime code constant in `RouteProcessor4.pointers.sol` also matches the creation code's expected output (the portion after the constructor execution), as verified by the test. - -### Verification: Runtime code consistency - -The `RUNTIME_CODE` in `RouteProcessor4.pointers.sol` (lines 20-21) is a hex constant. When the `ROUTE_PROCESSOR_4_CREATION_CODE` from this file is deployed via `create`, the resulting runtime code's hash should equal `BYTECODE_HASH`. The test confirms this. - -### Findings - -No findings. The file is a straightforward data constant with accurate NatSpec documentation. The constructor arguments are correctly encoded. The test verifies that deploying the creation code produces runtime bytecode matching the known Sushi RouteProcessor4 codehash. The codehash is consistent between the test, the generated pointers file, and the deploy library. diff --git a/audit/2026-03-14-01/triage.md b/audit/2026-03-14-01/triage.md deleted file mode 100644 index 72412961c5..0000000000 --- a/audit/2026-03-14-01/triage.md +++ /dev/null @@ -1,107 +0,0 @@ -# Triage — audit/2026-03-14-01 - -## Legend -- **PENDING** — not yet triaged -- **FIXED** — code changed -- **DOCUMENTED** — documentation/comments added -- **DISMISSED** — no action needed (with reason) -- **UPSTREAM** — fix belongs in a dependency/submodule - -Where a finding was flagged in multiple passes, the primary finding is listed and duplicates are cross-referenced. Triaging the primary finding applies to all its duplicates. - ---- - -## MEDIUM - -| # | ID | Pass | File | Title | Status | Notes | -|---|-----|------|------|-------|--------|-------| -| 1 | A01-2 | P0 | AGENTS.md | No nix shell guidance in AGENTS.md | DISMISSED | Carried from prior triage; same as 2026-03-13-01 A01-2; process doc, not code | -| 2 | A07-1 | P2 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No test for non-18-decimal tokens in onTakeOrders2 | FIXED | Added nonStandardDecimals.t.sol (6-decimal e2e) and lossyRounding.t.sol (lossy conversion round-up) | -| 3 | A08-1 | P2 | OrderBookV6.sol | No test for `MinimumIO` revert in `takeOrders4` | FIXED | Added minimumIO.t.sol with specific MinimumIO revert expectation | -| 4 | A08-2 | P2 | OrderBookV6.sol | No test for `SameOwner` revert in `clear3` | FIXED | Added clear.sameOwner.t.sol with fuzz test | -| 5 | A08-3 | P2 | OrderBookV6.sol | No test for `OrderExceedsMaxRatio` event/skip path in `takeOrders4` | FIXED | Added exceedsMaxRatio.t.sol with event expectation and zero IO assertion | -| 6 | GAP-A12-2 | P2 | LibOrderBookArb.sol | No test for output token profit sweep | FIXED | Added finalizeArbOutputTokenProfit.t.sol verifying 20e18 output token swept to sender | -| 7 | GAP-A12-3 | P2 | LibOrderBookArb.sol | No test verifying post-arb task context values | FIXED | Added finalizeArbTaskContext.t.sol with rainlang ensure expressions verifying Float-encoded context<1 0..2> | -| 8 | A14-1 | P2 | LibOrderBookDeploy.sol | RouteProcessor constants not tested in deploy tests | FIXED | Added RouteProcessor deploy/codehash/address/runtime tests to LibOrderBookDeploy.t.sol; added to prod fork tests | -| 9 | A14-2 | P2 | LibOrderBookDeploy.sol | `etchOrderBook` RouteProcessor branch not verified | FIXED | testEtchOrderBook and testEtchOrderBookIdempotent now assert RouteProcessor codehash | -| 10 | A14-1 | P4 | LibOrderBookDeploy.sol | Production `src/` library imports forge-std `Vm` | FIXED | Extracted `etchOrderBook` to test helper `LibEtchOrderBook`; removed `Vm` import from production code | - -## LOW - -| # | ID | Pass | File | Title | Status | Notes | -|---|-----|------|------|-------|--------|-------| -| 11 | A01-1 | P0 | CLAUDE.md | `@AGENTS.md` syntax is IDE-specific | DISMISSED | Carried from prior triage; process doc | -| 12 | A01-3 | P0 | AGENTS.md | Preflight check omits `forge fmt` | DISMISSED | Carried from prior triage; process doc | -| 13 | A01-4 | P0 | ~/.claude/CLAUDE.md | Global CLAUDE.md applies audit rules universally | DISMISSED | Carried from prior triage; process doc | -| 14 | A08-1 | P1 | OrderBookV6.sol | `clear3` computes order hashes twice each (gas) | DISMISSED | Carried from prior triage 2026-03-13-01; intentional for readability, gas cost minimal vs. external calls | -| 15 | A15-1 | P1 | Deploy.sol | String revert used for unknown deployment suite | DISMISSED | Carried from prior triage 2026-03-13-01; deploy script only | -| 16 | GAP-A03-1 | P2 | OrderBookV6FlashBorrower.sol | No reentrancy test for `arb4` (flash borrower path) | FIXED | Added OrderBookV6FlashBorrower.reentrancy.t.sol with ReentrantExchange that re-enters arb4 during _exchange pool call | -| 17 | A05-1 | P2 | GenericPoolOrderBookV6ArbOrderTaker.sol | No dedicated test for approval revocation after onTakeOrders2 | FIXED | Added approvalRevoked.t.sol asserting max allowance during call and zero after arb5 | -| 18 | A05-2 | P2 | GenericPoolOrderBookV6ArbOrderTaker.sol | No test for pool call revert propagation (order-taker path) | FIXED | Added exchangeRevert.t.sol using LibTestArb.setup abstraction; also refactored 3 flash borrower tests + order-taker approvalRevoked to use shared LibTestFlashBorrowerArb/LibTestArb setup helpers | -| 19 | A06-1 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No test for `spender != pool` in `_exchange` | PENDING | | -| 20 | A06-2 | P2 | GenericPoolOrderBookV6FlashBorrower.sol | No fuzz test over `exchangeData` decoding in `_exchange` | PENDING | | -| 21 | A07-2 | P2 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No test for receive() and fallback() payable functions | PENDING | | -| 22 | A07-3 | P2 | RouteProcessorOrderBookV6ArbOrderTaker.sol | No fuzz test on onTakeOrders2 parameters directly | PENDING | | -| 23 | A08-4 | P2 | OrderBookV6.sol | No test for `OrderZeroAmount` event/skip path in `takeOrders4` | PENDING | | -| 24 | A08-5 | P2 | OrderBookV6.sol | No test for `NegativeVaultBalance` revert | PENDING | | -| 25 | A08-6 | P2 | OrderBookV6.sol | No test for `NegativeVaultBalanceChange` revert | PENDING | | -| 26 | A08-7 | P2 | OrderBookV6.sol | No test for `NegativePull` and `NegativePush` reverts | PENDING | | -| 27 | A08-8 | P2 | OrderBookV6.sol | No test for `IOIsInput = false` branch with `minimumIO` check | PENDING | | -| 28 | A08-12 | P2 | OrderBookV6.sol | No test for `Multicall` functionality | PENDING | | -| 29 | A09-1 | P2 | OrderBookV6SubParser.sol | No dedicated sub-parser unit tests for deposit context words | DISMISSED | Carried from prior triage 2026-03-13-01 #49; trivial constant lookups | -| 30 | A09-2 | P2 | OrderBookV6SubParser.sol | No dedicated sub-parser unit tests for withdraw context words | DISMISSED | Same as #29 | -| 31 | A10-1 | P2 | LibOrder.sol | `testHashNotEqual` missing `vm.assume` guard for equal inputs | PENDING | Dup: A10-1 P5 | -| 32 | GAP-A11-1 | P2 | LibOrderBook.sol | No direct unit test for `doPost` with empty post array | PENDING | | -| 33 | GAP-A11-2 | P2 | LibOrderBook.sol | No test for `doPost` skipping tasks with empty bytecode | PENDING | | -| 34 | GAP-A11-3 | P2 | LibOrderBook.sol | No test for `doPost` store.set path when writes are empty | PENDING | | -| 35 | GAP-A12-1 | P2 | LibOrderBookArb.sol | No test for zero-balance token transfers path | PENDING | | -| 36 | GAP-A12-4 | P2 | LibOrderBookArb.sol | No fuzz testing on finalizeArb | PENDING | | -| 37 | GAP-A13-1 | P2 | LibOrderBookSubParser.sol | No dedicated sub-parser unit tests for deposit/withdraw context words | DISMISSED | Same as #29 | -| 38 | A14-3 | P2 | LibOrderBookDeploy.sol | Prod fork tests do not verify RouteProcessor deployment | PENDING | Dup: A14-3 P5 | -| 39 | GAP-A15-1 | P2 | Deploy.sol | Deploy script has zero unit test coverage | DISMISSED | Carried from prior triage 2026-03-13-01 #43; deploy script tested via CI dry-runs | -| 40 | A02-1 | P3 | OrderBookV6ArbOrderTaker.sol | Constructor has no NatSpec documentation | FIXED | Added `@param config` NatSpec | -| 41 | A02-2 | P3 | OrderBookV6ArbOrderTaker.sol | `onTakeOrders2` parameter names are elided | DISMISSED | Naming unused params causes compiler warnings; elided intentionally | -| 42 | A03-1 | P3 | OrderBookV6FlashBorrower.sol | Constructor has no NatSpec documentation | FIXED | Added `@param config` NatSpec | -| 43 | A03-2 | P3 | OrderBookV6FlashBorrower.sol | `onFlashLoan` parameter names are partially elided | DISMISSED | Naming unused params causes compiler warnings; elided intentionally | -| 44 | A03-3 | P3 | OrderBookV6FlashBorrower.sol | `_exchange` hook docs missing explicit `@notice` tag | FIXED | Added `@dev` tag to `_exchange` hook NatSpec | -| 45 | A05-1 | P3 | GenericPoolOrderBookV6ArbOrderTaker.sol | Constructor has no NatSpec documentation | FIXED | Added `@param config` NatSpec | -| 46 | A05-2 | P3 | GenericPoolOrderBookV6ArbOrderTaker.sol | `onTakeOrders2` override lacks parameter documentation | FIXED | Added `@dev` describing `takeOrdersData` decoding | -| 47 | A06-1 | P3 | GenericPoolOrderBookV6FlashBorrower.sol | Constructor has no NatSpec documentation | FIXED | Added `@param config` NatSpec | -| 48 | A06-2 | P3 | GenericPoolOrderBookV6FlashBorrower.sol | `_exchange` override lacks parameter documentation | FIXED | Added `@dev` describing `exchangeData` decoding | -| 49 | A08-1 | P3 | OrderBookV6.sol | `recordVaultIO` doc comment truncated and inaccurate | FIXED | Rewrote NatSpec with complete param docs | -| 50 | A09-1 | P3 | OrderBookV6SubParser.sol | Missing contract-level NatSpec | FIXED | Added `@title` and `@notice` | -| 51 | A09-2 | P3 | OrderBookV6SubParser.sol | `buildSubParserWordParsers` missing `@inheritdoc` or `@return` | FIXED | Replaced ad-hoc `@dev` with `@inheritdoc IParserToolingV1` | -| 52 | A13-3 | P3 | LibOrderBookSubParser.sol | `authoringMetaV2()` return value doc inaccurate | FIXED | Changed `AuthoringMetaV2[][]` to `AuthoringMetaV2[]`; noted flattening | -| 53 | A14-1 | P3 | LibOrderBookDeploy.sol | `etchOrderBook` NatSpec omits RouteProcessor4 | FIXED | Already correct in new `LibEtchOrderBook.sol`; Dup: A14-1 P5 | -| 54 | A01-1 | P4 | OrderBookV6ArbCommon.sol | Unused `using LibEvaluable for EvaluableV4` directive | FIXED | Removed directive and unused imports | -| 55 | A01-2 | P4 | OrderBookV6ArbCommon.sol | Unused `BEFORE_ARB_SOURCE_INDEX` constant | FIXED | Removed constant and test reference; Dup: A01-1 P5 | -| 56 | A01-3 | P4 | OrderBookV6ArbCommon.sol | Unused `SignedContextV1` import | FIXED | Removed import | -| 57 | A01-4 | P4 | OrderBookV6ArbCommon.sol | Unused `IRaindexV6` import | FIXED | Removed import | -| 58 | A02-1 | P4 | OrderBookV6ArbOrderTaker.sol | Unused imports `EvaluableV4` and `SignedContextV1` | FIXED | Removed imports | -| 59 | A03-1 | P4 | OrderBookV6FlashBorrower.sol | Production code imports forge-std via `LibOrderBookDeploy` | FIXED | Fixed via #10; `LibOrderBookDeploy` no longer imports forge-std | -| 60 | A05-1 | P4 | GenericPoolOrderBookV6ArbOrderTaker.sol | Duplicated exchange pattern across GenericPool arb contracts | FIXED | Extracted to `LibGenericPoolExchange.exchange()` | -| 61 | A06-1 | P4 | GenericPoolOrderBookV6FlashBorrower.sol | Duplicated exchange pattern (dup of #60) | FIXED | Fixed via #60 | -| 62 | A07-1 | P4 | RouteProcessorOrderBookV6ArbOrderTaker.sol | Missing `sushixswap-v2` remapping in `foundry.toml` | FIXED | Added explicit remapping | -| 63 | A08-1 | P4 | OrderBookV6.sol | Stale `IOrderBookV1` reference in NatDoc comment | FIXED | Updated to `IRaindexV6`; Dup: A08-1 P5 | -| 64 | A08-2 | P4 | OrderBookV6.sol | Unused errors `TokenDecimalsMismatch`, `NegativeInput`, `NegativeOutput`, `UnsupportedCalculateInputs` | FIXED | Removed 4 unused error declarations + test import | -| 65 | A09-1 | P4 | OrderBookV6SubParser.sol | Missing `rain.lib.typecast` remapping in `foundry.toml` | FIXED | Added explicit remapping | -| 66 | A09-2 | P4 | OrderBookV6SubParser.sol | Bare `src/` import paths in test/script files | FIXED | Converted all 111 bare `src/` imports to relative paths across 72 files | -| 67 | A10-1 | P4 | LibOrder.sol | Inconsistent pragma version (`^0.8.18` vs `^0.8.19`) | FIXED | Changed to `^0.8.19` | -| 68 | A11-1 | P4 | LibOrderBook.sol | Unused imports from LibContext.sol | FIXED | Removed unused constant imports | -| 69 | A12-1 | P4 | LibOrderBookArb.sol | Unused import `IERC20Metadata` | FIXED | Removed unused import; Dup: A12-1 P5 | -| 70 | A13-1 | P4 | LibOrderBookSubParser.sol | Pragma version inconsistency across `src/lib/` | FIXED | Fixed via #67; Dup: A10-1 P4 (#67) | -| 71 | A13-3 | P4 | LibOrderBookSubParser.sol | Deposit metadata uses row+1 offsets instead of named constants | FIXED | Replaced `CONTEXT_CALLING_CONTEXT_ROW_DEPOSIT_* + 1` with `DEPOSIT_WORD_*` constants | -| 72 | A03-1 | P5 | OrderBookV6FlashBorrower.sol | Test contract name uses "V5" instead of "V6" | FIXED | Renamed contract and function to V6 | -| 73 | A04-1 | P5 | OrderBookV6FlashLender.sol | `flashFee` does not revert for unsupported tokens per ERC-3156 | PENDING | | -| 74 | A08-1 | P5 | OrderBookV6.sol | NatSpec says "18 decimal fixed point" but uses Floats | FIXED | Updated NatSpec to say "Float values" | -| 75 | A13-1 | P5 | LibOrderBookSubParser.sol | Test uses hardcoded depth `2` instead of `EXTERN_PARSE_META_BUILD_DEPTH` (1) | FIXED | Test now uses `EXTERN_PARSE_META_BUILD_DEPTH` constant | - -## CodeRabbit (PR #2512) - -| # | ID | File | Title | Status | Notes | -|---|-----|------|-------|--------|-------| -| 76 | CR-1 | LibGenericPoolExchange.sol | No zero-address guards for decoded spender/pool | PENDING | | -| 77 | CR-2 | LibOrderBookDeployProd.t.sol | Comments say "Both contracts" but 3 are verified | PENDING | | -| 78 | CR-3 | OrderBookV6FlashBorrower.sol | NatSpec references obsolete `onlyValidTask`; code uses `_beforeArb` | PENDING | | -| 79 | CR-4 | Tests (multiple) | Repeated TaskV2 literal with deploy addresses should be shared helper | FIXED | Extracted to LibTestArb.noopTask() shared helper | -| 80 | CR-5 | Tests (multiple) | Inconsistent use of `address(0)` vs `LibInterpreterDeploy` constants | FIXED | LibTestArb.noopTask() and setupAndArb() use deploy constants throughout | diff --git a/crates/bindings/ARCHITECTURE.md b/crates/bindings/ARCHITECTURE.md index 1cb8c4c4f9..052de9012e 100644 --- a/crates/bindings/ARCHITECTURE.md +++ b/crates/bindings/ARCHITECTURE.md @@ -1,11 +1,11 @@ -Rain Orderbook Bindings — Architecture +Rain Raindex Bindings — Architecture Summary -- Purpose: Provide strongly typed Rust bindings to the Rain Orderbook Solidity contracts and small utilities for calling them from Rust (native and WASM). The crate centralizes ABI-derived types and call helpers so the rest of the workspace can construct calldata, perform reads, and expose safe JS-facing types. +- Purpose: Provide strongly typed Rust bindings to the Rain Raindex Solidity contracts and small utilities for calling them from Rust (native and WASM). The crate centralizes ABI-derived types and call helpers so the rest of the workspace can construct calldata, perform reads, and expose safe JS-facing types. - Scope: ABI-based type generation via Alloy, a read‑only provider builder with multi‑RPC fallback, and WASM interop shims (TypeScript typings + conversions). File Layout -- Cargo.toml: Declares the crate `rain_orderbook_bindings`. Key deps: `alloy` (codegen + types + RPC), `serde` (Serialize/Deserialize), `tower` (layers), `url`, `thiserror`. For WASM builds it uses `wasm-bindgen-utils` and `wasm-bindgen-test` for tests. +- Cargo.toml: Declares the crate `raindex_bindings`. Key deps: `alloy` (codegen + types + RPC), `serde` (Serialize/Deserialize), `tower` (layers), `url`, `thiserror`. For WASM builds it uses `wasm-bindgen-utils` and `wasm-bindgen-test` for tests. - src/lib.rs: Declares contract bindings using Alloy’s `sol!` macro and re‑exports internal modules. Conditionally includes WASM modules. - src/provider.rs: Builds a read‑only provider with multi‑RPC fallback and sensible default request fillers. - src/js_api.rs (wasm only): JS/WASM interop. Implements wasm conversion traits and custom TypeScript interfaces for selected ABI types used in the GUI. @@ -15,10 +15,10 @@ Generated Solidity Bindings (Alloy `sol!`) - The crate uses `alloy::sol!` to generate Rust modules, types, and (optionally) RPC call helpers from contract ABIs produced by Foundry. ABIs are read from the repository’s `out/` directory. - Bindings defined in `src/lib.rs`: - - `IOrderBookV5, "../../out/IOrderBookV5.sol/IOrderBookV5.json"` + - `IRaindexV5, "../../out/IRaindexV5.sol/IRaindexV5.json"` - Attributes: `#![sol(all_derives = true, rpc)]`, `#![sol(extra_derives(serde::Serialize, serde::Deserialize))]`. - Effect: Generates Rust types for all ABI structs/enums/events and RPC instance helpers for calling the contract. Adds `Serialize/Deserialize` derives for ergonomic (de)serialization. - - `OrderBook, "../../out/OrderBook.sol/OrderBook.json"` + - `Raindex, "../../out/Raindex.sol/Raindex.json"` - Attributes: `#![sol(all_derives = true)]`, `#![sol(extra_derives(serde::Serialize, serde::Deserialize))]`. - Effect: Same as above but without the `rpc` helpers. This is sufficient for constructing/calculating calldata (e.g., `multicallCall`) without needing a bound instance type. - `IERC20, "../../out/IERC20.sol/IERC20.json"` @@ -29,8 +29,8 @@ Generated Solidity Bindings (Alloy `sol!`) - Effect: Full types for concrete ERC‑20; used for calldata construction and decoding when instance helpers aren’t required. - Practical result of the `sol!(… rpc)` attribute: - - For `IOrderBookV5` and `IERC20`, you can construct an instance bound to a provider and call methods with strong typing, for example: `let ob = IOrderBookV5Instance::new(address, provider.clone()); ob.quote2(config).await?`. - - For all bindings, you can still directly use generated call structs, e.g., `IOrderBookV5::removeOrder3Call { ... }.abi_encode()` or `OrderBook::multicallCall { ... }`. + - For `IRaindexV5` and `IERC20`, you can construct an instance bound to a provider and call methods with strong typing, for example: `let ob = IRaindexV5Instance::new(address, provider.clone()); ob.quote2(config).await?`. + - For all bindings, you can still directly use generated call structs, e.g., `IRaindexV5::removeOrder3Call { ... }.abi_encode()` or `Raindex::multicallCall { ... }`. - Derives and defaults: - `all_derives = true` enables useful traits on generated types, including `Clone`, `Debug`, `Default`, `Eq`, `PartialEq`, and more, which the codebase relies on (e.g., `OrderV4::default()`). @@ -88,20 +88,20 @@ WASM Numeric Conversion (`src/wasm_traits.rs`) How This Crate Is Used Elsewhere - Quote engine (`crates/quote`): - - Imports `IOrderBookV5::IOrderBookV5Instance` and `mk_read_provider`. + - Imports `IRaindexV5::IRaindexV5Instance` and `mk_read_provider`. - Binds the instance to a provider and calls `quote2` for many orders via Alloy’s multicall helper. - Common utilities (`crates/common`): - Uses ABI‑generated call structs (e.g., `deposit3Call`, `withdraw3Call`, `removeOrder3Call`, `IERC20::approveCall`) to build calldata for transactions. - JS API (`crates/js_api`): - - Builds GUI calldata for approvals/deposits/add‑order and uses call structs like `OrderBook::multicallCall` without needing on‑chain RPC instance helpers. + - Builds GUI calldata for approvals/deposits/add‑order and uses call structs like `Raindex::multicallCall` without needing on‑chain RPC instance helpers. - CLI (`crates/cli`): - Consumes ABI struct types such as `OrderV4` and `IOV2` to construct orders from user inputs. Design Choices and Rationale - Keep bindings centralized: All ABI structs and call helpers live in one place so downstream crates share a single, consistent type system. - Split `rpc` vs. non‑`rpc` bindings: - - `IOrderBookV5`/`IERC20` include RPC instance helpers for ergonomic reads. - - `OrderBook`/`ERC20` are included without `rpc` when only calldata construction/decoding is required. + - `IRaindexV5`/`IERC20` include RPC instance helpers for ergonomic reads. + - `Raindex`/`ERC20` are included without `rpc` when only calldata construction/decoding is required. - Provider is read‑only by design: This crate does not handle signing or nonce management beyond auto‑fillers. Submission/signature flows live in other crates. - WASM boundary is explicit: Hand‑authored TS interfaces lock the surface area for the webapp, preventing accidental breaking changes from codegen drift. @@ -111,19 +111,19 @@ Error Handling - ABI call errors, revert decoding, and multicall aggregation are handled in consumer crates (e.g., `quote`), leveraging these bindings for encoding/decoding. Build and Test -- Build (workspace): `nix develop -c cargo build -p rain_orderbook_bindings`. +- Build (workspace): `nix develop -c cargo build -p raindex_bindings`. - Tests (native and wasm; wasm executed via runner in the flake): - - Native: `nix develop -c cargo test -p rain_orderbook_bindings`. - - WASM: the workspace’s Nix config sets `CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner'` and runs `cargo test --target wasm32-unknown-unknown -p rain_orderbook_bindings`. + - Native: `nix develop -c cargo test -p raindex_bindings`. + - WASM: the workspace’s Nix config sets `CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner'` and runs `cargo test --target wasm32-unknown-unknown -p raindex_bindings`. Examples - Constructing a read provider and querying via an instance (native): - Parse URLs to `url::Url` and build: `let provider = mk_read_provider(&rpcs)?;` - - Bind to an orderbook: `let ob = IOrderBookV5Instance::new(orderbook_addr, provider.clone());` + - Bind to a raindex: `let ob = IRaindexV5Instance::new(raindex_addr, provider.clone());` - Call a view: `let quote = ob.quote2(config).await?;` - Building calldata without an instance: - - `use rain_orderbook_bindings::IOrderBookV5::removeOrder3Call;` + - `use raindex_bindings::IRaindexV5::removeOrder3Call;` - Construct the struct and encode: `let bytes = removeOrder3Call { order, tasks }.abi_encode();` Limitations and Notes diff --git a/crates/bindings/Cargo.toml b/crates/bindings/Cargo.toml index bce3aef708..c3413923b1 100644 --- a/crates/bindings/Cargo.toml +++ b/crates/bindings/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_bindings" -description = "Bindings for the Rain Orderbook Solidity contracts to Rust types." +name = "raindex_bindings" +description = "Bindings for the Raindex Solidity contracts to Rust types." version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs index 2456622ad6..3e3a6dfc22 100644 --- a/crates/bindings/src/lib.rs +++ b/crates/bindings/src/lib.rs @@ -9,7 +9,7 @@ sol!( sol!( #![sol(all_derives = true)] #![sol(extra_derives(serde::Serialize, serde::Deserialize))] - OrderBook, "../../out/OrderBookV6.sol/OrderBookV6.json" + Raindex, "../../out/RaindexV6.sol/RaindexV6.json" ); // Inline definition avoids non-deterministic artifact collision between @@ -60,11 +60,11 @@ pub mod topics { IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, RemoveOrderV3, TakeOrderV3, WithdrawV2, }, - OrderBook::MetaV1_2, + Raindex::MetaV1_2, }; use alloy::{primitives::B256, sol_types::SolEvent}; - pub const ORDERBOOK_EVENT_TOPICS: [B256; 8] = [ + pub const RAINDEX_EVENT_TOPICS: [B256; 8] = [ AddOrderV3::SIGNATURE_HASH, TakeOrderV3::SIGNATURE_HASH, WithdrawV2::SIGNATURE_HASH, diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 69e9e44b46..75ce54d437 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_cli" -description = "Rain Orderbook CLI." +name = "raindex_cli" +description = "Raindex CLI." version.workspace = true edition.workspace = true license.workspace = true @@ -11,11 +11,11 @@ homepage.workspace = true [dependencies] alloy-ethers-typecast = { workspace = true } alloy = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_common = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_quote = { workspace = true } +raindex_subgraph_client = { workspace = true } +raindex_bindings = { workspace = true } +raindex_common = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_quote = { workspace = true } anyhow = { workspace = true } async-trait = { workspace = true } clap = { workspace = true } @@ -52,4 +52,4 @@ httpmock = "0.7.0" rain-metadata = { workspace = true } rain_interpreter_bindings = { workspace = true } tempfile.workspace = true -rain_orderbook_test_fixtures = { workspace = true } +raindex_test_fixtures = { workspace = true } diff --git a/crates/cli/src/commands/chart.rs b/crates/cli/src/commands/chart.rs index 5116782b23..6fd0f74f1a 100644 --- a/crates/cli/src/commands/chart.rs +++ b/crates/cli/src/commands/chart.rs @@ -1,7 +1,7 @@ use crate::execute::Execute; use anyhow::{anyhow, Result}; use clap::Args; -use rain_orderbook_common::fuzz::{FuzzRunner, FuzzRunnerContext}; +use raindex_common::fuzz::{FuzzRunner, FuzzRunnerContext}; use std::fs::read_to_string; use std::path::PathBuf; use tracing::info; @@ -31,8 +31,8 @@ impl Execute for Chart { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_test_fixtures::LocalEvm; use std::io::Write; use tempfile::NamedTempFile; @@ -50,14 +50,14 @@ tokens: decimals: 18 orders: flare: - orderbook: "flare" + raindex: "flare" inputs: - token: "token1" outputs: - token: "token2" scenarios: flare: - orderbook: "flare" + raindex: "flare" runs: 1 bindings: raindex-subparser: {subparser} @@ -70,7 +70,7 @@ deployments: ) } - fn get_settings(rpc: &str, orderbook: &str, rainlang: &str) -> String { + fn get_settings(rpc: &str, raindex: &str, rainlang: &str) -> String { format!( r#" version: {spec_version} @@ -84,9 +84,9 @@ subgraphs: flare: "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-flare/2024-12-13-9dc7/gn" metaboards: flare: "https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn" -orderbooks: +raindexes: flare: - address: {orderbook} + address: {raindex} network: "flare" subgraph: "flare" rainlangs: @@ -183,19 +183,19 @@ io: fixed-io; #[tokio::test(flavor = "multi_thread")] async fn test_chart_execute_success() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; - let orderbook_subparser = &local_evm.orderbook_subparser; + let raindex = &local_evm.raindex; + let raindex_subparser = &local_evm.raindex_subparser; let rainlang = local_evm.rainlang; let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); let settings = get_settings( &local_evm.url(), - &orderbook.address().to_string(), + &raindex.address().to_string(), &rainlang.to_string(), ); let dotrain_prefix = get_dotrain_prefix( - &orderbook_subparser.address().to_string(), + &raindex_subparser.address().to_string(), &token1.address().to_string(), &token2.address().to_string(), ); @@ -235,19 +235,19 @@ io: fixed-io; #[tokio::test(flavor = "multi_thread")] async fn test_chart_execute_missing_scenario() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; - let orderbook_subparser = &local_evm.orderbook_subparser; + let raindex = &local_evm.raindex; + let raindex_subparser = &local_evm.raindex_subparser; let rainlang = local_evm.rainlang; let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); let settings = get_settings( &local_evm.url(), - &orderbook.address().to_string(), + &raindex.address().to_string(), &rainlang.to_string(), ); let dotrain_prefix = get_dotrain_prefix( - &orderbook_subparser.address().to_string(), + &raindex_subparser.address().to_string(), &token1.address().to_string(), &token2.address().to_string(), ); @@ -292,19 +292,19 @@ charts: #[tokio::test(flavor = "multi_thread")] async fn test_chart_execute_missing_rpc_response() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; - let orderbook_subparser = &local_evm.orderbook_subparser; + let raindex = &local_evm.raindex; + let raindex_subparser = &local_evm.raindex_subparser; let rainlang = local_evm.rainlang; let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); let settings = get_settings( "http://localhost:8545", - &orderbook.address().to_string(), + &raindex.address().to_string(), &rainlang.to_string(), ); let dotrain_prefix = get_dotrain_prefix( - &orderbook_subparser.address().to_string(), + &raindex_subparser.address().to_string(), &token1.address().to_string(), &token2.address().to_string(), ); diff --git a/crates/cli/src/commands/local_db/README.md b/crates/cli/src/commands/local_db/README.md index 3a885689d7..80b01ca0a3 100644 --- a/crates/cli/src/commands/local_db/README.md +++ b/crates/cli/src/commands/local_db/README.md @@ -1,18 +1,18 @@ -# Rain Orderbook CLI — LocalDB +# Raindex CLI — LocalDB The legacy subcommands in this directory have been replaced by a single orchestration entry point: `local-db sync`. It drives the entire SQLite pipeline—bootstrap, fetch, decode, apply, export, and manifest generation—using the same engine that powers the browser sync. ## Pipeline Overview -- Parse the Rain settings YAML to discover networks, RPCs, orderbooks, and per-network sync parameters. -- Optionally download and import the most recent dump referenced by each orderbook’s `local-db-remote` manifest. -- Run the local DB engine for every orderbook concurrently, fetching logs via HyperRPC, decoding events, fetching token metadata, and applying the resulting SQL into a fresh SQLite database. +- Parse the Rain settings YAML to discover networks, RPCs, raindexes, and per-network sync parameters. +- Optionally download and import the most recent dump referenced by each raindex’s `local-db-remote` manifest. +- Run the local DB engine for every raindex concurrently, fetching logs via HyperRPC, decoding events, fetching token metadata, and applying the resulting SQL into a fresh SQLite database. - Export a gzipped SQL dump for the synced state and write an aggregated `manifest.yaml` that maps release URLs to the produced dumps when all jobs succeed. ## Usage Run the command from the workspace root so the CLI crate is available: ```bash -nix develop -c cargo run -p rain_orderbook_cli -- local-db sync \ +nix develop -c cargo run -p raindex_cli -- local-db sync \ --settings-yaml "https://github.com/rainlanguage/rain.strategies/blob/main/settings.yaml" \ --api-token "$HYPERRPC_TOKEN" \ --release-base-url "https://github.com/rainlanguage/rain.local-db.remote/releases/latest" \ @@ -28,21 +28,21 @@ nix develop -c cargo run -p rain_orderbook_cli -- local-db sync \ ## Settings YAML Expectations The runner consumes the same schema as `crates/cli/settings.yaml`: - `networks`: chain metadata plus RPC endpoints used for metadata reads. -- `orderbooks`: each entry must reference a `network`, declare a `deployment-block`, and point to a `local-db-remote` manifest URL. +- `raindexes`: each entry must reference a `network`, declare a `deployment-block`, and point to a `local-db-remote` manifest URL. - `local-db-remotes`: map of manifest aliases to URLs; manifests describe previously published dumps that can be used as a bootstrap baseline. - `local-db-sync`: per-network fetch configuration (batch size, concurrency, retry policy, finality depth). -Validation is handled by `rain_orderbook_app_settings`, and missing sections will surface as CLI errors before any network calls are made. +Validation is handled by `raindex_app_settings`, and missing sections will surface as CLI errors before any network calls are made. ## Outputs All artifacts live under `--out-root`: -- `/.db`: fresh SQLite database containing the synced state. -- `/-.sql.gz`: gzipped SQL transaction with the data delta at the synced head. -- `manifest.yaml`: generated only when every orderbook finishes successfully; references each dump using the provided `--release-base-url`. +- `/.db`: fresh SQLite database containing the synced state. +- `/-.sql.gz`: gzipped SQL transaction with the data delta at the synced head. +- `manifest.yaml`: generated only when every raindex finishes successfully; references each dump using the provided `--release-base-url`. Each run starts from a clean SQLite file. When a remote manifest exposes a prior dump, it is downloaded and replayed before the new sync to avoid replaying the entire chain from genesis. ## Operational Notes -- The command reports a per-orderbook summary once all jobs finish; non-zero failures prevent manifest emission. +- The command reports a per-raindex summary once all jobs finish; non-zero failures prevent manifest emission. - Supported chains are limited to those exposed by HyperRPC. Providing an unsupported `chain-id` in the settings YAML will fail early. - Upload the generated `.sql.gz` files to the location represented by `--release-base-url` before distributing `manifest.yaml`. diff --git a/crates/cli/src/commands/local_db/cli.rs b/crates/cli/src/commands/local_db/cli.rs index f1ebef0b71..c6f8387a16 100644 --- a/crates/cli/src/commands/local_db/cli.rs +++ b/crates/cli/src/commands/local_db/cli.rs @@ -2,13 +2,13 @@ use super::pipeline::runner::ProducerRunReport; use crate::commands::local_db::pipeline::runner::ProducerRunner; use anyhow::Result; use clap::Parser; -use rain_orderbook_common::local_db::pipeline::runner::TargetFailure; +use raindex_common::local_db::pipeline::runner::TargetFailure; use std::io::{self, Write}; use std::path::PathBuf; use url::Url; #[derive(Debug, Clone, Parser)] -#[command(about = "Run the producer pipeline across all orderbooks in settings.yaml")] +#[command(about = "Run the producer pipeline across all raindexes in settings.yaml")] pub struct RunPipeline { #[clap( long, @@ -26,7 +26,7 @@ pub struct RunPipeline { #[clap( long, - help = "Output directory where per-orderbook SQLite databases and dumps are written", + help = "Output directory where per-raindex SQLite databases and dumps are written", value_name = "PATH", default_value = "./local-db" )] @@ -98,14 +98,14 @@ fn render_report_to(report: &ProducerRunReport, writer: &mut W) -> io: report.successes().len() )?; for outcome in report.successes() { - let ob_id = &outcome.outcome.ob_id; - match report.export_for(ob_id) { + let raindex_id = &outcome.outcome.raindex_id; + match report.export_for(raindex_id) { Some(export) => { writeln!( writer, - "- chain {} orderbook {:#x}: start {} → target {} | logs {} | events {} | dump {} (end block {}, hash {}, time {})", - ob_id.chain_id, - ob_id.orderbook_address, + "- chain {} raindex {:#x}: start {} → target {} | logs {} | events {} | dump {} (end block {}, hash {}, time {})", + raindex_id.chain_id, + raindex_id.raindex_address, outcome.outcome.start_block, outcome.outcome.target_block, outcome.outcome.fetched_logs, @@ -119,9 +119,9 @@ fn render_report_to(report: &ProducerRunReport, writer: &mut W) -> io: None => { writeln!( writer, - "- chain {} orderbook {:#x}: start {} → target {} | logs {} | events {} | dump ", - ob_id.chain_id, - ob_id.orderbook_address, + "- chain {} raindex {:#x}: start {} → target {} | logs {} | events {} | dump ", + raindex_id.chain_id, + raindex_id.raindex_address, outcome.outcome.start_block, outcome.outcome.target_block, outcome.outcome.fetched_logs, @@ -149,22 +149,22 @@ fn render_report_to(report: &ProducerRunReport, writer: &mut W) -> io: } fn render_failure_to(failure: &TargetFailure, writer: &mut W) -> io::Result<()> { - let ob_id = &failure.ob_id; - let address = ob_id.orderbook_address; - let chain_id = ob_id.chain_id; + let raindex_id = &failure.raindex_id; + let address = raindex_id.raindex_address; + let chain_id = raindex_id.chain_id; let stage = failure.stage; let message = failure.error.to_readable_msg(); let key = failure - .orderbook_key + .raindex_key .as_deref() - .unwrap_or(""); + .unwrap_or(""); if chain_id == 0 && address.is_zero() { writeln!(writer, "- job {} failed at {:?}: {}", key, stage, message) } else { writeln!( writer, - "- chain {} orderbook {:#x} ({}) failed at {:?}: {}", + "- chain {} raindex {:#x} ({}) failed at {:?}: {}", chain_id, address, key, stage, message ) } @@ -176,15 +176,13 @@ mod tests { use super::*; use alloy::primitives::{address, Address}; - use rain_orderbook_common::local_db::pipeline::engine::SyncInputs; - use rain_orderbook_common::local_db::pipeline::runner::utils::RunnerTarget; - use rain_orderbook_common::local_db::pipeline::runner::{ - TargetFailure, TargetStage, TargetSuccess, - }; - use rain_orderbook_common::local_db::pipeline::{ + use raindex_common::local_db::pipeline::engine::SyncInputs; + use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; + use raindex_common::local_db::pipeline::runner::{TargetFailure, TargetStage, TargetSuccess}; + use raindex_common::local_db::pipeline::{ FinalityConfig, SyncConfig, SyncOutcome, WindowOverrides, }; - use rain_orderbook_common::local_db::{FetchConfig, LocalDbError, OrderbookIdentifier}; + use raindex_common::local_db::{FetchConfig, LocalDbError, RaindexIdentifier}; use std::collections::HashMap; #[test] @@ -202,7 +200,7 @@ mod tests { } fn sample_success_and_export(chain_id: u32) -> (TargetSuccess, ExportMetadata) { - let ob_id = OrderbookIdentifier::new( + let raindex_id = RaindexIdentifier::new( chain_id, address!("0000000000000000000000000000000000000a11"), ); @@ -214,7 +212,7 @@ mod tests { window_overrides: WindowOverrides::default(), }; let inputs = SyncInputs { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), metadata_rpcs: Vec::new(), cfg: sync_config, dump_str: None, @@ -222,14 +220,14 @@ mod tests { manifest_end_block: 1, }; let runner_target = RunnerTarget { - orderbook_key: "test".to_string(), + raindex_key: "test".to_string(), manifest_url: "https://example.com/manifest.yaml".parse().unwrap(), network_key: "anvil".to_string(), inputs, }; let outcome = SyncOutcome { - ob_id: runner_target.inputs.ob_id.clone(), + raindex_id: runner_target.inputs.raindex_id.clone(), start_block: 200, target_block: 400, fetched_logs: 123, @@ -238,7 +236,7 @@ mod tests { let export = ExportMetadata { dump_path: PathBuf::from(format!( "./local-db/{}/{}-{}.sql.gz", - chain_id, chain_id, runner_target.inputs.ob_id.orderbook_address + chain_id, chain_id, runner_target.inputs.raindex_id.raindex_address )), end_block: 400, end_block_hash: "0xdeadbeef".to_string(), @@ -252,7 +250,7 @@ mod tests { fn render_report_to_writes_success_summary() { let (success, export) = sample_success_and_export(42161); let mut exports = HashMap::new(); - exports.insert(success.outcome.ob_id.clone(), Some(export)); + exports.insert(success.outcome.raindex_id.clone(), Some(export)); let report = ProducerRunReport { successes: vec![success], failures: vec![], @@ -274,7 +272,7 @@ mod tests { fn render_report_to_handles_missing_dump() { let (success, _) = sample_success_and_export(10); let mut exports = HashMap::new(); - exports.insert(success.outcome.ob_id.clone(), None); + exports.insert(success.outcome.raindex_id.clone(), None); let report = ProducerRunReport { successes: vec![success], failures: vec![], @@ -290,10 +288,10 @@ mod tests { #[test] fn render_report_to_lists_failures() { - let orderbook_address = address!("0000000000000000000000000000000000000fA1"); + let raindex_address = address!("0000000000000000000000000000000000000fA1"); let failure = TargetFailure { - ob_id: OrderbookIdentifier::new(1, orderbook_address), - orderbook_key: Some("book".into()), + raindex_id: RaindexIdentifier::new(1, raindex_address), + raindex_key: Some("book".into()), stage: TargetStage::EngineRun, error: LocalDbError::CustomError("oh no".into()), }; @@ -309,22 +307,22 @@ mod tests { let output = String::from_utf8(buffer).expect("utf8"); assert!(output.contains("No producer jobs completed successfully.")); assert!(output.contains("1 job(s) failed")); - assert!(output.contains(&format!("chain {} orderbook {:#x}", 1, orderbook_address))); + assert!(output.contains(&format!("chain {} raindex {:#x}", 1, raindex_address))); assert!(output.contains("oh no")); } #[test] fn render_failure_to_handles_unknowns() { let failure = TargetFailure { - ob_id: OrderbookIdentifier::new(0, Address::ZERO), - orderbook_key: None, + raindex_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_key: None, stage: TargetStage::EngineRun, error: LocalDbError::CustomError("boom".into()), }; let mut buffer = Vec::new(); render_failure_to(&failure, &mut buffer).expect("render succeeds"); let output = String::from_utf8(buffer).expect("utf8"); - assert!(output.contains("job failed")); + assert!(output.contains("job failed")); assert!(output.contains("EngineRun")); } } diff --git a/crates/cli/src/commands/local_db/executor.rs b/crates/cli/src/commands/local_db/executor.rs index 761817f406..c4414c764d 100644 --- a/crates/cli/src/commands/local_db/executor.rs +++ b/crates/cli/src/commands/local_db/executor.rs @@ -1 +1 @@ -pub use rain_orderbook_common::local_db::executor::RusqliteExecutor; +pub use raindex_common::local_db::executor::RusqliteExecutor; diff --git a/crates/cli/src/commands/local_db/pipeline/bootstrap.rs b/crates/cli/src/commands/local_db/pipeline/bootstrap.rs index 03855b52fe..dc7bf8daa7 100644 --- a/crates/cli/src/commands/local_db/pipeline/bootstrap.rs +++ b/crates/cli/src/commands/local_db/pipeline/bootstrap.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::local_db::{ +use raindex_common::local_db::{ pipeline::adapters::bootstrap::{BootstrapConfig, BootstrapPipeline}, query::LocalDbQueryExecutor, LocalDbError, @@ -44,14 +44,14 @@ mod tests { use super::*; use alloy::primitives::Address; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; - use rain_orderbook_common::local_db::query::clear_tables::clear_tables_stmt; - use rain_orderbook_common::local_db::query::create_tables::create_tables_stmt; - use rain_orderbook_common::local_db::query::insert_db_metadata::insert_db_metadata_stmt; - use rain_orderbook_common::local_db::query::{ + use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; + use raindex_common::local_db::query::clear_tables::clear_tables_stmt; + use raindex_common::local_db::query::create_tables::create_tables_stmt; + use raindex_common::local_db::query::insert_db_metadata::insert_db_metadata_stmt; + use raindex_common::local_db::query::{ FromDbJson, LocalDbQueryError, LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }; - use rain_orderbook_common::local_db::OrderbookIdentifier; + use raindex_common::local_db::RaindexIdentifier; const TEST_BLOCK_NUMBER_THRESHOLD: u32 = 10_000; @@ -73,7 +73,7 @@ mod tests { } fn with_views(self) -> Self { - rain_orderbook_common::local_db::query::create_views::create_views_batch() + raindex_common::local_db::query::create_views::create_views_batch() .statements() .iter() .fold(self, |db, stmt| db.with_text(stmt, "ok")) @@ -111,8 +111,8 @@ mod tests { } } - fn sample_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(1, Address::ZERO) + fn sample_ob_id() -> RaindexIdentifier { + RaindexIdentifier::new(1, Address::ZERO) } #[tokio::test] @@ -125,7 +125,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -160,7 +160,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -171,7 +171,7 @@ mod tests { let calls = db.calls(); let expected_views: Vec = - rain_orderbook_common::local_db::query::create_views::create_views_batch() + raindex_common::local_db::query::create_views::create_views_batch() .statements() .iter() .map(|s| s.sql().to_string()) @@ -194,7 +194,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -233,7 +233,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: 0, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -270,7 +270,7 @@ mod tests { .with_views(); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: 0, block_number_threshold: 1, diff --git a/crates/cli/src/commands/local_db/pipeline/runner/environment.rs b/crates/cli/src/commands/local_db/pipeline/runner/environment.rs index 57e8ab1f0b..a5485e6bed 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/environment.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/environment.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::local_db::pipeline::{ +use raindex_common::local_db::pipeline::{ adapters::{ apply::DefaultApplyPipeline, events::DefaultEventsPipeline, tokens::DefaultTokensPipeline, window::DefaultWindowPipeline, @@ -33,14 +33,14 @@ pub fn default_environment( default_dump_downloader(), Arc::new(move |target: &RunnerTarget| { let events = DefaultEventsPipeline::with_hyperrpc( - target.inputs.ob_id.chain_id, + target.inputs.raindex_id.chain_id, hypersync_token.clone(), )?; let tokens = DefaultTokensPipeline::new(target.inputs.metadata_rpcs.clone())?; let status = ProducerStatusBus::new( debug_status, - target.orderbook_key.clone(), - target.inputs.ob_id.clone(), + target.raindex_key.clone(), + target.inputs.raindex_id.clone(), ); Ok(EnginePipelines::new( @@ -59,21 +59,21 @@ pub fn default_environment( mod tests { use super::*; use alloy::primitives::address; - use rain_orderbook_common::local_db::fetch::FetchConfig; - use rain_orderbook_common::local_db::pipeline::engine::SyncInputs; - use rain_orderbook_common::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; - use rain_orderbook_common::local_db::{LocalDbError, OrderbookIdentifier}; - use rain_orderbook_common::rpc_client::RpcClientError; + use raindex_common::local_db::fetch::FetchConfig; + use raindex_common::local_db::pipeline::engine::SyncInputs; + use raindex_common::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; + use raindex_common::local_db::{LocalDbError, RaindexIdentifier}; + use raindex_common::rpc_client::RpcClientError; use url::Url; fn sample_target(chain_id: u32) -> RunnerTarget { let fetch = FetchConfig::new(1, 1, 1, 1, 0, 0).expect("fetch config"); RunnerTarget { - orderbook_key: "test-book".to_string(), + raindex_key: "test-book".to_string(), manifest_url: Url::parse("https://manifests.example/default.yaml").unwrap(), network_key: "anvil".to_string(), inputs: SyncInputs { - ob_id: OrderbookIdentifier::new( + raindex_id: RaindexIdentifier::new( chain_id, address!("00000000000000000000000000000000000000a1"), ), diff --git a/crates/cli/src/commands/local_db/pipeline/runner/export.rs b/crates/cli/src/commands/local_db/pipeline/runner/export.rs index 58cfa1a33d..2f62c98bdb 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/export.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/export.rs @@ -2,14 +2,14 @@ use crate::commands::local_db::executor::RusqliteExecutor; use alloy::primitives::hex::encode_prefixed; use flate2::write::GzEncoder; use flate2::Compression; -use rain_orderbook_common::local_db::export::{export_data_only, ExportError}; -use rain_orderbook_common::local_db::pipeline::runner::utils::RunnerTarget; -use rain_orderbook_common::local_db::pipeline::SyncOutcome; -use rain_orderbook_common::local_db::query::fetch_target_watermark::{ +use raindex_common::local_db::export::{export_data_only, ExportError}; +use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; +use raindex_common::local_db::pipeline::SyncOutcome; +use raindex_common::local_db::query::fetch_target_watermark::{ fetch_target_watermark_stmt, TargetWatermarkRow, }; -use rain_orderbook_common::local_db::query::LocalDbQueryExecutor; -use rain_orderbook_common::local_db::LocalDbError; +use raindex_common::local_db::query::LocalDbQueryExecutor; +use raindex_common::local_db::LocalDbError; use std::io::Write; use std::path::{Path, PathBuf}; use tokio::fs::create_dir_all; @@ -28,17 +28,17 @@ pub(super) async fn export_dump( outcome: &SyncOutcome, out_root: &Path, ) -> Result, LocalDbError> { - let dump_sql = match export_data_only(executor, &target.inputs.ob_id).await? { + let dump_sql = match export_data_only(executor, &target.inputs.raindex_id).await? { Some(sql) => sql, None => return Ok(None), }; - let chain_folder = out_root.join(target.inputs.ob_id.chain_id.to_string()); + let chain_folder = out_root.join(target.inputs.raindex_id.chain_id.to_string()); create_dir_all(&chain_folder).await?; let filename = format!( "{}-{}.sql.gz", - target.inputs.ob_id.chain_id, target.inputs.ob_id.orderbook_address + target.inputs.raindex_id.chain_id, target.inputs.raindex_id.raindex_address ); let dump_path = chain_folder.join(filename); @@ -51,12 +51,12 @@ pub(super) async fn export_dump( tokio::fs::write(&dump_path, compressed).await?; - let watermark_stmt = fetch_target_watermark_stmt(&target.inputs.ob_id); + let watermark_stmt = fetch_target_watermark_stmt(&target.inputs.raindex_id); let rows: Vec = executor.query_json(&watermark_stmt).await?; let row = rows.into_iter().next().ok_or_else(|| { LocalDbError::from(ExportError::MissingTargetWatermark { - chain_id: target.inputs.ob_id.chain_id, - orderbook_address: target.inputs.ob_id.orderbook_address, + chain_id: target.inputs.raindex_id.chain_id, + raindex_address: target.inputs.raindex_id.raindex_address, }) })?; @@ -73,9 +73,9 @@ mod tests { use super::*; use alloy::primitives::address; use flate2::read::GzDecoder; - use rain_orderbook_common::local_db::{ + use raindex_common::local_db::{ pipeline::{engine::SyncInputs, FinalityConfig, SyncConfig, WindowOverrides}, - FetchConfig, OrderbookIdentifier, + FetchConfig, RaindexIdentifier, }; use rusqlite::{params, Connection}; use std::io::{Cursor, Read}; @@ -86,22 +86,20 @@ mod tests { #[tokio::test] async fn export_dump_writes_gzip_and_reads_watermark_metadata() { let temp_dir = TempDir::new().unwrap(); - let db_path = temp_dir.path().join("orderbook.sqlite"); + let db_path = temp_dir.path().join("raindex.sqlite"); let conn = Connection::open(&db_path).expect("open sqlite db"); - conn.execute_batch( - rain_orderbook_common::local_db::query::create_tables::CREATE_TABLES_SQL, - ) - .expect("create tables"); + conn.execute_batch(raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL) + .expect("create tables"); let chain_id = 42161u32; - let orderbook_address = address!("0x0000000000000000000000000000000000000abc"); - let orderbook_str = encode_prefixed(orderbook_address); + let raindex_address = address!("0x0000000000000000000000000000000000000abc"); + let raindex_str = encode_prefixed(raindex_address); conn.execute( - "INSERT INTO raw_events (chain_id, orderbook_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10);", + "INSERT INTO raw_events (chain_id, raindex_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10);", params![ chain_id as i64, - orderbook_str.as_str(), + raindex_str.as_str(), "0xtesttx", 0i64, 1000i64, @@ -115,11 +113,11 @@ mod tests { .expect("insert raw_events row"); conn.execute( - "INSERT INTO target_watermarks (chain_id, orderbook_address, last_block, last_hash) VALUES (?1, ?2, ?3, ?4) - ON CONFLICT(chain_id, orderbook_address) DO UPDATE SET last_block = excluded.last_block, last_hash = excluded.last_hash, updated_at = 1_700_000_000_000;", + "INSERT INTO target_watermarks (chain_id, raindex_address, last_block, last_hash) VALUES (?1, ?2, ?3, ?4) + ON CONFLICT(chain_id, raindex_address) DO UPDATE SET last_block = excluded.last_block, last_hash = excluded.last_hash, updated_at = 1_700_000_000_000;", params![ chain_id as i64, - orderbook_str.as_str(), + raindex_str.as_str(), 1000i64, "0xdeadbeef", ], @@ -137,17 +135,17 @@ mod tests { window_overrides: WindowOverrides::default(), }; - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id, - orderbook_address, + raindex_address, }; let target = RunnerTarget { - orderbook_key: "test".to_string(), + raindex_key: "test".to_string(), manifest_url: Url::parse("https://example.com/manifest.yaml").unwrap(), network_key: "anvil".to_string(), inputs: SyncInputs { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), metadata_rpcs: Vec::new(), cfg: sync_config, dump_str: None, @@ -157,7 +155,7 @@ mod tests { }; let outcome = SyncOutcome { - ob_id, + raindex_id, start_block: 900, target_block: 1000, fetched_logs: 1, @@ -181,7 +179,7 @@ mod tests { ); let expected_file = format!( "{}-{}.sql.gz", - chain_id, target.inputs.ob_id.orderbook_address + chain_id, target.inputs.raindex_id.raindex_address ); assert_eq!( metadata @@ -207,16 +205,14 @@ mod tests { #[tokio::test] async fn export_dump_returns_none_when_no_rows_are_present() { let temp_dir = TempDir::new().unwrap(); - let db_path = temp_dir.path().join("orderbook.sqlite"); + let db_path = temp_dir.path().join("raindex.sqlite"); let conn = Connection::open(&db_path).expect("open sqlite db"); - conn.execute_batch( - rain_orderbook_common::local_db::query::create_tables::CREATE_TABLES_SQL, - ) - .expect("create tables"); + conn.execute_batch(raindex_common::local_db::query::create_tables::CREATE_TABLES_SQL) + .expect("create tables"); drop(conn); let chain_id = 10u32; - let orderbook_address = address!("0x0000000000000000000000000000000000000fff"); + let raindex_address = address!("0x0000000000000000000000000000000000000fff"); let executor = RusqliteExecutor::new(&db_path); let fetch = FetchConfig::new(1, 1, 1, 1, 0, 0).expect("fetch config"); let sync_config = SyncConfig { @@ -226,17 +222,17 @@ mod tests { window_overrides: WindowOverrides::default(), }; - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id, - orderbook_address, + raindex_address, }; let target = RunnerTarget { - orderbook_key: "empty".to_string(), + raindex_key: "empty".to_string(), manifest_url: Url::parse("https://example.com/empty.yaml").unwrap(), network_key: "anvil".to_string(), inputs: SyncInputs { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), metadata_rpcs: Vec::new(), cfg: sync_config, dump_str: None, @@ -246,7 +242,7 @@ mod tests { }; let outcome = SyncOutcome { - ob_id, + raindex_id, start_block: 0, target_block: 0, fetched_logs: 0, diff --git a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs index 093d61a99b..81db2ac580 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/manifest.rs @@ -1,10 +1,10 @@ use super::export::ExportMetadata; use alloy::primitives::{Address, Bytes}; -use rain_orderbook_app_settings::local_db_manifest::{LocalDbManifest, ManifestOrderbook}; -use rain_orderbook_app_settings::remote::manifest::ManifestMap; -use rain_orderbook_common::local_db::pipeline::runner::utils::RunnerTarget; -use rain_orderbook_common::local_db::pipeline::runner::TargetSuccess; -use rain_orderbook_common::local_db::{LocalDbError, OrderbookIdentifier}; +use raindex_app_settings::local_db_manifest::{LocalDbManifest, ManifestRaindex}; +use raindex_app_settings::remote::manifest::ManifestMap; +use raindex_common::local_db::pipeline::runner::utils::RunnerTarget; +use raindex_common::local_db::pipeline::runner::TargetSuccess; +use raindex_common::local_db::{LocalDbError, RaindexIdentifier}; use std::collections::HashMap; use std::path::Path; use std::str::FromStr; @@ -16,33 +16,37 @@ use url::Url; /// targets keep their last known manifest entry when available. pub fn build_manifest( successes: &[TargetSuccess], - exports: &HashMap>, - target_lookup: &HashMap, + exports: &HashMap>, + target_lookup: &HashMap, release_base_url: &Url, previous_manifests: &ManifestMap, ) -> Result { - let mut per_network: HashMap)> = HashMap::new(); + let mut per_network: HashMap)> = HashMap::new(); // First, record the latest successful exports. for success in successes { - let ob_id = &success.outcome.ob_id; - let export = match exports.get(ob_id).and_then(|export| export.as_ref()) { + let raindex_id = &success.outcome.raindex_id; + let export = match exports.get(raindex_id).and_then(|export| export.as_ref()) { Some(export) => export, None => continue, }; let runner_target = target_lookup - .get(ob_id) + .get(raindex_id) .ok_or_else(|| LocalDbError::MissingRunnerTarget { - chain_id: ob_id.chain_id, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id, + raindex_address: raindex_id.raindex_address, })?; - let dump_url = build_dump_url(release_base_url, ob_id.chain_id, ob_id.orderbook_address)?; + let dump_url = build_dump_url( + release_base_url, + raindex_id.chain_id, + raindex_id.raindex_address, + )?; let end_block_hash = Bytes::from_str(export.end_block_hash.as_str())?; - let manifest_orderbook = ManifestOrderbook { - address: ob_id.orderbook_address, + let manifest_raindex = ManifestRaindex { + address: raindex_id.raindex_address, dump_url, end_block: export.end_block, end_block_hash, @@ -52,21 +56,21 @@ pub fn build_manifest( push_entry( &mut per_network, runner_target.network_key.clone(), - ob_id.chain_id, - manifest_orderbook, + raindex_id.chain_id, + manifest_raindex, )?; } // Then, carry forward any existing manifest entries for targets that did // not produce a new dump in this run. - for (ob_id, runner_target) in target_lookup { + for (raindex_id, runner_target) in target_lookup { let already_recorded = per_network .get(&runner_target.network_key) - .is_some_and(|(_, orderbooks)| { - orderbooks + .is_some_and(|(_, raindexes)| { + raindexes .iter() - .any(|orderbook| orderbook.address == ob_id.orderbook_address) + .any(|raindex| raindex.address == raindex_id.raindex_address) }); if already_recorded { continue; @@ -74,15 +78,15 @@ pub fn build_manifest( let previous_entry = previous_manifests .get(&runner_target.manifest_url) - .and_then(|manifest| manifest.find(ob_id.chain_id, ob_id.orderbook_address)) + .and_then(|manifest| manifest.find(raindex_id.chain_id, raindex_id.raindex_address)) .cloned(); - if let Some(orderbook) = previous_entry { + if let Some(raindex) = previous_entry { push_entry( &mut per_network, runner_target.network_key.clone(), - ob_id.chain_id, - orderbook, + raindex_id.chain_id, + raindex, )?; } } @@ -92,11 +96,11 @@ pub fn build_manifest( network_keys.sort(); for key in network_keys { - if let Some((chain_id, mut orderbooks)) = per_network.remove(&key) { - orderbooks.sort_by(|a, b| a.address.cmp(&b.address)); + if let Some((chain_id, mut raindexes)) = per_network.remove(&key) { + raindexes.sort_by(|a, b| a.address.cmp(&b.address)); manifest.add_network(&key, chain_id)?; - for orderbook in orderbooks { - manifest.push_orderbook(&key, orderbook)?; + for raindex in raindexes { + manifest.push_raindex(&key, raindex)?; } } } @@ -105,10 +109,10 @@ pub fn build_manifest( } fn push_entry( - per_network: &mut HashMap)>, + per_network: &mut HashMap)>, network_key: String, chain_id: u32, - orderbook: ManifestOrderbook, + raindex: ManifestRaindex, ) -> Result<(), LocalDbError> { let entry = per_network .entry(network_key.clone()) @@ -120,17 +124,17 @@ fn push_entry( found: chain_id, }); } - entry.1.push(orderbook); + entry.1.push(raindex); Ok(()) } fn build_dump_url( base_url: &Url, chain_id: u32, - orderbook_address: Address, + raindex_address: Address, ) -> Result { let base = base_url.as_str().trim_end_matches('/'); - let address_str = orderbook_address.to_string(); + let address_str = raindex_address.to_string(); let url_str = format!("{}/{}-{}.sql.gz", base, chain_id, address_str); Url::parse(&url_str).map_err(|source| LocalDbError::DumpUrlConstructionFailed { url: url_str, @@ -156,27 +160,27 @@ mod tests { use super::*; use crate::commands::local_db::pipeline::runner::export::ExportMetadata; use alloy::primitives::address; - use rain_orderbook_app_settings::local_db_manifest::{ - LocalDbManifest, ManifestNetwork, ManifestOrderbook, DB_SCHEMA_VERSION, MANIFEST_VERSION, + use raindex_app_settings::local_db_manifest::{ + LocalDbManifest, ManifestNetwork, ManifestRaindex, DB_SCHEMA_VERSION, MANIFEST_VERSION, }; - use rain_orderbook_common::local_db::pipeline::engine::SyncInputs; - use rain_orderbook_common::local_db::pipeline::{ + use raindex_common::local_db::pipeline::engine::SyncInputs; + use raindex_common::local_db::pipeline::{ FinalityConfig, SyncConfig, SyncOutcome, WindowOverrides, }; - use rain_orderbook_common::local_db::{FetchConfig, OrderbookIdentifier}; + use raindex_common::local_db::{FetchConfig, RaindexIdentifier}; use std::collections::HashMap; use tempfile::TempDir; fn sample_runner_target(network_key: &str, chain_id: u32, address: Address) -> RunnerTarget { let fetch = FetchConfig::new(10, 5, 5, 1, 0, 0).unwrap(); RunnerTarget { - orderbook_key: format!("{}-{}", network_key, address), + raindex_key: format!("{}-{}", network_key, address), manifest_url: Url::parse("https://example.com/manifest.yaml").unwrap(), network_key: network_key.to_string(), inputs: SyncInputs { - ob_id: OrderbookIdentifier { + raindex_id: RaindexIdentifier { chain_id, - orderbook_address: address, + raindex_address: address, }, metadata_rpcs: Vec::new(), cfg: SyncConfig { @@ -193,13 +197,13 @@ mod tests { } fn sample_success( - target: &OrderbookIdentifier, + target: &RaindexIdentifier, dump_suffix: &str, ) -> (TargetSuccess, ExportMetadata) { ( TargetSuccess { outcome: SyncOutcome { - ob_id: target.clone(), + raindex_id: target.clone(), start_block: 0, target_block: 1234, fetched_logs: 10, @@ -217,22 +221,22 @@ mod tests { #[test] fn build_manifest_skips_missing_exported_dump() { - let target_included = OrderbookIdentifier { + let target_included = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; - let target_skipped = OrderbookIdentifier { + let target_skipped = RaindexIdentifier { chain_id: 10, - orderbook_address: address!("0x0000000000000000000000000000000000000bb2"), + raindex_address: address!("0x0000000000000000000000000000000000000bb2"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( target_included.clone(), sample_runner_target( "arbitrum", target_included.chain_id, - target_included.orderbook_address, + target_included.raindex_address, ), ); lookup.insert( @@ -240,7 +244,7 @@ mod tests { sample_runner_target( "optimism", target_skipped.chain_id, - target_skipped.orderbook_address, + target_skipped.raindex_address, ), ); @@ -259,38 +263,38 @@ mod tests { assert!( !manifest.networks.contains_key("optimism"), - "orderbook without dump should be ignored" + "raindex without dump should be ignored" ); let arbitrum = manifest .networks .get("arbitrum") .expect("network with dump should exist"); - assert_eq!(arbitrum.orderbooks.len(), 1); + assert_eq!(arbitrum.raindexes.len(), 1); assert_eq!( - arbitrum.orderbooks[0].address, - target_included.orderbook_address + arbitrum.raindexes[0].address, + target_included.raindex_address ); } #[test] fn build_manifest_happy_path_multiple_networks() { - let target_a = OrderbookIdentifier { + let target_a = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000Aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000Aa1"), }; - let target_b = OrderbookIdentifier { + let target_b = RaindexIdentifier { chain_id: 10, - orderbook_address: address!("0x0000000000000000000000000000000000000Bb2"), + raindex_address: address!("0x0000000000000000000000000000000000000Bb2"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( target_a.clone(), - sample_runner_target("anvil", target_a.chain_id, target_a.orderbook_address), + sample_runner_target("anvil", target_a.chain_id, target_a.raindex_address), ); lookup.insert( target_b.clone(), - sample_runner_target("optimism", target_b.chain_id, target_b.orderbook_address), + sample_runner_target("optimism", target_b.chain_id, target_b.raindex_address), ); let (success_a, export_a) = sample_success(&target_a, "dump-a.sql.gz"); @@ -305,47 +309,47 @@ mod tests { .expect("manifest build succeeds"); assert_eq!(manifest.manifest_version, 1); - assert_eq!(manifest.db_schema_version, 2); + assert_eq!(manifest.db_schema_version, 3); assert_eq!(manifest.networks.len(), 2); let anvil = manifest.networks.get("anvil").expect("anvil network"); assert_eq!(anvil.chain_id, 42161); - assert_eq!(anvil.orderbooks.len(), 1); + assert_eq!(anvil.raindexes.len(), 1); let expected_anvil = format!( "https://releases.example.com/{}-{}.sql.gz", - target_a.chain_id, target_a.orderbook_address + target_a.chain_id, target_a.raindex_address ); - assert_eq!(anvil.orderbooks[0].dump_url.as_str(), expected_anvil); + assert_eq!(anvil.raindexes[0].dump_url.as_str(), expected_anvil); let optimism = manifest.networks.get("optimism").expect("optimism network"); assert_eq!(optimism.chain_id, 10); - assert_eq!(optimism.orderbooks.len(), 1); + assert_eq!(optimism.raindexes.len(), 1); let expected_optimism = format!( "https://releases.example.com/{}-{}.sql.gz", - target_b.chain_id, target_b.orderbook_address + target_b.chain_id, target_b.raindex_address ); - assert_eq!(optimism.orderbooks[0].dump_url.as_str(), expected_optimism); + assert_eq!(optimism.raindexes[0].dump_url.as_str(), expected_optimism); } #[test] fn build_manifest_errors_on_chain_id_mismatch() { - let target_a = OrderbookIdentifier { + let target_a = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000cc1"), + raindex_address: address!("0x0000000000000000000000000000000000000cc1"), }; - let target_b = OrderbookIdentifier { + let target_b = RaindexIdentifier { chain_id: 10, - orderbook_address: address!("0x0000000000000000000000000000000000000cc2"), + raindex_address: address!("0x0000000000000000000000000000000000000cc2"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( target_a.clone(), - sample_runner_target("shared", target_a.chain_id, target_a.orderbook_address), + sample_runner_target("shared", target_a.chain_id, target_a.raindex_address), ); lookup.insert( target_b.clone(), - sample_runner_target("shared", target_b.chain_id, target_b.orderbook_address), + sample_runner_target("shared", target_b.chain_id, target_b.raindex_address), ); let (success_a, export_a) = sample_success(&target_a, "dump-a.sql.gz"); @@ -374,24 +378,24 @@ mod tests { } #[test] - fn build_manifest_sorts_orderbooks_within_network() { - let target_a = OrderbookIdentifier { + fn build_manifest_sorts_raindexes_within_network() { + let target_a = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000aa2"), + raindex_address: address!("0x0000000000000000000000000000000000000aa2"), }; - let target_b = OrderbookIdentifier { + let target_b = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( target_a.clone(), - sample_runner_target("anvil", target_a.chain_id, target_a.orderbook_address), + sample_runner_target("anvil", target_a.chain_id, target_a.raindex_address), ); lookup.insert( target_b.clone(), - sample_runner_target("anvil", target_b.chain_id, target_b.orderbook_address), + sample_runner_target("anvil", target_b.chain_id, target_b.raindex_address), ); // Intentionally provide outcomes out of order to ensure sorting occurs. @@ -406,7 +410,11 @@ mod tests { let manifest = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) .expect("manifest build succeeds"); let anvil = manifest.networks.get("anvil").expect("anvil network"); - let addresses: Vec<_> = anvil.orderbooks.iter().map(|ob| ob.address).collect(); + let addresses: Vec<_> = anvil + .raindexes + .iter() + .map(|raindex_entry| raindex_entry.address) + .collect(); assert_eq!( addresses, vec![ @@ -418,15 +426,15 @@ mod tests { #[test] fn build_manifest_errors_on_missing_target() { - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; - let lookup: HashMap = HashMap::new(); - let (success, export) = sample_success(&ob_id, "dump.sql.gz"); + let lookup: HashMap = HashMap::new(); + let (success, export) = sample_success(&raindex_id, "dump.sql.gz"); let successes = vec![success]; let mut exports = HashMap::new(); - exports.insert(ob_id.clone(), Some(export)); + exports.insert(raindex_id.clone(), Some(export)); let base_url = Url::parse("https://releases.example.com").unwrap(); @@ -435,10 +443,10 @@ mod tests { match err { LocalDbError::MissingRunnerTarget { chain_id, - orderbook_address, + raindex_address, } => { - assert_eq!(chain_id, ob_id.chain_id); - assert_eq!(orderbook_address, ob_id.orderbook_address); + assert_eq!(chain_id, raindex_id.chain_id); + assert_eq!(raindex_address, raindex_id.raindex_address); } other => panic!("unexpected error variant: {other:?}"), } @@ -446,22 +454,22 @@ mod tests { #[test] fn build_manifest_errors_on_invalid_end_block_hash() { - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000dd1"), + raindex_address: address!("0x0000000000000000000000000000000000000dd1"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( - ob_id.clone(), - sample_runner_target("arbitrum", ob_id.chain_id, ob_id.orderbook_address), + raindex_id.clone(), + sample_runner_target("arbitrum", raindex_id.chain_id, raindex_id.raindex_address), ); - let (success, mut export) = sample_success(&ob_id, "dump.sql.gz"); + let (success, mut export) = sample_success(&raindex_id, "dump.sql.gz"); export.end_block_hash = "not-a-hex-string".to_string(); let successes = vec![success]; let mut exports = HashMap::new(); - exports.insert(ob_id.clone(), Some(export)); + exports.insert(raindex_id.clone(), Some(export)); let base_url = Url::parse("https://releases.example.com").unwrap(); let err = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) @@ -487,28 +495,28 @@ mod tests { assert!(manifest.networks.is_empty()); assert_eq!(manifest.manifest_version, 1); - assert_eq!(manifest.db_schema_version, 2); + assert_eq!(manifest.db_schema_version, 3); } #[test] fn build_manifest_overlays_successes_and_reuses_previous_entries() { - let target_a = OrderbookIdentifier { + let target_a = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; - let target_b = OrderbookIdentifier { + let target_b = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000bb2"), + raindex_address: address!("0x0000000000000000000000000000000000000bb2"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( target_a.clone(), - sample_runner_target("anvil", target_a.chain_id, target_a.orderbook_address), + sample_runner_target("anvil", target_a.chain_id, target_a.raindex_address), ); lookup.insert( target_b.clone(), - sample_runner_target("anvil", target_b.chain_id, target_b.orderbook_address), + sample_runner_target("anvil", target_b.chain_id, target_b.raindex_address), ); let (success_a, export_a) = sample_success(&target_a, "dump-a.sql.gz"); @@ -516,7 +524,7 @@ mod tests { let mut exports = HashMap::new(); exports.insert(target_a.clone(), Some(export_a)); - // Previous manifest contains both orderbooks; only A gets a fresh export. + // Previous manifest contains both raindexes; only A gets a fresh export. let previous_manifest = LocalDbManifest { manifest_version: MANIFEST_VERSION, db_schema_version: DB_SCHEMA_VERSION, @@ -524,16 +532,16 @@ mod tests { "anvil".to_string(), ManifestNetwork { chain_id: target_a.chain_id, - orderbooks: vec![ - ManifestOrderbook { - address: target_a.orderbook_address, + raindexes: vec![ + ManifestRaindex { + address: target_a.raindex_address, dump_url: Url::parse("https://old.example/a.sql.gz").unwrap(), end_block: 100, end_block_hash: Bytes::from_str("0x0aaa").unwrap(), end_block_time_ms: 1_700_000_000, }, - ManifestOrderbook { - address: target_b.orderbook_address, + ManifestRaindex { + address: target_b.raindex_address, dump_url: Url::parse("https://old.example/b.sql.gz").unwrap(), end_block: 200, end_block_hash: Bytes::from_str("0x0bbb").unwrap(), @@ -551,40 +559,40 @@ mod tests { .expect("manifest build succeeds"); let anvil = manifest.networks.get("anvil").expect("anvil network"); - assert_eq!(anvil.orderbooks.len(), 2); + assert_eq!(anvil.raindexes.len(), 2); // New dump for target A should use the release base URL, while target B // should keep its previous dump URL. assert_eq!( - anvil.orderbooks[0].dump_url.as_str(), + anvil.raindexes[0].dump_url.as_str(), format!( "https://releases.example.com/{}-{}.sql.gz", - target_a.chain_id, target_a.orderbook_address + target_a.chain_id, target_a.raindex_address ) ); assert_eq!( - anvil.orderbooks[1].dump_url.as_str(), + anvil.raindexes[1].dump_url.as_str(), "https://old.example/b.sql.gz" ); } #[test] fn build_manifest_orders_networks_alphabetically() { - let target_devnet = OrderbookIdentifier { + let target_devnet = RaindexIdentifier { chain_id: 1, - orderbook_address: address!("0x0000000000000000000000000000000000000aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; - let target_testnet = OrderbookIdentifier { + let target_testnet = RaindexIdentifier { chain_id: 10, - orderbook_address: address!("0x0000000000000000000000000000000000000bb1"), + raindex_address: address!("0x0000000000000000000000000000000000000bb1"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( target_devnet.clone(), sample_runner_target( "devnet", target_devnet.chain_id, - target_devnet.orderbook_address, + target_devnet.raindex_address, ), ); lookup.insert( @@ -592,7 +600,7 @@ mod tests { sample_runner_target( "testnet", target_testnet.chain_id, - target_testnet.orderbook_address, + target_testnet.raindex_address, ), ); @@ -635,19 +643,19 @@ mod tests { #[tokio::test] async fn write_manifest_to_path_writes_yaml() { - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, - orderbook_address: address!("0x0000000000000000000000000000000000000aa1"), + raindex_address: address!("0x0000000000000000000000000000000000000aa1"), }; - let mut lookup: HashMap = HashMap::new(); + let mut lookup: HashMap = HashMap::new(); lookup.insert( - ob_id.clone(), - sample_runner_target("anvil", ob_id.chain_id, ob_id.orderbook_address), + raindex_id.clone(), + sample_runner_target("anvil", raindex_id.chain_id, raindex_id.raindex_address), ); - let (success, export) = sample_success(&ob_id, "dump.sql.gz"); + let (success, export) = sample_success(&raindex_id, "dump.sql.gz"); let successes = vec![success]; let mut exports = HashMap::new(); - exports.insert(ob_id.clone(), Some(export)); + exports.insert(raindex_id.clone(), Some(export)); let base_url = Url::parse("https://releases.example.com").unwrap(); let manifest = build_manifest(&successes, &exports, &lookup, &base_url, &HashMap::new()) diff --git a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs index 21f74857c7..eb80481b43 100644 --- a/crates/cli/src/commands/local_db/pipeline/runner/mod.rs +++ b/crates/cli/src/commands/local_db/pipeline/runner/mod.rs @@ -12,15 +12,15 @@ use environment::default_environment; use export::export_dump; pub use export::ExportMetadata; use manifest::{build_manifest, write_manifest_to_path}; -use rain_orderbook_app_settings::local_db_manifest::ManifestOrderbook; -use rain_orderbook_common::local_db::pipeline::adapters::apply::ApplyPipeline; -use rain_orderbook_common::local_db::pipeline::runner::{ +use raindex_app_settings::local_db_manifest::ManifestRaindex; +use raindex_common::local_db::pipeline::adapters::apply::ApplyPipeline; +use raindex_common::local_db::pipeline::runner::{ environment::RunnerEnvironment, remotes::lookup_manifest_entry, utils::{build_runner_targets, parse_runner_settings, ParsedRunnerSettings, RunnerTarget}, RunReport, TargetFailure, TargetStage, TargetSuccess, }; -use rain_orderbook_common::local_db::pipeline::{ +use raindex_common::local_db::pipeline::{ adapters::{ apply::DefaultApplyPipeline, bootstrap::BootstrapPipeline, events::DefaultEventsPipeline, tokens::DefaultTokensPipeline, window::DefaultWindowPipeline, @@ -28,7 +28,7 @@ use rain_orderbook_common::local_db::pipeline::{ engine::SyncInputs, EventsPipeline, StatusBus, TokensPipeline, WindowPipeline, }; -use rain_orderbook_common::local_db::{LocalDbError, OrderbookIdentifier}; +use raindex_common::local_db::{LocalDbError, RaindexIdentifier}; use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -39,7 +39,7 @@ use url::Url; pub struct ProducerRunner { settings: ParsedRunnerSettings, targets: Vec, - target_lookup: HashMap, + target_lookup: HashMap, out_root: PathBuf, release_base_url: Url, manifest_output_path: PathBuf, @@ -62,11 +62,11 @@ where environment: RunnerEnvironment, ) -> Result { let settings = parse_runner_settings(&settings_yaml)?; - let targets = build_runner_targets(&settings.orderbooks, &settings.syncs)?; + let targets = build_runner_targets(&settings.raindexes, &settings.syncs)?; let mut target_lookup = HashMap::with_capacity(targets.len()); for target in &targets { - target_lookup.insert(target.inputs.ob_id.clone(), target.clone()); + target_lookup.insert(target.inputs.raindex_id.clone(), target.clone()); } let manifest_output_path = out_root.join("manifest.yaml"); @@ -85,7 +85,7 @@ where pub async fn run(&self) -> Result { let manifest_map = match self .environment - .fetch_manifests(&self.settings.orderbooks) + .fetch_manifests(&self.settings.raindexes) .await { Ok(map) => Arc::new(map), @@ -93,8 +93,8 @@ where let report = RunReport { successes: Vec::new(), failures: vec![TargetFailure { - ob_id: OrderbookIdentifier::new(0, Address::ZERO), - orderbook_key: None, + raindex_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_key: None, stage: TargetStage::ManifestFetch, error, }], @@ -117,7 +117,7 @@ where let environment = environment.clone(); tasks.spawn_local(async move { let manifest_entry = lookup_manifest_entry(manifest_map.as_ref(), &target); - run_orderbook_job::( + run_raindex_job::( target, manifest_entry, environment, @@ -129,21 +129,21 @@ where let mut successes = Vec::new(); let mut failures = Vec::new(); - let mut exports: HashMap> = + let mut exports: HashMap> = HashMap::new(); while let Some(result) = tasks.join_next().await { match result { Ok(Ok((success, export))) => { - exports.insert(success.outcome.ob_id.clone(), export); + exports.insert(success.outcome.raindex_id.clone(), export); successes.push(success); } Ok(Err(failure)) => { error!( - address = ?failure.ob_id.orderbook_address, + address = ?failure.raindex_id.raindex_address, stage = ?failure.stage, error = %failure.error, "producer job failed (chain_id={:?})", - failure.ob_id.chain_id, + failure.raindex_id.chain_id, ); failures.push(failure); } @@ -154,8 +154,8 @@ where "producer job panicked or was cancelled before completion" ); failures.push(TargetFailure { - ob_id: OrderbookIdentifier::new(0, Address::ZERO), - orderbook_key: None, + raindex_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_key: None, stage: TargetStage::EngineRun, error, }); @@ -165,7 +165,7 @@ where Ok::< ( RunReport, - HashMap>, + HashMap>, ), LocalDbError, >(( @@ -228,13 +228,13 @@ impl pub struct ProducerRunReport { pub successes: Vec, pub failures: Vec, - pub exports: HashMap>, + pub exports: HashMap>, } impl ProducerRunReport { fn from_parts( report: RunReport, - exports: HashMap>, + exports: HashMap>, ) -> Self { Self { successes: report.successes, @@ -251,14 +251,14 @@ impl ProducerRunReport { &self.failures } - pub fn export_for(&self, ob_id: &OrderbookIdentifier) -> Option<&ExportMetadata> { - self.exports.get(ob_id)?.as_ref() + pub fn export_for(&self, raindex_id: &RaindexIdentifier) -> Option<&ExportMetadata> { + self.exports.get(raindex_id)?.as_ref() } } -async fn run_orderbook_job( +async fn run_raindex_job( target: RunnerTarget, - manifest_entry: Option, + manifest_entry: Option, environment: RunnerEnvironment, out_root: PathBuf, ) -> Result<(TargetSuccess, Option), TargetFailure> @@ -271,17 +271,17 @@ where S: StatusBus + 'static, { let RunnerTarget { - orderbook_key, + raindex_key, manifest_url, network_key, inputs, } = target; - let ob_id = inputs.ob_id.clone(); - let ob_key_for_failure = orderbook_key.clone(); + let raindex_id = inputs.raindex_id.clone(); + let ob_key_for_failure = raindex_key.clone(); let mk_failure = move |stage: TargetStage, error: LocalDbError| TargetFailure { - ob_id: ob_id.clone(), - orderbook_key: Some(ob_key_for_failure.clone()), + raindex_id: raindex_id.clone(), + raindex_key: Some(ob_key_for_failure.clone()), stage, error, }; @@ -301,7 +301,7 @@ where }; let target = RunnerTarget { - orderbook_key, + raindex_key, manifest_url, network_key, inputs, @@ -328,9 +328,9 @@ where } fn db_path_for_target(out_root: &Path, target: &RunnerTarget) -> Result { - let chain_folder = out_root.join(target.inputs.ob_id.chain_id.to_string()); + let chain_folder = out_root.join(target.inputs.raindex_id.chain_id.to_string()); std::fs::create_dir_all(&chain_folder)?; - let filename = format!("{}.db", target.inputs.ob_id.orderbook_address); + let filename = format!("{}.db", target.inputs.raindex_id.raindex_address); Ok(chain_folder.join(filename)) } @@ -347,26 +347,24 @@ mod tests { use alloy::primitives::{address, hex::encode_prefixed, Address, Bytes, B256}; use async_trait::async_trait; use flate2::read::GzDecoder; - use rain_orderbook_app_settings::local_db_manifest::{ - LocalDbManifest, ManifestNetwork, ManifestOrderbook, DB_SCHEMA_VERSION, MANIFEST_VERSION, + use raindex_app_settings::local_db_manifest::{ + LocalDbManifest, ManifestNetwork, ManifestRaindex, DB_SCHEMA_VERSION, MANIFEST_VERSION, }; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::remote::manifest::ManifestMap; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_common::local_db::pipeline::adapters::apply::ApplyPipelineTargetInfo; - use rain_orderbook_common::local_db::pipeline::adapters::bootstrap::{ + use raindex_app_settings::raindex::RaindexCfg; + use raindex_app_settings::remote::manifest::ManifestMap; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_common::local_db::pipeline::adapters::apply::ApplyPipelineTargetInfo; + use raindex_common::local_db::pipeline::adapters::bootstrap::{ BootstrapConfig, BootstrapPipeline, BootstrapState, }; - use rain_orderbook_common::local_db::pipeline::runner::environment::{ + use raindex_common::local_db::pipeline::runner::environment::{ DumpFuture, EnginePipelines, ManifestFuture, }; - use rain_orderbook_common::local_db::pipeline::{ + use raindex_common::local_db::pipeline::{ EventsPipeline, StatusBus, SyncPhase, TokensPipeline, WindowPipeline, }; - use rain_orderbook_common::local_db::query::{ - LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, - }; - use rain_orderbook_common::local_db::{FetchConfig, LocalDbError}; + use raindex_common::local_db::query::{LocalDbQueryExecutor, SqlStatement, SqlStatementBatch}; + use raindex_common::local_db::{FetchConfig, LocalDbError}; use std::collections::HashMap; use std::fs::File; use std::io::Read; @@ -435,17 +433,17 @@ mod tests { batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS target_watermarks ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, last_block INTEGER NOT NULL DEFAULT 0, last_hash TEXT, updated_at INTEGER NOT NULL DEFAULT (CAST(strftime('%s', 'now') AS INTEGER) * 1000), - PRIMARY KEY (chain_id, orderbook_address) + PRIMARY KEY (chain_id, raindex_address) );", )); batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS raw_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -454,20 +452,20 @@ mod tests { topics TEXT NOT NULL, data TEXT NOT NULL, raw_json TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) );", )); batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS order_events ( chain_id INTEGER, - orderbook_address TEXT, + raindex_address TEXT, store_address TEXT );", )); batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS interpreter_store_sets ( chain_id INTEGER, - orderbook_address TEXT, + raindex_address TEXT, store_address TEXT );", )); @@ -494,7 +492,7 @@ mod tests { async fn inspect_state( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _ob_id: &RaindexIdentifier, ) -> Result where DB: LocalDbQueryExecutor + ?Sized, @@ -516,10 +514,10 @@ mod tests { Ok(()) } - async fn clear_orderbook_data( + async fn clear_raindex_data( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, ) -> Result<(), LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, @@ -538,14 +536,14 @@ mod tests { self.ensure_tables(db).await?; // Seed a raw event to force export_data_only to return Some, but skip watermark to trigger export failure. - let ob_id = &config.ob_id; - let orderbook_address = encode_prefixed(ob_id.orderbook_address); + let raindex_id = &config.raindex_id; + let raindex_address = encode_prefixed(raindex_id.raindex_address); let mut batch = SqlStatementBatch::new(); batch.add(SqlStatement::new(format!( - "INSERT INTO raw_events (chain_id, orderbook_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) \ + "INSERT INTO raw_events (chain_id, raindex_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) \ VALUES ({}, '{}', '0xseedtx', 0, {}, 1_700_000_000, '{}', '[]', '0x00', '{{}}') \ - ON CONFLICT(chain_id, orderbook_address, transaction_hash, log_index) DO NOTHING;", - ob_id.chain_id, orderbook_address, config.latest_block, orderbook_address + ON CONFLICT(chain_id, raindex_address, transaction_hash, log_index) DO NOTHING;", + raindex_id.chain_id, raindex_address, config.latest_block, raindex_address ))); db.execute_batch(&batch.ensure_transaction()).await?; @@ -590,17 +588,17 @@ mod tests { batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS target_watermarks ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, last_block INTEGER NOT NULL DEFAULT 0, last_hash TEXT, updated_at INTEGER NOT NULL DEFAULT (CAST(strftime('%s', 'now') AS INTEGER) * 1000), - PRIMARY KEY (chain_id, orderbook_address) + PRIMARY KEY (chain_id, raindex_address) );", )); batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS raw_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -609,20 +607,20 @@ mod tests { topics TEXT NOT NULL, data TEXT NOT NULL, raw_json TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) );", )); batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS order_events ( chain_id INTEGER, - orderbook_address TEXT, + raindex_address TEXT, store_address TEXT );", )); batch.add(SqlStatement::new( "CREATE TABLE IF NOT EXISTS interpreter_store_sets ( chain_id INTEGER, - orderbook_address TEXT, + raindex_address TEXT, store_address TEXT );", )); @@ -649,7 +647,7 @@ mod tests { async fn inspect_state( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _ob_id: &RaindexIdentifier, ) -> Result where DB: LocalDbQueryExecutor + ?Sized, @@ -671,10 +669,10 @@ mod tests { Ok(()) } - async fn clear_orderbook_data( + async fn clear_raindex_data( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, ) -> Result<(), LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, @@ -699,24 +697,24 @@ mod tests { self.ensure_tables(db).await?; if self.seed_export { - let ob_id = &config.ob_id; - let orderbook_address = encode_prefixed(ob_id.orderbook_address); + let raindex_id = &config.raindex_id; + let raindex_address = encode_prefixed(raindex_id.raindex_address); let mut batch = SqlStatementBatch::new(); batch.add(SqlStatement::new(format!( - "INSERT INTO raw_events (chain_id, orderbook_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) \ + "INSERT INTO raw_events (chain_id, raindex_address, transaction_hash, log_index, block_number, block_timestamp, address, topics, data, raw_json) \ VALUES ({}, '{}', '0xseedtx', 0, {}, 1_700_000_000, '{}', '[]', '0x00', '{{}}') \ - ON CONFLICT(chain_id, orderbook_address, transaction_hash, log_index) DO NOTHING;", - ob_id.chain_id, orderbook_address, config.latest_block, orderbook_address + ON CONFLICT(chain_id, raindex_address, transaction_hash, log_index) DO NOTHING;", + raindex_id.chain_id, raindex_address, config.latest_block, raindex_address ))); batch.add(SqlStatement::new(format!( - "INSERT INTO target_watermarks (chain_id, orderbook_address, last_block, last_hash, updated_at) \ + "INSERT INTO target_watermarks (chain_id, raindex_address, last_block, last_hash, updated_at) \ VALUES ({}, '{}', {}, '0xfeedface', 1_700_000_000_000) \ - ON CONFLICT(chain_id, orderbook_address) DO UPDATE \ + ON CONFLICT(chain_id, raindex_address) DO UPDATE \ SET last_block = excluded.last_block, \ last_hash = excluded.last_hash, \ updated_at = excluded.updated_at;", - ob_id.chain_id, orderbook_address, config.latest_block + raindex_id.chain_id, raindex_address, config.latest_block ))); db.execute_batch(&batch.ensure_transaction()).await?; @@ -757,8 +755,8 @@ mod tests { async fn compute( &self, _db: &DB, - _target: &OrderbookIdentifier, - _cfg: &rain_orderbook_common::local_db::pipeline::SyncConfig, + _target: &RaindexIdentifier, + _cfg: &raindex_common::local_db::pipeline::SyncConfig, _latest_block: u64, ) -> Result<(u64, u64), LocalDbError> where @@ -779,14 +777,13 @@ mod tests { Ok(self.latest_block) } - async fn fetch_orderbook( + async fn fetch_raindex( &self, - _orderbook_address: Address, + _raindex_address: Address, _from_block: u64, _to_block: u64, _cfg: &FetchConfig, - ) -> Result, LocalDbError> - { + ) -> Result, LocalDbError> { Ok(Vec::new()) } @@ -796,18 +793,17 @@ mod tests { _from_block: u64, _to_block: u64, _cfg: &FetchConfig, - ) -> Result, LocalDbError> - { + ) -> Result, LocalDbError> { Ok(Vec::new()) } fn decode( &self, - _logs: &[rain_orderbook_common::rpc_client::LogEntryResponse], + _logs: &[raindex_common::rpc_client::LogEntryResponse], ) -> Result< Vec< - rain_orderbook_common::local_db::decode::DecodedEventData< - rain_orderbook_common::local_db::decode::DecodedEvent, + raindex_common::local_db::decode::DecodedEventData< + raindex_common::local_db::decode::DecodedEvent, >, >, LocalDbError, @@ -828,10 +824,10 @@ mod tests { async fn load_existing( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _ob_id: &RaindexIdentifier, _token_addrs_lower: &[Address], ) -> Result< - Vec, + Vec, LocalDbError, > where @@ -844,7 +840,7 @@ mod tests { &self, _missing: Vec
, _cfg: &FetchConfig, - ) -> Result, LocalDbError> { + ) -> Result, LocalDbError> { Ok(Vec::new()) } } @@ -865,14 +861,14 @@ mod tests { fn build_batch( &self, _target_info: &ApplyPipelineTargetInfo, - _raw_logs: &[rain_orderbook_common::rpc_client::LogEntryResponse], - _decoded_events: &[rain_orderbook_common::local_db::decode::DecodedEventData< - rain_orderbook_common::local_db::decode::DecodedEvent, + _raw_logs: &[raindex_common::rpc_client::LogEntryResponse], + _decoded_events: &[raindex_common::local_db::decode::DecodedEventData< + raindex_common::local_db::decode::DecodedEvent, >], _existing_tokens: &[ - rain_orderbook_common::local_db::query::fetch_erc20_tokens_by_addresses::Erc20TokenRow + raindex_common::local_db::query::fetch_erc20_tokens_by_addresses::Erc20TokenRow ], - _tokens_to_upsert: &[(Address, rain_orderbook_common::erc20::TokenInfo)], + _tokens_to_upsert: &[(Address, raindex_common::erc20::TokenInfo)], ) -> Result { Ok(SqlStatementBatch::new()) } @@ -897,7 +893,7 @@ mod tests { async fn export_dump( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, _end_block: u64, ) -> Result<(), LocalDbError> where @@ -951,7 +947,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: ok: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -999,7 +995,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: ok: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -1040,7 +1036,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: panic: address: 0x00000000000000000000000000000000000000c3 network: anvil @@ -1075,7 +1071,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: ok: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -1111,7 +1107,7 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: +raindexes: ok: address: 0x00000000000000000000000000000000000000a1 network: anvil @@ -1129,10 +1125,10 @@ orderbooks: ) } - fn manifest_for_ok_orderbook() -> ManifestMap { + fn manifest_for_ok_raindex() -> ManifestMap { let url = Url::parse("https://manifests.example/a.yaml").unwrap(); let dump_url = Url::parse("https://dumps.example/ok.dump.sql").unwrap(); - let orderbook_address = address!("00000000000000000000000000000000000000a1"); + let raindex_address = address!("00000000000000000000000000000000000000a1"); let manifest = LocalDbManifest { manifest_version: MANIFEST_VERSION, db_schema_version: DB_SCHEMA_VERSION, @@ -1140,8 +1136,8 @@ orderbooks: "anvil".to_string(), ManifestNetwork { chain_id: 42161, - orderbooks: vec![ManifestOrderbook { - address: orderbook_address, + raindexes: vec![ManifestRaindex { + address: raindex_address, dump_url, end_block: 111, end_block_hash: Bytes::from_str("0xdead").unwrap(), @@ -1153,8 +1149,8 @@ orderbooks: HashMap::from([(url, manifest)]) } - fn manifest_for_two_ok_orderbooks() -> ManifestMap { - let mut map = manifest_for_ok_orderbook(); + fn manifest_for_two_ok_raindexes() -> ManifestMap { + let mut map = manifest_for_ok_raindex(); let second_url = Url::parse("https://manifests.example/d.yaml").unwrap(); let second_dump_url = Url::parse("https://dumps.example/ok-second.dump.sql").unwrap(); let second_address = address!("00000000000000000000000000000000000000d4"); @@ -1165,7 +1161,7 @@ orderbooks: "anvil".to_string(), ManifestNetwork { chain_id: 42161, - orderbooks: vec![ManifestOrderbook { + raindexes: vec![ManifestRaindex { address: second_address, dump_url: second_dump_url, end_block: 222, @@ -1220,7 +1216,7 @@ orderbooks: let telemetry_for_builder = telemetry.clone(); Arc::new(move |target: &RunnerTarget| { let behavior = behaviors - .get(&target.orderbook_key) + .get(&target.raindex_key) .copied() .unwrap_or(EngineBehavior::Success); let telemetry = telemetry_for_builder.clone(); @@ -1257,7 +1253,7 @@ orderbooks: let behaviors = Arc::new(behaviors); let manifest_fetcher = { let manifests = Arc::clone(&manifests); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let manifests = Arc::clone(&manifests); Box::pin(async move { Ok((*manifests).clone()) }) as ManifestFuture }) @@ -1286,7 +1282,7 @@ orderbooks: fn build_targets(yaml: &str) -> Vec { let parsed = parse_settings(yaml); - build_runner_targets(&parsed.orderbooks, &parsed.syncs).expect("targets") + build_runner_targets(&parsed.raindexes, &parsed.syncs).expect("targets") } #[test] @@ -1303,8 +1299,8 @@ orderbooks: ) .expect("runner to be constructed"); assert_eq!(runner.targets.len(), 3); - assert_eq!(runner.settings.orderbooks.len(), 3); - assert!(runner.settings.orderbooks.contains_key("ok")); + assert_eq!(runner.settings.raindexes.len(), 3); + assert!(runner.settings.raindexes.contains_key("ok")); } #[test] @@ -1338,7 +1334,7 @@ orderbooks: let mut behaviors = HashMap::new(); behaviors.insert("ok".to_string(), EngineBehavior::Success); behaviors.insert("fail".to_string(), EngineBehavior::Fail); - let (environment, telemetry) = build_environment(manifest_for_ok_orderbook(), behaviors); + let (environment, telemetry) = build_environment(manifest_for_ok_raindex(), behaviors); let temp_dir = TempDir::new().unwrap(); let release_base = Url::parse("https://releases.example.com").unwrap(); let runner = ProducerRunner::with_environment( @@ -1357,17 +1353,17 @@ orderbooks: let success = &report.successes[0]; assert_eq!(success.outcome.start_block, 0); assert_eq!( - success.outcome.ob_id.orderbook_address, + success.outcome.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 42161); + assert_eq!(failure.raindex_id.chain_id, 42161); assert_eq!( - failure.ob_id.orderbook_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000b2") ); - assert_eq!(failure.orderbook_key.as_deref(), Some("fail")); + assert_eq!(failure.raindex_key.as_deref(), Some("fail")); assert!(matches!(failure.error, LocalDbError::CustomError(_))); let dumps: Vec> = telemetry.bootstrap_dumps.lock().unwrap().clone(); @@ -1403,8 +1399,8 @@ orderbooks: assert_eq!(report.successes.len(), 0); assert_eq!(report.failures.len(), 1); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 0); - assert!(failure.orderbook_key.is_none()); + assert_eq!(failure.raindex_id.chain_id, 0); + assert!(failure.raindex_key.is_none()); assert!(matches!(failure.error, LocalDbError::TaskJoin(_))); } @@ -1415,7 +1411,7 @@ orderbooks: behaviors.insert("ok".to_string(), EngineBehavior::Success); behaviors.insert("fail".to_string(), EngineBehavior::Fail); behaviors.insert("panic".to_string(), EngineBehavior::Panic); - let (environment, telemetry) = build_environment(manifest_for_ok_orderbook(), behaviors); + let (environment, telemetry) = build_environment(manifest_for_ok_raindex(), behaviors); let temp_dir = TempDir::new().unwrap(); let release_base = Url::parse("https://releases.example.com").unwrap(); let runner = ProducerRunner::with_environment( @@ -1434,7 +1430,7 @@ orderbooks: let success_addresses: Vec
= report .successes .iter() - .map(|outcome| outcome.outcome.ob_id.orderbook_address) + .map(|outcome| outcome.outcome.raindex_id.raindex_address) .collect(); assert_eq!( success_addresses, @@ -1444,7 +1440,10 @@ orderbooks: let mut custom_failure = None; let mut join_failure = None; for failure in &report.failures { - match (failure.ob_id.chain_id, failure.ob_id.orderbook_address) { + match ( + failure.raindex_id.chain_id, + failure.raindex_id.raindex_address, + ) { (42161, addr) if addr == address!("00000000000000000000000000000000000000b2") => { custom_failure = Some(failure); } @@ -1470,7 +1469,7 @@ orderbooks: behaviors.insert("ok".to_string(), EngineBehavior::SuccessWithExport); behaviors.insert("ok-second".to_string(), EngineBehavior::Fail); let (environment, _telemetry) = - build_environment(manifest_for_two_ok_orderbooks(), behaviors); + build_environment(manifest_for_two_ok_raindexes(), behaviors); let temp_dir = TempDir::new().unwrap(); let release_base = Url::parse("https://releases.example.com").unwrap(); let runner = ProducerRunner::with_environment( @@ -1513,7 +1512,7 @@ orderbooks: let yaml = settings_yaml_ok_only(); let telemetry = Telemetry::default(); let manifest_fetcher = Arc::new( - |_orderbooks: &HashMap| -> ManifestFuture { + |_raindexes: &HashMap| -> ManifestFuture { Box::pin(async { Err(LocalDbError::CustomError( "manifest fetch failure".to_string(), @@ -1550,12 +1549,12 @@ orderbooks: #[tokio::test] async fn run_records_download_failure() { let yaml = settings_yaml_ok_only(); - let manifest_map = manifest_for_ok_orderbook(); + let manifest_map = manifest_for_ok_raindex(); let telemetry = Telemetry::default(); let manifests = Arc::new(manifest_map); let manifest_fetcher = { let manifests = Arc::clone(&manifests); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let manifests = Arc::clone(&manifests); Box::pin(async move { Ok((*manifests).clone()) }) as ManifestFuture }) @@ -1589,12 +1588,12 @@ orderbooks: assert!(report.successes.is_empty()); assert_eq!(report.failures.len(), 1); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 42161); + assert_eq!(failure.raindex_id.chain_id, 42161); assert_eq!( - failure.ob_id.orderbook_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); - assert_eq!(failure.orderbook_key.as_deref(), Some("ok")); + assert_eq!(failure.raindex_key.as_deref(), Some("ok")); assert!(matches!( &failure.error, LocalDbError::CustomError(message) if message.contains("download failed") @@ -1608,7 +1607,7 @@ orderbooks: async fn run_records_engine_build_error() { let yaml = settings_yaml_ok_only(); let manifest_fetcher = Arc::new( - |_orderbooks: &HashMap| -> ManifestFuture { + |_raindexes: &HashMap| -> ManifestFuture { Box::pin(async { Ok(HashMap::new()) }) }, ); @@ -1642,12 +1641,12 @@ orderbooks: assert!(report.successes.is_empty()); assert_eq!(report.failures.len(), 1); let failure = &report.failures[0]; - assert_eq!(failure.ob_id.chain_id, 42161); + assert_eq!(failure.raindex_id.chain_id, 42161); assert_eq!( - failure.ob_id.orderbook_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); - assert_eq!(failure.orderbook_key.as_deref(), Some("ok")); + assert_eq!(failure.raindex_key.as_deref(), Some("ok")); assert!(matches!( &failure.error, LocalDbError::CustomError(message) if message == "engine build error" @@ -1657,9 +1656,9 @@ orderbooks: #[tokio::test] async fn run_records_export_failure_with_stage() { let yaml = settings_yaml_ok_only(); - let manifest_map = manifest_for_ok_orderbook(); + let manifest_map = manifest_for_ok_raindex(); let manifest_fetcher = Arc::new( - move |_orderbooks: &HashMap| -> ManifestFuture { + move |_raindexes: &HashMap| -> ManifestFuture { let manifest_map = manifest_map.clone(); Box::pin(async move { Ok(manifest_map) }) }, @@ -1705,7 +1704,7 @@ orderbooks: let failure = &report.failures[0]; assert_eq!(failure.stage, TargetStage::Export); assert_eq!( - failure.ob_id.orderbook_address, + failure.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); } @@ -1739,7 +1738,7 @@ orderbooks: let yaml = settings_yaml_ok_only(); let mut behaviors = HashMap::new(); behaviors.insert("ok".to_string(), EngineBehavior::Success); - let (environment, _telemetry) = build_environment(manifest_for_ok_orderbook(), behaviors); + let (environment, _telemetry) = build_environment(manifest_for_ok_raindex(), behaviors); let temp_dir = TempDir::new().unwrap(); let release_base = Url::parse("https://releases.example.com").unwrap(); let runner = ProducerRunner::with_environment( @@ -1755,11 +1754,11 @@ orderbooks: panic!("expected success, got failures: {:?}", report.failures); } let outcome = &report.successes[0]; - assert_eq!(outcome.outcome.ob_id.chain_id, 42161); + assert_eq!(outcome.outcome.raindex_id.chain_id, 42161); assert_eq!(outcome.outcome.start_block, 0); assert!( - report.export_for(&outcome.outcome.ob_id).is_none(), + report.export_for(&outcome.outcome.raindex_id).is_none(), "stub environment should not emit dumps" ); } @@ -1787,7 +1786,7 @@ orderbooks: let outcome = &report.successes[0]; let metadata = report - .export_for(&outcome.outcome.ob_id) + .export_for(&outcome.outcome.raindex_id) .expect("export metadata to be present"); assert!( metadata.dump_path.exists(), @@ -1800,7 +1799,7 @@ orderbooks: .expect("dump file name"); let expected_file = format!( "{}-{}.sql.gz", - outcome.outcome.ob_id.chain_id, outcome.outcome.ob_id.orderbook_address + outcome.outcome.raindex_id.chain_id, outcome.outcome.raindex_id.raindex_address ); assert_eq!(file_name, expected_file); assert_eq!(metadata.end_block, outcome.outcome.target_block); @@ -1887,7 +1886,7 @@ orderbooks: .expect("second address present"); assert!( first_index < second_index, - "expected orderbooks to be sorted by address" + "expected raindexes to be sorted by address" ); } @@ -1898,7 +1897,7 @@ orderbooks: behaviors.insert("ok".to_string(), EngineBehavior::Success); behaviors.insert("ok-second".to_string(), EngineBehavior::Success); let (environment, telemetry) = - build_environment(manifest_for_two_ok_orderbooks(), behaviors); + build_environment(manifest_for_two_ok_raindexes(), behaviors); let temp_dir = TempDir::new().unwrap(); let release_base = Url::parse("https://releases.example.com").unwrap(); let runner = ProducerRunner::with_environment( @@ -1973,8 +1972,8 @@ orderbooks: "{}.db", targets[0] .inputs - .ob_id - .orderbook_address + .raindex_id + .raindex_address .to_string() .to_lowercase() ); diff --git a/crates/cli/src/commands/local_db/pipeline/status.rs b/crates/cli/src/commands/local_db/pipeline/status.rs index c0c07360b9..1315ad1946 100644 --- a/crates/cli/src/commands/local_db/pipeline/status.rs +++ b/crates/cli/src/commands/local_db/pipeline/status.rs @@ -1,6 +1,6 @@ -use rain_orderbook_common::local_db::{ +use raindex_common::local_db::{ pipeline::{StatusBus, SyncPhase}, - LocalDbError, OrderbookIdentifier, + LocalDbError, RaindexIdentifier, }; use tracing::info; @@ -24,16 +24,16 @@ impl From for DebugStatus { #[derive(Clone)] pub struct ProducerStatusBus { debug: DebugStatus, - orderbook_key: String, - ob_id: OrderbookIdentifier, + raindex_key: String, + raindex_id: RaindexIdentifier, } impl ProducerStatusBus { - pub fn new(debug: DebugStatus, orderbook_key: String, ob_id: OrderbookIdentifier) -> Self { + pub fn new(debug: DebugStatus, raindex_key: String, raindex_id: RaindexIdentifier) -> Self { Self { debug, - orderbook_key, - ob_id, + raindex_key, + raindex_id, } } } @@ -42,8 +42,8 @@ impl Default for ProducerStatusBus { fn default() -> Self { Self { debug: DebugStatus::Disabled, - orderbook_key: "".to_string(), - ob_id: OrderbookIdentifier::new(0, Default::default()), + raindex_key: "".to_string(), + raindex_id: RaindexIdentifier::new(0, Default::default()), } } } @@ -54,9 +54,9 @@ impl StatusBus for ProducerStatusBus { if self.debug == DebugStatus::Enabled { info!( target: "local_db_status", - chain_id = self.ob_id.chain_id, - orderbook = %self.ob_id.orderbook_address, - orderbook_key = %self.orderbook_key, + chain_id = self.raindex_id.chain_id, + raindex = %self.raindex_id.raindex_address, + raindex_key = %self.raindex_key, "{}", phase.to_message() ); diff --git a/crates/cli/src/commands/order/add.rs b/crates/cli/src/commands/order/add.rs index 000e5f38a9..8c035efc37 100644 --- a/crates/cli/src/commands/order/add.rs +++ b/crates/cli/src/commands/order/add.rs @@ -3,11 +3,11 @@ use crate::{ }; use anyhow::{anyhow, Result}; use clap::{ArgAction, Args}; -use rain_orderbook_app_settings::yaml::dotrain::{DotrainYaml, DotrainYamlValidation}; -use rain_orderbook_app_settings::yaml::YamlParsable; -use rain_orderbook_common::add_order::AddOrderArgs; -use rain_orderbook_common::dotrain::RainDocument; -use rain_orderbook_common::transaction::TransactionArgs; +use raindex_app_settings::yaml::dotrain::{DotrainYaml, DotrainYamlValidation}; +use raindex_app_settings::yaml::YamlParsable; +use raindex_common::add_order::AddOrderArgs; +use raindex_common::dotrain::RainDocument; +use raindex_common::transaction::TransactionArgs; use std::fs::read_to_string; use std::path::PathBuf; use tracing::info; @@ -79,8 +79,8 @@ impl Execute for CliOrderAddArgs { mod tests { use super::*; use alloy::primitives::{address, Address, B256, U256}; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_bindings::IRaindexV6::IOV2; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_bindings::IRaindexV6::IOV2; use std::{collections::HashMap, str::FromStr}; use tempfile::NamedTempFile; @@ -97,7 +97,7 @@ mod tests { dotrain_file: dotrain_path, deployment: "some-deployment".to_string(), transaction_args: CliTransactionArgs { - orderbook_address: Address::random(), + raindex_address: Address::random(), derivation_index: None, chain_id: Some(123), rpcs: vec!["https://some-rpc.com".to_string()], @@ -144,8 +144,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -179,7 +179,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: diff --git a/crates/cli/src/commands/order/calldata.rs b/crates/cli/src/commands/order/calldata.rs index fec1723b76..62a05bda99 100644 --- a/crates/cli/src/commands/order/calldata.rs +++ b/crates/cli/src/commands/order/calldata.rs @@ -3,8 +3,8 @@ use crate::output::{output, SupportedOutputEncoding}; use alloy::sol_types::SolCall; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_common::add_order::AddOrderArgs; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::add_order::AddOrderArgs; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -75,8 +75,8 @@ mod tests { use rain_interpreter_bindings::Rainlang::{ expressionDeployerAddressCall, interpreterAddressCall, parserAddressCall, storeAddressCall, }; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::{FieldErrorKind, YamlError}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::{FieldErrorKind, YamlError}; use serde_json::json; use std::io::Write; use std::str::FromStr; @@ -126,7 +126,7 @@ mod tests { ); } - async fn mock_orderbook_rpc_calls(rpc_server: &MockServer) { + async fn mock_raindex_rpc_calls(rpc_server: &MockServer) { // Helper to build ABI-encoded address return values. let build_address_return = |id: u64| { let addr = Address::random(); @@ -214,8 +214,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -251,7 +251,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: @@ -273,7 +273,7 @@ _ _: 0 0; write!(temp_dotrain_file, "{}", dotrain_content).unwrap(); let dotrain_path = temp_dotrain_file.path(); - mock_orderbook_rpc_calls(&rpc_server).await; + mock_raindex_rpc_calls(&rpc_server).await; let add_order_calldata = AddOrderCalldata { dotrain_file: dotrain_path.to_path_buf(), @@ -325,7 +325,7 @@ scenarios: orders: some-order: rainlang: some-rainlang - orderbook: 0x0000000000000000000000000000000000000000 + raindex: 0x0000000000000000000000000000000000000000 inputs: [] outputs: [] deployments: @@ -410,7 +410,7 @@ test: test #[tokio::test] async fn test_execute_invalid_rainlang_script() { let rpc_server = MockServer::start_async().await; - mock_orderbook_rpc_calls(&rpc_server).await; + mock_raindex_rpc_calls(&rpc_server).await; let dotrain_content_invalid_script = format!( " @@ -422,8 +422,8 @@ networks: chain-id: 1 subgraphs: some-subgraph: https://www.some-subgraph.com -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0x0000000000000000000000000000000000000000 network: some-network subgraph: some-subgraph @@ -439,7 +439,7 @@ scenarios: orders: some-order: rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex inputs: - token: token1 outputs: @@ -493,8 +493,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -530,7 +530,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: diff --git a/crates/cli/src/commands/order/compose.rs b/crates/cli/src/commands/order/compose.rs index 2ecb7725eb..3b115c5553 100644 --- a/crates/cli/src/commands/order/compose.rs +++ b/crates/cli/src/commands/order/compose.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Args; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -62,7 +62,7 @@ impl Execute for Compose { #[cfg(test)] mod tests { - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use tempfile::NamedTempFile; use super::*; @@ -125,8 +125,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg diff --git a/crates/cli/src/commands/order/detail.rs b/crates/cli/src/commands/order/detail.rs index 025d8c7f2b..af46b02c94 100644 --- a/crates/cli/src/commands/order/detail.rs +++ b/crates/cli/src/commands/order/detail.rs @@ -1,7 +1,7 @@ use crate::{execute::Execute, subgraph::CliSubgraphArgs}; use anyhow::Result; use clap::Args; -use rain_orderbook_common::{subgraph::SubgraphArgs, types::OrderDetailExtended}; +use raindex_common::{subgraph::SubgraphArgs, types::OrderDetailExtended}; use tracing::info; #[derive(Args, Clone)] @@ -32,7 +32,7 @@ mod tests { use super::*; use alloy::{hex::encode_prefixed, primitives::B256, sol_types::SolValue}; use httpmock::MockServer; - use rain_orderbook_bindings::IRaindexV6::{OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{OrderV4, IOV2}; use serde_json::{json, Value}; #[tokio::test] @@ -99,7 +99,7 @@ mod tests { "address": encode_prefixed(io.token), "decimals": "0" }, - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "owner": encode_prefixed(order.owner), "ordersAsOutput": [], "ordersAsInput": [], @@ -116,13 +116,13 @@ mod tests { "address": encode_prefixed(io.token), "decimals": "0" }, - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "owner": encode_prefixed(order.owner), "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "meta": null, diff --git a/crates/cli/src/commands/order/list.rs b/crates/cli/src/commands/order/list.rs index 0c9a4ec432..71d9000598 100644 --- a/crates/cli/src/commands/order/list.rs +++ b/crates/cli/src/commands/order/list.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, OrderFlattened, LIST_DELIMITER}, @@ -99,7 +99,7 @@ mod tests { use super::*; use alloy::{hex::encode_prefixed, primitives::B256, sol_types::SolValue}; use httpmock::MockServer; - use rain_orderbook_bindings::IRaindexV6::{OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{OrderV4, IOV2}; use serde_json::{json, Value}; #[tokio::test] @@ -228,7 +228,7 @@ mod tests { "address": encode_prefixed(io.token), "decimals": "0", }, - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "owner": encode_prefixed(order.owner), "ordersAsOutput": [], "ordersAsInput": [], @@ -245,13 +245,13 @@ mod tests { "address": encode_prefixed(io.token), "decimals": "0", }, - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "owner": encode_prefixed(order.owner), "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "meta": null, diff --git a/crates/cli/src/commands/order/listorderfrontmatterkeys.rs b/crates/cli/src/commands/order/listorderfrontmatterkeys.rs index 49f46ad936..fe19a9c012 100644 --- a/crates/cli/src/commands/order/listorderfrontmatterkeys.rs +++ b/crates/cli/src/commands/order/listorderfrontmatterkeys.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; @@ -71,7 +71,7 @@ impl Execute for ListOrderFrontmatterKeys { #[cfg(test)] mod tests { use clap::CommandFactory; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use std::str::FromStr; use tempfile::NamedTempFile; @@ -119,7 +119,7 @@ mod tests { ); } - fn get_test_dotrain(orderbook_key: &str) -> String { + fn get_test_dotrain(raindex_key: &str) -> String { format!( " version: {spec_version} @@ -139,7 +139,7 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: +raindexes: {}: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network @@ -197,14 +197,14 @@ _ _: 0 0; :; #handle-add-order :;", - orderbook_key, + raindex_key, spec_version = SpecVersion::current() ) } #[tokio::test] async fn test_execute_deployment_key() { - let dotrain = get_test_dotrain("some-orderbook"); + let dotrain = get_test_dotrain("some-raindex"); let dotrain_file = NamedTempFile::new().unwrap(); let dotrain_path = dotrain_file.path(); @@ -222,7 +222,7 @@ _ _: 0 0; #[tokio::test] async fn test_execute_scenario_key() { - let dotrain = get_test_dotrain("some-orderbook"); + let dotrain = get_test_dotrain("some-raindex"); let dotrain_file = NamedTempFile::new().unwrap(); let dotrain_path = dotrain_file.path(); @@ -274,7 +274,7 @@ _ _: 0 0; let dotrain_file = NamedTempFile::new().unwrap(); let settings_file = NamedTempFile::new().unwrap(); - let dotrain = get_test_dotrain("some-orderbook"); + let dotrain = get_test_dotrain("some-raindex"); let dotrain_path = dotrain_file.path(); let settings_path = settings_file.path(); diff --git a/crates/cli/src/commands/order/mod.rs b/crates/cli/src/commands/order/mod.rs index 356cb24ad7..e98e5d754c 100644 --- a/crates/cli/src/commands/order/mod.rs +++ b/crates/cli/src/commands/order/mod.rs @@ -4,10 +4,10 @@ mod compose; mod detail; mod list; mod listorderfrontmatterkeys; -mod orderbook_address; +mod raindex_address; mod remove; -use crate::commands::order::orderbook_address::OrderbookAddress; +use crate::commands::order::raindex_address::RaindexAddress; use crate::execute::Execute; use add::CliOrderAddArgs; use anyhow::Result; @@ -44,10 +44,10 @@ pub enum Order { Calldata(AddOrderCalldata), #[command( - about = "Get the orderbook address for a given order", - alias = "ob-addr" + about = "Get the raindex address for a given order", + alias = "raindex-addr" )] - OrderbookAddress(OrderbookAddress), + RaindexAddress(RaindexAddress), #[command(about = "Get frontmatter keys from a dotrain file", alias = "keys")] ListOrderFrontmatterKeys(ListOrderFrontmatterKeys), @@ -62,7 +62,7 @@ impl Execute for Order { Order::Remove(remove) => remove.execute().await, Order::Compose(compose) => compose.execute().await, Order::Calldata(calldata) => calldata.execute().await, - Order::OrderbookAddress(orderbook_address) => orderbook_address.execute().await, + Order::RaindexAddress(raindex_address) => raindex_address.execute().await, Order::ListOrderFrontmatterKeys(keys) => keys.execute().await, } } diff --git a/crates/cli/src/commands/order/orderbook_address.rs b/crates/cli/src/commands/order/raindex_address.rs similarity index 79% rename from crates/cli/src/commands/order/orderbook_address.rs rename to crates/cli/src/commands/order/raindex_address.rs index 9f3855d9c4..6eed20ee5c 100644 --- a/crates/cli/src/commands/order/orderbook_address.rs +++ b/crates/cli/src/commands/order/raindex_address.rs @@ -2,12 +2,12 @@ use crate::execute::Execute; use crate::output::{output, SupportedOutputEncoding}; use anyhow::{anyhow, Result}; use clap::Parser; -use rain_orderbook_common::dotrain_order::DotrainOrder; +use raindex_common::dotrain_order::DotrainOrder; use std::fs::read_to_string; use std::path::PathBuf; #[derive(Parser, Clone)] -pub struct OrderbookAddress { +pub struct RaindexAddress { #[arg( short = 'f', long, @@ -25,7 +25,7 @@ pub struct OrderbookAddress { encoding: SupportedOutputEncoding, } -impl Execute for OrderbookAddress { +impl Execute for RaindexAddress { async fn execute(&self) -> Result<()> { let dotrain = read_to_string(self.dotrain_file.clone()).map_err(|e| anyhow!(e))?; let settings = match &self.settings_file { @@ -39,23 +39,23 @@ impl Execute for OrderbookAddress { .dotrain_yaml() .get_deployment(&self.deployment)?; - let orderbook_address = if let Some(v) = &deployment_ref.order.orderbook { + let raindex_address = if let Some(v) = &deployment_ref.order.raindex { v.address } else { let network_key = &deployment_ref.scenario.rainlang.network.key; - let mut orderbook_address = None; - for key in dotrain_order.orderbook_yaml().get_orderbook_keys()? { - let orderbook = dotrain_order.orderbook_yaml().get_orderbook(&key)?; - if key == *network_key || orderbook.network.key == *network_key { - orderbook_address = Some(orderbook.address); + let mut raindex_address = None; + for key in dotrain_order.raindex_yaml().get_raindex_keys()? { + let raindex = dotrain_order.raindex_yaml().get_raindex(&key)?; + if key == *network_key || raindex.network.key == *network_key { + raindex_address = Some(raindex.address); } } - if orderbook_address.is_none() { - return Err(anyhow!("specified orderbook is undefined!")); + if raindex_address.is_none() { + return Err(anyhow!("specified raindex is undefined!")); } - orderbook_address.unwrap() + raindex_address.unwrap() }; - output(&None, self.encoding.clone(), orderbook_address.as_slice())?; + output(&None, self.encoding.clone(), raindex_address.as_slice())?; Ok(()) } @@ -65,13 +65,13 @@ impl Execute for OrderbookAddress { mod tests { use super::*; use clap::CommandFactory; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use std::str::FromStr; use tempfile::NamedTempFile; #[test] fn verify_cli() { - OrderbookAddress::command().debug_assert(); + RaindexAddress::command().debug_assert(); } #[test] @@ -81,7 +81,7 @@ mod tests { let deployment_str = "some-deployment"; let output_str = "hex"; - let cmd = OrderbookAddress::command(); + let cmd = RaindexAddress::command(); let result = cmd.get_matches_from(vec![ "cmd", "-f", @@ -111,7 +111,7 @@ mod tests { ); } - fn get_test_dotrain(orderbook_key: &str) -> String { + fn get_test_dotrain(raindex_key: &str) -> String { format!( " version: {spec_version} @@ -132,7 +132,7 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: +raindexes: {}: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network @@ -183,26 +183,26 @@ _ _: 0 0; :; #handle-add-order :;", - orderbook_key, + raindex_key, spec_version = SpecVersion::current() ) } #[tokio::test] async fn test_execute_diff_name() { - let dotrain = get_test_dotrain("some-orderbook"); + let dotrain = get_test_dotrain("some-raindex"); let dotrain_file = NamedTempFile::new().unwrap(); std::fs::write(dotrain_file.path(), dotrain).unwrap(); - let orderbook_adress = OrderbookAddress { + let raindex_address = RaindexAddress { dotrain_file: dotrain_file.path().into(), settings_file: None, deployment: "some-deployment".to_string(), encoding: SupportedOutputEncoding::Hex, }; // should succeed without err - orderbook_adress.execute().await.unwrap(); + raindex_address.execute().await.unwrap(); } #[tokio::test] @@ -212,14 +212,14 @@ _ _: 0 0; let dotrain_file = NamedTempFile::new().unwrap(); std::fs::write(dotrain_file.path(), dotrain).unwrap(); - let orderbook_adress = OrderbookAddress { + let raindex_address = RaindexAddress { dotrain_file: dotrain_file.path().into(), settings_file: None, deployment: "some-deployment".to_string(), encoding: SupportedOutputEncoding::Hex, }; // should succeed without err - orderbook_adress.execute().await.unwrap(); + raindex_address.execute().await.unwrap(); } #[tokio::test] @@ -229,39 +229,39 @@ _ _: 0 0; let dotrain_file = NamedTempFile::new().unwrap(); std::fs::write(dotrain_file.path(), dotrain).unwrap(); - let orderbook_adress = OrderbookAddress { + let raindex_address = RaindexAddress { dotrain_file: dotrain_file.path().into(), settings_file: None, deployment: "non-existing-deployment".to_string(), encoding: SupportedOutputEncoding::Hex, }; // should return err - orderbook_adress.execute().await.unwrap_err(); + raindex_address.execute().await.unwrap_err(); } #[tokio::test] async fn test_execute_non_existing_file() { - let orderbook_adress = OrderbookAddress { + let raindex_address = RaindexAddress { dotrain_file: PathBuf::from_str("non-existing-file.rain").unwrap(), settings_file: None, deployment: "some-deployment".to_string(), encoding: SupportedOutputEncoding::Hex, }; // should return err - orderbook_adress.execute().await.unwrap_err(); + raindex_address.execute().await.unwrap_err(); } #[tokio::test] async fn test_execute_empty_dotrain() { let dotrain_file = NamedTempFile::new().unwrap(); - let orderbook_adress = OrderbookAddress { + let raindex_address = RaindexAddress { dotrain_file: dotrain_file.path().into(), settings_file: None, deployment: "some-deployment".to_string(), encoding: SupportedOutputEncoding::Hex, }; // should return err - orderbook_adress.execute().await.unwrap_err(); + raindex_address.execute().await.unwrap_err(); } } diff --git a/crates/cli/src/commands/order/remove.rs b/crates/cli/src/commands/order/remove.rs index 80f7c56b85..2200842a97 100644 --- a/crates/cli/src/commands/order/remove.rs +++ b/crates/cli/src/commands/order/remove.rs @@ -4,9 +4,9 @@ use crate::{ }; use anyhow::Result; use clap::Args; -use rain_orderbook_common::remove_order::RemoveOrderArgs; -use rain_orderbook_common::subgraph::SubgraphArgs; -use rain_orderbook_common::transaction::TransactionArgs; +use raindex_common::remove_order::RemoveOrderArgs; +use raindex_common::subgraph::SubgraphArgs; +use raindex_common::transaction::TransactionArgs; use tracing::info; #[derive(Args, Clone)] diff --git a/crates/cli/src/commands/quote/mod.rs b/crates/cli/src/commands/quote/mod.rs index 8e05ee65a9..06264c27c5 100644 --- a/crates/cli/src/commands/quote/mod.rs +++ b/crates/cli/src/commands/quote/mod.rs @@ -1,5 +1,5 @@ use crate::execute::Execute; -use rain_orderbook_quote::cli::Quoter; +use raindex_quote::cli::Quoter; impl Execute for Quoter { async fn execute(&self) -> anyhow::Result<()> { diff --git a/crates/cli/src/commands/subgraph/mod.rs b/crates/cli/src/commands/subgraph/mod.rs index 99b7e8cf1d..148f0f046e 100644 --- a/crates/cli/src/commands/subgraph/mod.rs +++ b/crates/cli/src/commands/subgraph/mod.rs @@ -1,7 +1,7 @@ use crate::execute::Execute; use anyhow::Result; use clap::Parser; -use rain_orderbook_subgraph_client::validate::validate_subgraph_schema; +use raindex_subgraph_client::validate::validate_subgraph_schema; #[derive(Parser)] pub enum Subgraph { diff --git a/crates/cli/src/commands/trade/detail.rs b/crates/cli/src/commands/trade/detail.rs index a4916812f5..ad3fda203e 100644 --- a/crates/cli/src/commands/trade/detail.rs +++ b/crates/cli/src/commands/trade/detail.rs @@ -2,7 +2,7 @@ use crate::{execute::Execute, subgraph::CliSubgraphArgs}; use anyhow::Result; use clap::Args; -use rain_orderbook_common::subgraph::SubgraphArgs; +use raindex_common::subgraph::SubgraphArgs; use tracing::info; @@ -88,7 +88,7 @@ mod tests { "orderBytes": encode_prefixed(B256::random()), "outputs": [], "inputs": [], - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "meta": null, @@ -120,7 +120,7 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "trade": { @@ -153,7 +153,7 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "trade": { @@ -172,7 +172,7 @@ mod tests { "from": encode_prefixed(Address::random()) } }, - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, } diff --git a/crates/cli/src/commands/trade/list.rs b/crates/cli/src/commands/trade/list.rs index 5f413db762..fbed5f6cbd 100644 --- a/crates/cli/src/commands/trade/list.rs +++ b/crates/cli/src/commands/trade/list.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, OrderTakeFlattened, NO_SYMBOL}, @@ -98,7 +98,7 @@ mod tests { primitives::{Address, B256}, }; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; #[tokio::test] @@ -184,7 +184,7 @@ mod tests { "orderBytes": encode_prefixed(B256::random()), "outputs": [], "inputs": [], - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "meta": null, @@ -216,7 +216,7 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "trade": { @@ -249,7 +249,7 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "trade": { @@ -268,7 +268,7 @@ mod tests { "from": encode_prefixed(Address::random()) } }, - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, }] diff --git a/crates/cli/src/commands/vault/deposit.rs b/crates/cli/src/commands/vault/deposit.rs index 16cbecf547..30e5cc1f28 100644 --- a/crates/cli/src/commands/vault/deposit.rs +++ b/crates/cli/src/commands/vault/deposit.rs @@ -5,7 +5,7 @@ use alloy::primitives::{Address, B256, U256}; use anyhow::Result; use clap::Args; use rain_math_float::Float; -use rain_orderbook_common::{deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs}; +use raindex_common::{deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs}; use tracing::info; #[derive(Args, Clone)] @@ -58,7 +58,7 @@ impl Execute for CliVaultDepositArgs { }) .await?; - info!("----- Deposit tokens into Orderbook -----"); + info!("----- Deposit tokens into Raindex -----"); deposit_args .execute_deposit(tx_args, |status| { display_write_transaction_status(status); diff --git a/crates/cli/src/commands/vault/detail.rs b/crates/cli/src/commands/vault/detail.rs index b218e1efed..c8a5224a1b 100644 --- a/crates/cli/src/commands/vault/detail.rs +++ b/crates/cli/src/commands/vault/detail.rs @@ -1,7 +1,7 @@ use crate::{execute::Execute, subgraph::CliSubgraphArgs}; use anyhow::Result; use clap::Args; -use rain_orderbook_common::subgraph::SubgraphArgs; +use raindex_common::subgraph::SubgraphArgs; use tracing::info; #[derive(Args, Clone)] @@ -100,7 +100,7 @@ mod tests { "orderHash": encode_prefixed(B256::random()), }], "balanceChanges": [], - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "balanceChanges": [] diff --git a/crates/cli/src/commands/vault/list.rs b/crates/cli/src/commands/vault/list.rs index 40aced8580..8fac46c401 100644 --- a/crates/cli/src/commands/vault/list.rs +++ b/crates/cli/src/commands/vault/list.rs @@ -5,12 +5,12 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, TokenVaultFlattened, NO_SYMBOL}, }; -use rain_orderbook_subgraph_client::SgPaginationArgs; +use raindex_subgraph_client::SgPaginationArgs; use tracing::info; #[derive(Args, Clone)] @@ -92,7 +92,7 @@ mod tests { primitives::{Address, B256}, }; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; #[tokio::test] @@ -209,7 +209,7 @@ mod tests { "orderHash": encode_prefixed(B256::random()), "active": true, }], - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, "balanceChanges": [] diff --git a/crates/cli/src/commands/vault/list_balance_changes.rs b/crates/cli/src/commands/vault/list_balance_changes.rs index 45871260f2..21b8d504fa 100644 --- a/crates/cli/src/commands/vault/list_balance_changes.rs +++ b/crates/cli/src/commands/vault/list_balance_changes.rs @@ -5,7 +5,7 @@ use crate::{ use anyhow::Result; use clap::Args; use comfy_table::Table; -use rain_orderbook_common::{ +use raindex_common::{ csv::TryIntoCsv, subgraph::SubgraphArgs, types::{FlattenError, VaultBalanceChangeFlattened}, @@ -93,7 +93,7 @@ mod tests { primitives::{Address, B256}, }; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; #[tokio::test] @@ -193,7 +193,7 @@ mod tests { "from": encode_prefixed(Address::random()) }, "timestamp": "0", - "orderbook": { + "raindex": { "id": encode_prefixed(B256::random()), }, }] diff --git a/crates/cli/src/commands/vault/withdraw.rs b/crates/cli/src/commands/vault/withdraw.rs index 5f7eefec9a..2e92f02a3b 100644 --- a/crates/cli/src/commands/vault/withdraw.rs +++ b/crates/cli/src/commands/vault/withdraw.rs @@ -4,8 +4,8 @@ use alloy::primitives::{Address, B256}; use anyhow::Result; use clap::Args; use rain_math_float::{Float, FloatError}; -use rain_orderbook_common::transaction::TransactionArgs; -use rain_orderbook_common::withdraw::WithdrawArgs; +use raindex_common::transaction::TransactionArgs; +use raindex_common::withdraw::WithdrawArgs; use tracing::info; #[derive(Args, Clone)] diff --git a/crates/cli/src/commands/words.rs b/crates/cli/src/commands/words.rs index ee2de34f32..351a9d2645 100644 --- a/crates/cli/src/commands/words.rs +++ b/crates/cli/src/commands/words.rs @@ -2,7 +2,7 @@ use crate::execute::Execute; use anyhow::{anyhow, Result}; use clap::{ArgAction, Args, Parser}; use csv::Writer; -use rain_orderbook_common::dotrain_order::{AuthoringMetaV2, DotrainOrder, WordsResult}; +use raindex_common::dotrain_order::{AuthoringMetaV2, DotrainOrder, WordsResult}; use std::{fs::read_to_string, path::PathBuf}; /// Get words of a rainlang contract from the given inputs @@ -96,7 +96,7 @@ impl Execute for Words { let results = if let Some(rainlang_key) = &self.source.rainlang { // get rainlang from order config - let rainlang = dotrain_order.orderbook_yaml().get_rainlang(rainlang_key)?; + let rainlang = dotrain_order.raindex_yaml().get_rainlang(rainlang_key)?; // get metaboard subgraph url let metaboard_url = self @@ -105,7 +105,7 @@ impl Execute for Words { .map(|v| v.to_string()) .or_else(|| { dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_metaboard(&rainlang.network.key) .ok() .map(|metaboard| metaboard.url.to_string()) @@ -132,7 +132,7 @@ impl Execute for Words { .key .clone(); dotrain_order - .orderbook_yaml() + .raindex_yaml() .add_metaboard(network_name, v)?; } if self.rainlang_only { @@ -179,7 +179,7 @@ impl Execute for Words { if let Some(v) = &self.metaboard_subgraph { let network_key = deployment.scenario.rainlang.network.key.clone(); dotrain_order - .orderbook_yaml() + .raindex_yaml() .add_metaboard(&network_key, v)?; } let result = dotrain_order.get_all_words_for_scenario(scenario).await?; @@ -225,7 +225,7 @@ mod tests { use clap::CommandFactory; use httpmock::MockServer; use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use serde_bytes::ByteBuf; use serde_json::json; use tempfile::NamedTempFile; @@ -533,8 +533,8 @@ scenarios: bindings: key1: 10 -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -563,7 +563,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index eba89a4991..0a4e39d9c7 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -3,7 +3,7 @@ use crate::execute::Execute; use anyhow::Result; use clap::Subcommand; use commands::local_db::LocalDbCommands; -use rain_orderbook_quote::cli::Quoter; +use raindex_quote::cli::Quoter; mod commands; mod execute; @@ -13,7 +13,7 @@ mod subgraph; mod transaction; #[derive(Subcommand)] -pub enum Orderbook { +pub enum Raindex { #[command(subcommand)] Order(Order), @@ -36,17 +36,17 @@ pub enum Orderbook { LocalDb(LocalDbCommands), } -impl Orderbook { +impl Raindex { pub async fn execute(self) -> Result<()> { match self { - Orderbook::Order(order) => order.execute().await, - Orderbook::Vault(vault) => vault.execute().await, - Orderbook::Trade(trade) => trade.execute().await, - Orderbook::Chart(chart) => chart.execute().await, - Orderbook::Quote(quote) => quote.execute().await, - Orderbook::Subgraph(subgraph) => subgraph.execute().await, - Orderbook::Words(words) => words.execute().await, - Orderbook::LocalDb(local_db) => local_db.execute().await, + Raindex::Order(order) => order.execute().await, + Raindex::Vault(vault) => vault.execute().await, + Raindex::Trade(trade) => trade.execute().await, + Raindex::Chart(chart) => chart.execute().await, + Raindex::Quote(quote) => quote.execute().await, + Raindex::Subgraph(subgraph) => subgraph.execute().await, + Raindex::Words(words) => words.execute().await, + Raindex::LocalDb(local_db) => local_db.execute().await, } } } diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index 182a663540..51a66a3f48 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -1,13 +1,13 @@ use anyhow::Result; use clap::Parser; -use rain_orderbook_cli::Orderbook; +use raindex_cli::Raindex; use tracing_subscriber::filter::{EnvFilter, LevelFilter}; #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Cli { #[command(subcommand)] - orderbook: Orderbook, + raindex: Raindex, } #[tokio::main] @@ -29,7 +29,7 @@ async fn main() -> Result<()> { .init(); let cli = Cli::parse(); - cli.orderbook.execute().await + cli.raindex.execute().await } #[cfg(test)] diff --git a/crates/cli/src/subgraph.rs b/crates/cli/src/subgraph.rs index feeee60f99..b1c17c6729 100644 --- a/crates/cli/src/subgraph.rs +++ b/crates/cli/src/subgraph.rs @@ -1,6 +1,6 @@ use clap::Args; -use rain_orderbook_common::subgraph::SubgraphArgs; -use rain_orderbook_subgraph_client::{ +use raindex_common::subgraph::SubgraphArgs; +use raindex_subgraph_client::{ types::common::{ SgBytes, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, SgVaultsListFilterArgs, }, @@ -12,7 +12,7 @@ pub struct CliSubgraphArgs { #[arg( short, long, - help = "Url of the hosted Subgraph for this Orderbook deployemnt" + help = "Url of the hosted Subgraph for this Raindex deployment" )] pub subgraph_url: String, } @@ -108,7 +108,7 @@ impl From for SgOrdersListFilterArgs { active: val.active, order_hash: val.order_hash.map(SgBytes), tokens, - orderbooks: vec![], + raindexes: vec![], } } } @@ -119,7 +119,7 @@ impl From for SgVaultsListFilterArgs { owners: val.owners.into_iter().map(SgBytes).collect(), hide_zero_balance: val.hide_zero_balance.unwrap_or(true), tokens: val.tokens, - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, } } diff --git a/crates/cli/src/transaction.rs b/crates/cli/src/transaction.rs index f79aff7546..603ba5de21 100644 --- a/crates/cli/src/transaction.rs +++ b/crates/cli/src/transaction.rs @@ -1,11 +1,11 @@ use alloy::primitives::Address; use clap::Args; -use rain_orderbook_common::transaction::TransactionArgs; +use raindex_common::transaction::TransactionArgs; #[derive(Args, Clone)] pub struct CliTransactionArgs { - #[arg(short, long, help = "Orderbook contract address")] - pub orderbook_address: Address, + #[arg(long, help = "Raindex contract address")] + pub raindex_address: Address, #[arg( short, @@ -31,7 +31,7 @@ pub struct CliTransactionArgs { impl From for TransactionArgs { fn from(val: CliTransactionArgs) -> Self { TransactionArgs { - orderbook_address: val.orderbook_address, + raindex_address: val.raindex_address, derivation_index: val.derivation_index, chain_id: val.chain_id, rpcs: val.rpcs, @@ -48,7 +48,7 @@ mod tests { #[test] fn test_from_cli_transaction_args() { let cli_args = CliTransactionArgs { - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: Some(1), chain_id: Some(2), rpcs: vec!["http://localhost:8545".to_string()], @@ -58,16 +58,16 @@ mod tests { let transaction_args: TransactionArgs = cli_args.into(); - assert_eq!(transaction_args.orderbook_address, Address::ZERO); + assert_eq!(transaction_args.raindex_address, Address::ZERO); assert_eq!(transaction_args.derivation_index, Some(1)); assert_eq!(transaction_args.chain_id, Some(2)); assert_eq!(transaction_args.rpcs, vec!["http://localhost:8545"]); assert_eq!(transaction_args.max_priority_fee_per_gas, Some(100)); assert_eq!(transaction_args.max_fee_per_gas, Some(1000)); - let orderbook_address = Address::random(); + let raindex_address = Address::random(); let cli_args = CliTransactionArgs { - orderbook_address, + raindex_address, derivation_index: None, chain_id: None, rpcs: vec!["http://localhost:8545".to_string()], @@ -77,7 +77,7 @@ mod tests { let transaction_args: TransactionArgs = cli_args.into(); - assert_eq!(transaction_args.orderbook_address, orderbook_address); + assert_eq!(transaction_args.raindex_address, raindex_address); assert_eq!(transaction_args.derivation_index, None); assert_eq!(transaction_args.chain_id, None); assert_eq!(transaction_args.rpcs, vec!["http://localhost:8545"]); diff --git a/crates/common/ARCHITECTURE.md b/crates/common/ARCHITECTURE.md index 8c0c382d04..abd7b7d5cc 100644 --- a/crates/common/ARCHITECTURE.md +++ b/crates/common/ARCHITECTURE.md @@ -1,10 +1,10 @@ -# rain_orderbook_common — Architecture & Reference +# raindex_common — Architecture & Reference -This crate provides the shared core for the Rain Orderbook toolchain across native (CLI, services) and WebAssembly (browser) targets. It bundles higher‑level orchestration around: +This crate provides the shared core for the Raindex toolchain across native (CLI, services) and WebAssembly (browser) targets. It bundles higher‑level orchestration around: - Parsing and composing Rain language (Rainlang) and DOTRAIN YAML frontmatter. -- Building and executing Orderbook contract calls (add/remove orders, deposit, withdraw), including Ledger support on native. -- Querying orderbook state via the subgraph and flattening results for display/CSV export. +- Building and executing Raindex contract calls (add/remove orders, deposit, withdraw), including Ledger support on native. +- Querying raindex state via the subgraph and flattening results for display/CSV export. - A WASM‑friendly API surface for UI apps (via `wasm_bindgen_utils` and `tsify`). - Developer ergonomics: LSP helpers, fuzz/unit‑test runners, and EVM fork utilities to parse/evaluate Rainlang and replay transactions. @@ -19,8 +19,8 @@ The library is built as `rlib` and `cdylib`. A Git commit identifier is embedded - `withdraw` — `withdraw3` call builder/executor and calldata generator. - `transaction` — Shared tx args (RPCs, chain ID, fees), Ledger provider creation (native), and `WriteContractParameters` helpers. - `erc20` — Typed ERC20 reads (decimals/name/symbol/allowance/balance), multicall token info, and robust revert decoding. -- `subgraph` — Thin wrapper to instantiate an orderbook subgraph client from a URL. -- `raindex_client/*` — High‑level client over orderbook YAML config: find networks/orderbooks, fetch orders, vaults, trades, transactions; quote orders; prepare batch withdraw calldata; expose WASM‑friendly structs. The `local_db/` subtree is split into `state.rs` (runtime state, query routing via `LocalDbState`/`QuerySource`/`SyncReadiness`) and `status.rs` (UI status‑reporting types). +- `subgraph` — Thin wrapper to instantiate a raindex subgraph client from a URL. +- `raindex_client/*` — High‑level client over raindex YAML config: find networks/raindexes, fetch orders, vaults, trades, transactions; quote orders; prepare batch withdraw calldata; expose WASM‑friendly structs. The `local_db/` subtree is split into `state.rs` (runtime state, query routing via `LocalDbState`/`QuerySource`/`SyncReadiness`) and `status.rs` (UI status‑reporting types). - `dotrain_order` — Parse and validate a DOTRAIN config; compose scenarios/deployments to Rainlang; fetch authoring metadata and pragma words; merge additional settings. - `rainlang` — Compose Rainlang from a DOTRAIN string + bindings; optional fork‑based parser that returns encoded bytecode. - `dotrain_add_order_lsp` — Language‑services integration for Rainlang/DOTRAIN (hover, completion, diagnostics, and fork‑parse problems). @@ -41,7 +41,7 @@ Target gating is used extensively: ## Key Data Flow & Responsibilities ### 1) DOTRAIN → Rainlang → Bytecode (add_order) -- Inputs: DOTRAIN (YAML frontmatter + Rainlang sections), selected scenario/deployment (from `rain_orderbook_app_settings`), and bindings. +- Inputs: DOTRAIN (YAML frontmatter + Rainlang sections), selected scenario/deployment (from `raindex_app_settings`), and bindings. - `AddOrderArgs::compose_to_rainlang` uses `rainlang::compose_to_rainlang` to produce the Rainlang snippet for order entrypoints (`calculate-io`, `handle-io`). - Parser address is discovered via `DISPair::from_deployer`; the Rainlang text is parsed by `ParserV2::parse_text` over provided RPCs to produce bytecode. - Metadata is generated as a Rain Meta V1 document containing `RainlangSourceV1` and CBOR‑encoded with `rain-metadata`. @@ -75,23 +75,23 @@ Target gating is used extensively: - Revert data is decoded via `rain_error_decoding` to produce human‑readable errors. For multicall `CallFailed`, the revert is decoded and mapped. ### 7) Subgraph Client Creation -- `SubgraphArgs::to_subgraph_client` parses the URL and returns an `OrderbookSubgraphClient` bound to that endpoint. +- `SubgraphArgs::to_subgraph_client` parses the URL and returns a raindex subgraph client bound to that endpoint. -### 8) Raindex Client (orderbook YAML–driven API) -- `RaindexClient::create` (async on WASM, aliased to `new` in JS) parses one or more orderbook YAML strings using `OrderbookYaml`, optionally with full validation. When the YAML declares `local-db-sync` sections and DB callbacks are provided, the constructor automatically sets up the local DB and starts the sync scheduler. +### 8) Raindex Client (raindex YAML–driven API) +- `RaindexClient::create` (async on WASM, aliased to `new` in JS) parses one or more raindex YAML strings using `RaindexYaml`, optionally with full validation. When the YAML declares `local-db-sync` sections and DB callbacks are provided, the constructor automatically sets up the local DB and starts the sync scheduler. - `LocalDbState` encapsulates the local DB handle, scheduler, `SyncReadiness` (tracks which chains have completed a sync cycle), and the set of configured chain IDs. Query routing uses `QuerySource::LocalDb` vs `QuerySource::Subgraph` — each chain is routed to exactly one source based on configuration and readiness. -- Derives a map of networks and orderbooks to build `MultiSubgraphArgs` groupings for cross‑network queries. +- Derives a map of networks and raindexes to build `MultiSubgraphArgs` groupings for cross‑network queries. - Exposed operations (with WASM bindings): - - YAML accessors: get unique chain IDs, networks, orderbooks by address, accounts, and RPC URLs. + - YAML accessors: get unique chain IDs, networks, raindexes by address, accounts, and RPC URLs. - Orders: list with filters/pagination across networks, fetch by hash, fetch orders created in a transaction. - Quotes: compute per‑pair quotes for an order (`get_order_quotes` under the hood), with formatted ratios and inverses. - - Vaults: list/query vaults for an order or orderbook, fetch balance changes, prepare withdraw multicall calldata, format balances. + - Vaults: list/query vaults for an order or raindex, fetch balance changes, prepare withdraw multicall calldata, format balances. - Trades and transactions: list trades (with optional time bounds), fetch trade detail, transaction detail. - Conversion helpers map subgraph types (`Sg*`) to WASM/JS‑friendly shapes (`Raindex*`) and back when needed. - Error surface `RaindexError` normalizes failures from YAML parsing, hex parsing, subgraph network errors, ERC20 reads, float/parse errors, etc., and provides user‑facing messages via `to_readable_msg`. ### 9) DOTRAIN Order Utilities -- `DotrainOrder::create` extracts frontmatter from a DOTRAIN text, validates spec version, hydrates remote networks/tokens if configured, and builds both `DotrainYaml` and `OrderbookYaml` caches. +- `DotrainOrder::create` extracts frontmatter from a DOTRAIN text, validates spec version, hydrates remote networks/tokens if configured, and builds both `DotrainYaml` and `RaindexYaml` caches. - Compose helpers: - `compose_scenario_to_rainlang` and `compose_deployment_to_rainlang` create Rainlang with scenario/deployment bindings applied. - `compose_scenario_to_post_task_rainlang` produces post‑task (`handle-add-order`) Rainlang. @@ -139,18 +139,18 @@ Target gating is used extensively: - `rainlang::compose_to_rainlang` and native `fork_parse::parse_rainlang_on_fork` - Raindex client (selected) - - YAML: `get_unique_chain_ids`, `get_all_networks`, `get_network_by_chain_id`, `get_orderbook_by_address`, `get_all_accounts` + - YAML: `get_unique_chain_ids`, `get_all_networks`, `get_network_by_chain_id`, `get_raindex_by_address`, `get_all_accounts` - Orders: `get_orders`, `get_order_by_hash`, `get_add_orders_for_transaction` - Quotes: `RaindexOrder::get_quotes` - - Vaults: `get_vaults_list`, `get_orderbook_vaults_list`, `RaindexVault::{get_balance_changes, get_deposit_calldata, get_withdraw_calldata}`, `RaindexVault::get_account_balance` + - Vaults: `get_vaults_list`, `get_raindex_vaults_list`, `RaindexVault::{get_balance_changes, get_deposit_calldata, get_withdraw_calldata}`, `RaindexVault::get_account_balance` - Trades/Tx: `RaindexOrder::{get_trades_list, get_trades_count}`, `RaindexOrder::get_trade_detail`, `RaindexClient::get_transaction` - CSV & types - `TryIntoCsv` implemented on vectors of flattened types for export. - Constants - - `ORDERBOOK_ORDER_ENTRYPOINTS` = [`calculate-io`, `handle-io`] - - `ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS` = [`handle-add-order`] + - `RAINDEX_ORDER_ENTRYPOINTS` = [`calculate-io`, `handle-io`] + - `RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS` = [`handle-add-order`] - `types::vault::NO_SYMBOL` — fallback when token symbol is absent - `GH_COMMIT_SHA` — compile‑time commit id @@ -181,8 +181,8 @@ Where functionality cannot run in WASM, equivalent calldata generation methods a ## Subgraph, YAML, and Quoting -- Subgraph clients are constructed from orderbook YAML to ensure per‑network routing and naming. -- The client supports multi‑network fan‑out via `MultiOrderbookSubgraphClient` and paginated queries. +- Subgraph clients are constructed from raindex YAML to ensure per‑network routing and naming. +- The client supports multi‑network fan‑out via `MultiRaindexSubgraphClient` and paginated queries. - Quotes use on‑chain multicall under the hood; results are converted to `Float` and pre‑formatted strings, including inverse ratios and empty/infinite cases. @@ -200,10 +200,10 @@ Where functionality cannot run in WASM, equivalent calldata generation methods a ## Notable Dependencies (workspace crates) -- `rain_orderbook_bindings` — Strongly‑typed ABI for Orderbook and ERC20 contracts (`addOrder3`, `removeOrder3`, `deposit3`, `withdraw3`, multicall). -- `rain_orderbook_subgraph_client` — GraphQL types and clients for orderbook data; provides `Sg*` models and helpers. -- `rain_orderbook_app_settings` — DOTRAIN/orderbook YAML structures, validation, and spec versioning. -- `rain_orderbook_quote` — Batch quote engine for orders. +- `raindex_bindings` — Strongly‑typed ABI for Raindex and ERC20 contracts (`addOrder3`, `removeOrder3`, `deposit3`, `withdraw3`, multicall). +- `raindex_subgraph_client` — GraphQL types and clients for raindex data; provides `Sg*` models and helpers. +- `raindex_app_settings` — DOTRAIN/raindex YAML structures, validation, and spec versioning. +- `raindex_quote` — Batch quote engine for orders. - `rain_interpreter_*` — Parser, eval, DISP pair, bindings used to compile/evaluate Rainlang. - `rain_metadata` — CBOR‑encoded metadata with magic prefixes; used to embed Rainlang source. - `rain_error_decoding` — ABI error decoding to readable types/names. @@ -227,7 +227,7 @@ Where functionality cannot run in WASM, equivalent calldata generation methods a 1) For deposit, check allowance and, when it differs from the intended amount, approve the exact target before calling `deposit3`. 2) For withdraw, construct `withdraw3` calldata or execute; batch multiple via `RaindexVaultsList::get_withdraw_calldata`. -- Explore orderbook data in a UI: +- Explore raindex data in a UI: 1) Instantiate `RaindexClient` from YAML configs. 2) List orders across networks; fetch vaults, trades, and quotes for selected orders. 3) Render CSV exports using `TryIntoCsv` on flattened types. diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index a5c1cebc53..699c73d85a 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_common" -description = "Rain Orderbook CLI." +name = "raindex_common" +description = "Raindex CLI." version.workspace = true edition.workspace = true license.workspace = true @@ -16,10 +16,10 @@ browser-tests = [] crate-type = ["rlib", "cdylib"] [dependencies] -rain_orderbook_bindings = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_quote = { workspace = true } +raindex_bindings = { workspace = true } +raindex_subgraph_client = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_quote = { workspace = true } alloy = { workspace = true, features = ["dyn-abi", "rand"] } alloy-ethers-typecast = { workspace = true } url = { workspace = true } @@ -77,5 +77,5 @@ wasm-bindgen-futures = "0.4" [target.'cfg(not(target_family = "wasm"))'.dev-dependencies] httpmock = "0.7.0" -rain_orderbook_test_fixtures = { workspace = true } +raindex_test_fixtures = { workspace = true } tempfile = "3" diff --git a/crates/common/src/add_order.rs b/crates/common/src/add_order.rs index d366fdc260..b09dadd0c4 100644 --- a/crates/common/src/add_order.rs +++ b/crates/common/src/add_order.rs @@ -32,17 +32,15 @@ use rain_metadata::{ ContentLanguage, ContentType, Error as RainMetaError, KnownMagic, RainMetaDocumentV1Item, }; use rain_metadata_bindings::MetaBoard::emitMetaCall; -use rain_orderbook_app_settings::deployment::DeploymentCfg; -use rain_orderbook_bindings::IRaindexV6::{ - addOrder4Call, EvaluableV4, OrderConfigV4, TaskV2, IOV2, -}; +use raindex_app_settings::deployment::DeploymentCfg; +use raindex_bindings::IRaindexV6::{addOrder4Call, EvaluableV4, OrderConfigV4, TaskV2, IOV2}; use serde::{Deserialize, Serialize}; use serde_bytes::ByteBuf; use std::collections::HashMap; use thiserror::Error; -pub static ORDERBOOK_ORDER_ENTRYPOINTS: [&str; 2] = ["calculate-io", "handle-io"]; -pub static ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS: [&str; 1] = ["handle-add-order"]; +pub static RAINDEX_ORDER_ENTRYPOINTS: [&str; 2] = ["calculate-io", "handle-io"]; +pub static RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS: [&str; 1] = ["handle-add-order"]; #[derive(Error, Debug)] pub enum AddOrderArgsError { @@ -258,7 +256,7 @@ impl AddOrderArgs { let res = compose_to_rainlang( self.dotrain.clone(), self.bindings.clone(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, )?; Ok(res) } @@ -268,7 +266,7 @@ impl AddOrderArgs { let res = compose_to_rainlang( self.dotrain.clone(), self.bindings.clone(), - &ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS, + &RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS, )?; Ok(res) } @@ -360,10 +358,8 @@ impl AddOrderArgs { transaction_args: TransactionArgs, ) -> Result, AddOrderArgsError> { let add_order_call = self.try_into_call(transaction_args.clone().rpcs).await?; - let params = transaction_args.try_into_write_contract_parameters( - add_order_call, - transaction_args.orderbook_address, - )?; + let params = transaction_args + .try_into_write_contract_parameters(add_order_call, transaction_args.raindex_address)?; Ok(params) } @@ -437,7 +433,7 @@ impl AddOrderArgs { match forker .alloy_call_committing( Address::from(from_address), - transaction_args.orderbook_address, + transaction_args.raindex_address, call, U256::ZERO, true, @@ -472,7 +468,7 @@ mod tests { use rain_metadata::{ types::dotrain::source_v1::DotrainSourceV1, Error as RainMetaError, KnownMagic, }; - use rain_orderbook_app_settings::{ + use raindex_app_settings::{ network::NetworkCfg, order::{OrderCfg, OrderIOCfg}, rainlang::RainlangCfg, @@ -481,7 +477,7 @@ mod tests { token::TokenCfg, yaml::{default_document, default_documents}, }; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use std::{ collections::BTreeMap, str::FromStr, @@ -748,7 +744,7 @@ price: 2e18; }], network: network_arc.clone(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }; let deployment = DeploymentCfg { @@ -872,7 +868,7 @@ _ _: 0 0; }], network: network_arc.clone(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }; let deployment = DeploymentCfg { @@ -1039,7 +1035,7 @@ _ _: 0 0; }], network: network_arc.clone(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }; let deployment = DeploymentCfg { @@ -1120,7 +1116,7 @@ _ _: 0 key1; async fn test_simulate_execute_ok() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -1151,9 +1147,9 @@ tokens: decimals: 18 label: Token1 symbol: token1 -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -1180,7 +1176,7 @@ _ _: 16 52; :; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -1197,7 +1193,7 @@ _ _: 16 52; .unwrap() .simulate_execute( TransactionArgs { - orderbook_address: *orderbook.address(), + raindex_address: *raindex.address(), rpcs: vec![local_evm.url()], ..Default::default() }, @@ -1211,7 +1207,7 @@ _ _: 16 52; async fn test_simulate_execute_err() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -1242,9 +1238,9 @@ tokens: decimals: 18 label: Token1 symbol: token1 -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -1271,7 +1267,7 @@ _ _: 16 52; :; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -1289,7 +1285,7 @@ _ _: 16 52; .simulate_execute( TransactionArgs { // send the tx to random address - orderbook_address: Address::random(), + raindex_address: Address::random(), rpcs: vec![local_evm.url()], ..Default::default() }, @@ -1384,7 +1380,7 @@ _ _: 16 52; }], network: network_arc.clone(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }; DeploymentCfg { @@ -1726,7 +1722,7 @@ _ _: 0 0; let res = add_order_args .get_add_order_call_parameters(TransactionArgs { rpcs: vec![local_evm.url().to_string()], - orderbook_address: *local_evm.orderbook.address(), + raindex_address: *local_evm.raindex.address(), max_priority_fee_per_gas: Some(100), max_fee_per_gas: Some(200), ..Default::default() @@ -1745,7 +1741,7 @@ _ _: 0 0; ); assert_eq!(res.call.config.meta, add_order_call.config.meta); assert_eq!(res.call.tasks, add_order_call.tasks); - assert_eq!(res.address, *local_evm.orderbook.address()); + assert_eq!(res.address, *local_evm.raindex.address()); assert_eq!(res.max_priority_fee_per_gas, Some(100)); assert_eq!(res.max_fee_per_gas, Some(200)); } diff --git a/crates/common/src/deposit.rs b/crates/common/src/deposit.rs index f49e997cf5..c4ab486e91 100644 --- a/crates/common/src/deposit.rs +++ b/crates/common/src/deposit.rs @@ -8,8 +8,8 @@ use alloy_ethers_typecast::{ use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; use rain_math_float::{Float, FloatError}; #[cfg(not(target_family = "wasm"))] -use rain_orderbook_bindings::IERC20::approveCall; -use rain_orderbook_bindings::{IRaindexV6::deposit4Call, IERC20::allowanceCall}; +use raindex_bindings::IERC20::approveCall; +use raindex_bindings::{IRaindexV6::deposit4Call, IERC20::allowanceCall}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -69,7 +69,7 @@ impl DepositArgs { .address(self.token) .call(allowanceCall { owner, - spender: transaction_args.orderbook_address, + spender: transaction_args.raindex_address, }) .build()?; let res = readable_client.read(parameters).await?; @@ -95,7 +95,7 @@ impl DepositArgs { // If allowance differs from desired amount, overwrite it with the target value if !current_allowance_float.eq(self.amount)? { let approve_call = approveCall { - spender: transaction_args.orderbook_address, + spender: transaction_args.raindex_address, amount: self.amount.to_fixed_decimal(self.decimals)?, }; let params = @@ -109,7 +109,7 @@ impl DepositArgs { Ok(()) } - /// Execute OrderbookV3 deposit call + /// Execute Raindex deposit call #[cfg(not(target_family = "wasm"))] pub async fn execute_deposit)>( &self, @@ -120,7 +120,7 @@ impl DepositArgs { let deposit_call: deposit4Call = self.clone().try_into()?; let params = transaction_args - .try_into_write_contract_parameters(deposit_call, transaction_args.orderbook_address)?; + .try_into_write_contract_parameters(deposit_call, transaction_args.raindex_address)?; WriteTransaction::new(ledger_client, params, 4, transaction_status_changed) .execute() @@ -184,7 +184,7 @@ mod tests { Address::ZERO, TransactionArgs { rpcs: vec![rpc_server.url("/rpc")], - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, ..Default::default() }, ) @@ -197,7 +197,7 @@ mod tests { fn test_deposit_call_try_into_write_contract_parameters() { let args = TransactionArgs { rpcs: vec!["http://test.com".to_string()], - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: Some(0_usize), chain_id: Some(1), max_priority_fee_per_gas: Some(200), @@ -224,7 +224,7 @@ mod tests { fn test_approve_call_try_into_write_contract_parameters() { let args = TransactionArgs { rpcs: vec!["http://test.com".to_string()], - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: Some(0_usize), chain_id: Some(1), max_priority_fee_per_gas: Some(200), diff --git a/crates/common/src/dotrain_add_order_lsp.rs b/crates/common/src/dotrain_add_order_lsp.rs index 98fe16d42f..ab472cc976 100644 --- a/crates/common/src/dotrain_add_order_lsp.rs +++ b/crates/common/src/dotrain_add_order_lsp.rs @@ -1,5 +1,5 @@ #[cfg(not(target_family = "wasm"))] -use crate::add_order::ORDERBOOK_ORDER_ENTRYPOINTS; +use crate::add_order::RAINDEX_ORDER_ENTRYPOINTS; #[cfg(not(target_family = "wasm"))] use crate::rainlang::parse_rainlang_on_fork; #[cfg(not(target_family = "wasm"))] @@ -76,7 +76,7 @@ impl DotrainAddOrderLsp { bindings_problems.extend(top_problems.to_vec()); bindings_problems } else { - let rainlang = match rain_document.compose(&ORDERBOOK_ORDER_ENTRYPOINTS) { + let rainlang = match rain_document.compose(&RAINDEX_ORDER_ENTRYPOINTS) { Ok(v) => v, Err(e) => match e { ComposeError::Reject(msg) => { @@ -123,8 +123,8 @@ impl DotrainAddOrderLsp { #[cfg(all(test, not(target_family = "wasm")))] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_test_fixtures::LocalEvm; use url::Url; fn get_text() -> String { @@ -144,19 +144,19 @@ tokens: orders: flare1: - orderbook: flare + raindex: flare inputs: - token: token1 outputs: - token: token2 flareaaaaa: - orderbook: flare + raindex: flare inputs: - token: token1 outputs: - token: token1 flare2: - orderbook: flare + raindex: flare inputs: - token: token2 outputs: @@ -164,7 +164,7 @@ orders: scenarios: flare: - orderbook: flare + raindex: flare runs: 1 bindings: raindex-subparser: 0xFe2411CDa193D9E4e83A5c234C7Fd320101883aC diff --git a/crates/common/src/dotrain_order.rs b/crates/common/src/dotrain_order.rs index b1e3a0416c..cd6d7e67a1 100644 --- a/crates/common/src/dotrain_order.rs +++ b/crates/common/src/dotrain_order.rs @@ -1,5 +1,5 @@ use crate::{ - add_order::{ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS, ORDERBOOK_ORDER_ENTRYPOINTS}, + add_order::{RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS, RAINDEX_ORDER_ENTRYPOINTS}, rainlang::compose_to_rainlang, }; use alloy::primitives::Address; @@ -8,16 +8,16 @@ use dotrain::{error::ComposeError, types::patterns::FRONTMATTER_SEPARATOR, RainD use futures::future::join_all; use rain_interpreter_parser::{Parser2, ParserError, ParserV2}; pub use rain_metadata::types::authoring::v2::*; -use rain_orderbook_app_settings::yaml::{ - clone_section_entry, context::ContextProfile, dotrain::DotrainYaml, orderbook::OrderbookYaml, +use raindex_app_settings::yaml::{ + clone_section_entry, context::ContextProfile, dotrain::DotrainYaml, raindex::RaindexYaml, FieldErrorKind, YamlError, YamlParsable, }; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, - yaml::{dotrain::DotrainYamlValidation, orderbook::OrderbookYamlValidation}, + yaml::{dotrain::DotrainYamlValidation, raindex::RaindexYamlValidation}, }; -use rain_orderbook_app_settings::{scenario::ScenarioCfg, spec_version::SpecVersion}; +use raindex_app_settings::{scenario::ScenarioCfg, spec_version::SpecVersion}; use serde::{Deserialize, Serialize}; use std::sync::{Arc, RwLock}; use strict_yaml_rust::{strict_yaml::Hash as StrictYamlHash, StrictYaml, StrictYamlLoader}; @@ -25,7 +25,7 @@ use thiserror::Error; use wasm_bindgen_utils::prelude::*; /// DotrainOrder represents a parsed and validated dotrain configuration that combines -/// YAML frontmatter with Rainlang code for orderbook operations. +/// YAML frontmatter with Rainlang code for raindex operations. /// /// A dotrain file contains: /// - YAML frontmatter defining networks, tokens, orders, scenarios, and deployments @@ -313,8 +313,7 @@ impl DotrainOrder { sources.extend(settings); } - let mut orderbook_yaml = - OrderbookYaml::new(sources.clone(), OrderbookYamlValidation::default())?; + let mut raindex_yaml = RaindexYaml::new(sources.clone(), RaindexYamlValidation::default())?; let mut dotrain_yaml = DotrainYaml::new_with_profile( sources.clone(), @@ -322,7 +321,7 @@ impl DotrainOrder { profile, )?; - let remote_data = orderbook_yaml.fetch_remote_data().await?; + let remote_data = raindex_yaml.fetch_remote_data().await?; if !remote_data.remote_networks.is_empty() { dotrain_yaml .cache @@ -396,7 +395,7 @@ impl DotrainOrder { Ok(compose_to_rainlang( self.dotrain.clone(), scenario.bindings.clone(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, )?) } @@ -433,7 +432,7 @@ impl DotrainOrder { Ok(compose_to_rainlang( self.dotrain.clone(), scenario.bindings.clone(), - &ORDERBOOK_ADDORDER_POST_TASK_ENTRYPOINTS, + &RAINDEX_ADDORDER_POST_TASK_ENTRYPOINTS, )?) } @@ -472,7 +471,7 @@ impl DotrainOrder { Ok(compose_to_rainlang( self.dotrain.clone(), scenario.bindings.clone(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, )?) } } @@ -482,8 +481,8 @@ impl DotrainOrder { self.dotrain_yaml.clone() } - pub fn orderbook_yaml(&self) -> OrderbookYaml { - OrderbookYaml::from_dotrain_yaml(self.dotrain_yaml.clone()) + pub fn raindex_yaml(&self) -> RaindexYaml { + RaindexYaml::from_dotrain_yaml(self.dotrain_yaml.clone()) } pub async fn get_pragmas_for_scenario( @@ -519,7 +518,7 @@ impl DotrainOrder { .iter() .map(|rpc| rpc.to_string()) .collect::>(); - let metaboard = self.orderbook_yaml().get_metaboard(&network.key)?.url; + let metaboard = self.raindex_yaml().get_metaboard(&network.key)?.url; Ok(AuthoringMetaV2::fetch_for_contract(address, rpcs, metaboard.to_string()).await?) } @@ -604,7 +603,7 @@ impl DotrainOrder { } pub async fn validate_spec_version(&self) -> Result<(), DotrainOrderError> { - let spec_version = self.orderbook_yaml().get_spec_version()?; + let spec_version = self.raindex_yaml().get_spec_version()?; if !SpecVersion::is_current(&spec_version) { return Err(DotrainOrderError::SpecVersionMismatch( SpecVersion::current(), @@ -620,7 +619,7 @@ impl DotrainOrder { deployment_key: &str, ) -> Result { let dotrain_yaml = self.dotrain_yaml(); - let orderbook_yaml = self.orderbook_yaml(); + let raindex_yaml = self.raindex_yaml(); let deployment = dotrain_yaml.get_deployment(deployment_key)?; let order_cfg = deployment.order.clone(); let scenario_cfg = deployment.scenario.clone(); @@ -628,16 +627,19 @@ impl DotrainOrder { let network_key = order_cfg.network.key.clone(); let rainlang_key = rainlang_cfg.key.clone(); - let orderbook_key = order_cfg.orderbook.as_ref().map(|ob| ob.key.clone()); + let raindex_key = order_cfg + .raindex + .as_ref() + .map(|raindex_cfg| raindex_cfg.key.clone()); let subgraph_key = order_cfg - .orderbook + .raindex .as_ref() - .map(|ob| ob.subgraph.key.clone()); + .map(|raindex_cfg| raindex_cfg.subgraph.key.clone()); let order_key = order_cfg.key.clone(); let deployment_key = deployment.key.clone(); - let metaboard_key = match orderbook_yaml.get_metaboard(&network_key) { + let metaboard_key = match raindex_yaml.get_metaboard(&network_key) { Ok(cfg) => Some(cfg.key.clone()), Err(YamlError::KeyNotFound(_)) => None, Err(YamlError::Field { @@ -649,7 +651,7 @@ impl DotrainOrder { let documents = dotrain_yaml.documents.clone(); - let spec_version = orderbook_yaml.get_spec_version()?; + let spec_version = raindex_yaml.get_spec_version()?; let mut root_hash = StrictYamlHash::new(); root_hash.insert( @@ -675,14 +677,14 @@ impl DotrainOrder { StrictYaml::Hash(rainlangs_hash), ); - if let Some(orderbook_key) = orderbook_key { - let orderbook_value = clone_section_entry(&documents, "orderbooks", &orderbook_key) + if let Some(raindex_key) = raindex_key { + let raindex_value = clone_section_entry(&documents, "raindexes", &raindex_key) .map_err(|err| DotrainOrderError::CleanUnusedFrontmatterError(err.to_string()))?; - let mut orderbooks_hash = StrictYamlHash::new(); - orderbooks_hash.insert(StrictYaml::String(orderbook_key.clone()), orderbook_value); + let mut raindexes_hash = StrictYamlHash::new(); + raindexes_hash.insert(StrictYaml::String(raindex_key.clone()), raindex_value); root_hash.insert( - StrictYaml::String("orderbooks".to_string()), - StrictYaml::Hash(orderbooks_hash), + StrictYaml::String("raindexes".to_string()), + StrictYaml::Hash(raindexes_hash), ); } @@ -867,7 +869,7 @@ mod tests { use alloy::{hex::encode_prefixed, primitives::B256, sol, sol_types::SolValue}; use httpmock::MockServer; use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; - use rain_orderbook_app_settings::yaml::FieldErrorKind; + use raindex_app_settings::yaml::FieldErrorKind; use serde_bytes::ByteBuf; use serde_json::json; use strict_yaml_rust::{strict_yaml::Hash as StrictYamlHash, StrictYaml, StrictYamlLoader}; @@ -928,7 +930,7 @@ _ _: 0 0; assert_eq!( dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_network("polygon") .unwrap() .rpcs @@ -1142,7 +1144,7 @@ rainlangs: polygon: address: 0x1234567890123456789012345678901234567890 network: polygon -orderbooks: +raindexes: primary: address: 0x0101010101010101010101010101010101010101 network: polygon @@ -1163,7 +1165,7 @@ tokens: orders: polygon-order: network: polygon - orderbook: primary + raindex: primary inputs: - token: t1 vault-id: 1 @@ -1204,15 +1206,15 @@ _ _: 0 0; let (frontmatter, _) = split_frontmatter_and_body(&generated); let root = get_root_hash(&frontmatter); - let StrictYaml::Hash(orderbooks) = root - .get(&StrictYaml::String("orderbooks".to_string())) - .expect("orderbooks present") + let StrictYaml::Hash(raindexes) = root + .get(&StrictYaml::String("raindexes".to_string())) + .expect("raindexes present") .clone() else { - panic!("orderbooks not a hash"); + panic!("raindexes not a hash"); }; - assert!(orderbooks.contains_key(&StrictYaml::String("primary".to_string()))); - assert!(!orderbooks.contains_key(&StrictYaml::String("unused".to_string()))); + assert!(raindexes.contains_key(&StrictYaml::String("primary".to_string()))); + assert!(!raindexes.contains_key(&StrictYaml::String("unused".to_string()))); let StrictYaml::Hash(subgraphs) = root .get(&StrictYaml::String("subgraphs".to_string())) @@ -1389,7 +1391,7 @@ networks: assert_eq!( dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_network("mainnet") .unwrap() .rpcs diff --git a/crates/common/src/erc20.rs b/crates/common/src/erc20.rs index 20c5ff36df..1444e85f97 100644 --- a/crates/common/src/erc20.rs +++ b/crates/common/src/erc20.rs @@ -3,9 +3,9 @@ use alloy::primitives::{Address, U256}; use alloy::providers::{MulticallError, Provider}; use alloy_ethers_typecast::ReadContractParametersBuilderError; use rain_error_decoding::{AbiDecodeFailedErrors, AbiDecodedErrorType}; -use rain_orderbook_app_settings::token::TokenCfg; -use rain_orderbook_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; -use rain_orderbook_bindings::IERC20Metadata::IERC20MetadataInstance; +use raindex_app_settings::token::TokenCfg; +use raindex_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; +use raindex_bindings::IERC20Metadata::IERC20MetadataInstance; use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::HashMap; @@ -251,7 +251,7 @@ mod tests { use super::*; use alloy::{hex, sol_types::SolValue}; use httpmock::MockServer; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use serde_json::json; #[tokio::test] diff --git a/crates/common/src/fuzz/impls.rs b/crates/common/src/fuzz/impls.rs index 2f5019ad91..3209decb47 100644 --- a/crates/common/src/fuzz/impls.rs +++ b/crates/common/src/fuzz/impls.rs @@ -1,5 +1,5 @@ use super::*; -use crate::add_order::ORDERBOOK_ORDER_ENTRYPOINTS; +use crate::add_order::RAINDEX_ORDER_ENTRYPOINTS; use alloy::primitives::private::rand; use alloy::primitives::Address; use alloy::primitives::B256; @@ -21,14 +21,14 @@ use rain_interpreter_eval::eval::ForkParseArgs; use rain_interpreter_eval::fork::{Forker, NewForkedEvm}; pub use rain_interpreter_eval::trace::{RainEvalResult, RainEvalResults, TraceSearchError}; use rain_interpreter_eval::{error::ForkCallError, eval::ForkEvalArgs}; -use rain_orderbook_app_settings::blocks::BlockError; -use rain_orderbook_app_settings::scenario::ScenarioCfg; -use rain_orderbook_app_settings::yaml::dotrain::DotrainYamlValidation; -use rain_orderbook_app_settings::{ +use raindex_app_settings::blocks::BlockError; +use raindex_app_settings::scenario::ScenarioCfg; +use raindex_app_settings::yaml::dotrain::DotrainYamlValidation; +use raindex_app_settings::{ order::OrderIOCfg, yaml::{dotrain::DotrainYaml, YamlError, YamlParsable}, }; -use rain_orderbook_bindings::IERC20Metadata; +use raindex_bindings::IERC20Metadata; use std::collections::HashMap; use std::sync::Arc; use thiserror::Error; @@ -286,13 +286,13 @@ impl FuzzRunner { let rainlang_string = RainDocument::compose_text( &dotrain, - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, None, Some(final_bindings), )?; // Create a 5x5 grid of zero values for context - later we'll - // replace these with sane values based on Orderbook context + // replace these with sane values based on Raindex context let mut context = vec![vec![U256::from(0); 5]; 5]; // set random hash for context order hash cell context[1][0] = rand::random(); @@ -439,14 +439,14 @@ impl FuzzRunner { let rainlang_string = RainDocument::compose_text( &dotrain, - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, None, Some(final_bindings), ) .map_err(FuzzRunnerError::ComposeError)?; // Create a 5x5 grid of zero values for context - later we'll - // replace these with sane values based on Orderbook context + // replace these with sane values based on Raindex context let mut context = vec![vec![B256::ZERO; 5]; 5]; // set random hash for context order hash cell context[1][0] = rand::random(); @@ -731,8 +731,8 @@ impl FuzzRunner { mod tests { use super::*; use alloy::providers::{ext::AnvilApi, Provider}; - use rain_orderbook_app_settings::{spec_version::SpecVersion, yaml::FieldErrorKind}; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::{spec_version::SpecVersion, yaml::FieldErrorKind}; + use raindex_test_fixtures::LocalEvm; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] async fn test_fuzz_runner_missing_spec_version() { @@ -1236,7 +1236,7 @@ scenarios: rainlang: flare runs: 1 bindings: - orderbook-subparser: {orderbook_subparser} + raindex-subparser: {raindex_subparser} orders: sell-wflr: network: flare @@ -1251,9 +1251,9 @@ deployments: order: sell-wflr scenario: flare --- -#orderbook-subparser ! +#raindex-subparser ! #calculate-io -using-words-from orderbook-subparser +using-words-from raindex-subparser _: input-token(), _: input-token-decimals(), _: input-vault-id(), @@ -1274,7 +1274,7 @@ _: 30; :;"#, rpc_url = local_evm.url(), rainlang_address = local_evm.rainlang, - orderbook_subparser = local_evm.orderbook_subparser.address(), + raindex_subparser = local_evm.raindex_subparser.address(), wflr_address = wflr_address, usdce_address = usdce_address, spec_version = SpecVersion::current() diff --git a/crates/common/src/fuzz/mod.rs b/crates/common/src/fuzz/mod.rs index bc7a0233e3..bf03ffabf9 100644 --- a/crates/common/src/fuzz/mod.rs +++ b/crates/common/src/fuzz/mod.rs @@ -1,5 +1,5 @@ pub use rain_interpreter_eval::trace::*; -use rain_orderbook_app_settings::chart::ChartCfg; +use raindex_app_settings::chart::ChartCfg; use serde::{Deserialize, Serialize}; use std::collections::HashMap; diff --git a/crates/common/src/local_db/address_collectors.rs b/crates/common/src/local_db/address_collectors.rs index 7ea765fbea..a6c42e0504 100644 --- a/crates/common/src/local_db/address_collectors.rs +++ b/crates/common/src/local_db/address_collectors.rs @@ -1,6 +1,6 @@ use super::decode::{DecodedEvent, DecodedEventData}; use alloy::primitives::Address; -use rain_orderbook_bindings::IRaindexV6::OrderV4; +use raindex_bindings::IRaindexV6::OrderV4; use std::collections::BTreeSet; pub fn collect_token_addresses( @@ -67,8 +67,8 @@ mod tests { use super::super::decode::InterpreterStoreSetEvent; use super::*; use alloy::primitives::{b256, Address, Bytes, FixedBytes, U256}; - use rain_orderbook_bindings::IInterpreterStoreV3::Set; - use rain_orderbook_bindings::IRaindexV6::{ + use raindex_bindings::IInterpreterStoreV3::Set; + use raindex_bindings::IRaindexV6::{ AddOrderV3, DepositV2, OrderV4, RemoveOrderV3, SignedContextV1, TakeOrderConfigV4, TakeOrderV3, WithdrawV2, IOV2, }; @@ -90,7 +90,7 @@ mod tests { OrderV4 { owner: Address::from([1u8; 20]), nonce: U256::from(1).into(), - evaluable: rain_orderbook_bindings::IRaindexV6::EvaluableV4 { + evaluable: raindex_bindings::IRaindexV6::EvaluableV4 { interpreter: Address::from([2u8; 20]), store: Address::from([3u8; 20]), bytecode: alloy::primitives::Bytes::from(vec![]), @@ -172,11 +172,11 @@ mod tests { vaultId: U256::from(0).into(), }); - let clear = rain_orderbook_bindings::IRaindexV6::ClearV3 { + let clear = raindex_bindings::IRaindexV6::ClearV3 { sender: Address::from([0u8; 20]), alice, bob, - clearConfig: rain_orderbook_bindings::IRaindexV6::ClearConfigV2 { + clearConfig: raindex_bindings::IRaindexV6::ClearConfigV2 { aliceInputIOIndex: U256::from(0), aliceOutputIOIndex: U256::from(0), bobInputIOIndex: U256::from(0), diff --git a/crates/common/src/local_db/decode.rs b/crates/common/src/local_db/decode.rs index 51e4581c93..1661faa23c 100644 --- a/crates/common/src/local_db/decode.rs +++ b/crates/common/src/local_db/decode.rs @@ -5,12 +5,12 @@ use alloy::{ sol_types::{abi::token::WordToken, SolEvent}, }; use core::convert::TryFrom; -use rain_orderbook_bindings::{ +use raindex_bindings::{ IInterpreterStoreV3::Set, IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, RemoveOrderV3, TakeOrderV3, WithdrawV2, }, - OrderBook::MetaV1_2, + Raindex::MetaV1_2, }; use serde::{Deserialize, Serialize}; @@ -209,13 +209,13 @@ mod test_helpers { use crate::rpc_client::LogEntryResponse; use alloy::hex; use alloy::primitives::{address, b256, Address, Bytes, FixedBytes, B256, U256}; - use rain_orderbook_bindings::{ + use raindex_bindings::{ IRaindexV6::{ AddOrderV3, AfterClearV2, ClearConfigV2, ClearStateChangeV2, ClearV3, DepositV2, RemoveOrderV3, SignedContextV1, TakeOrderConfigV4, TakeOrderV3, WithdrawV2, }, IRaindexV6::{EvaluableV4, OrderV4, IOV2}, - OrderBook::MetaV1_2, + Raindex::MetaV1_2, }; use serde_json::Value; use std::str::FromStr; diff --git a/crates/common/src/local_db/export.rs b/crates/common/src/local_db/export.rs index 6ce236fb3d..e9e988dfdc 100644 --- a/crates/common/src/local_db/export.rs +++ b/crates/common/src/local_db/export.rs @@ -8,7 +8,7 @@ use serde::Deserialize; use serde_json::Value; use thiserror::Error; -use super::OrderbookIdentifier; +use super::RaindexIdentifier; const SKIPPED_TABLES: &[&str] = &["db_metadata", "sync_status"]; @@ -25,23 +25,23 @@ pub enum ExportError { #[error("Row is missing expected column '{column}'")] MissingColumn { column: String }, - #[error("Missing target_watermarks row for chain {chain_id} orderbook {orderbook_address}")] + #[error("Missing target_watermarks row for chain {chain_id} raindex {raindex_address}")] MissingTargetWatermark { chain_id: u32, - orderbook_address: Address, + raindex_address: Address, }, } -/// Export all data rows for a specific `(chain_id, orderbook_address)` from the +/// Export all data rows for a specific `(chain_id, raindex_address)` from the /// local database as a SQL string containing data-only `INSERT` statements. /// /// Returns `Ok(None)` when no matching rows are found. /// -/// Tables that do not include both `chain_id` and `orderbook_address` columns, +/// Tables that do not include both `chain_id` and `raindex_address` columns, /// or that are explicitly skipped via [`SKIPPED_TABLES`], are ignored. pub async fn export_data_only( executor: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result, LocalDbError> where E: LocalDbQueryExecutor + ?Sized, @@ -60,7 +60,7 @@ where continue; } - let select_stmt = build_select_statement(table, &columns, ob_id); + let select_stmt = build_select_statement(table, &columns, raindex_id); let rows: Vec = executor .query_json(&select_stmt) .await @@ -104,16 +104,16 @@ fn has_target_filters(columns: &[TableInfoRow]) -> bool { let has_chain = columns .iter() .any(|col| col.name.eq_ignore_ascii_case("chain_id")); - let has_orderbook = columns + let has_raindex = columns .iter() - .any(|col| col.name.eq_ignore_ascii_case("orderbook_address")); - has_chain && has_orderbook + .any(|col| col.name.eq_ignore_ascii_case("raindex_address")); + has_chain && has_raindex } fn build_select_statement( table: &str, columns: &[TableInfoRow], - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> SqlStatement { let columns_sql = columns.iter().map(|c| format!("\"{}\"", c.name)).join(", "); @@ -126,9 +126,9 @@ fn build_select_statement( } if columns .iter() - .any(|c| c.name.eq_ignore_ascii_case("orderbook_address")) + .any(|c| c.name.eq_ignore_ascii_case("raindex_address")) { - order_columns.push("\"orderbook_address\"".to_string()); + order_columns.push("\"raindex_address\"".to_string()); } for column in columns { @@ -140,10 +140,10 @@ fn build_select_statement( let order_clause = order_columns.join(", "); let mut stmt = SqlStatement::new(format!( - "SELECT {columns_sql} FROM \"{table}\" WHERE chain_id = ?1 AND orderbook_address = ?2 ORDER BY {order_clause};" + "SELECT {columns_sql} FROM \"{table}\" WHERE chain_id = ?1 AND raindex_address = ?2 ORDER BY {order_clause};" )); - stmt.push(SqlValue::from(ob_id.chain_id as u64)); - stmt.push(SqlValue::from(ob_id.orderbook_address)); + stmt.push(SqlValue::from(raindex_id.chain_id as u64)); + stmt.push(SqlValue::from(raindex_id.raindex_address)); stmt } @@ -351,7 +351,7 @@ mod tests { struct TestTarget { chain_id: i64, - orderbook: Address, + raindex: Address, label: &'static str, } @@ -359,17 +359,17 @@ mod tests { let specs = [ TestTarget { chain_id: 42161, - orderbook: Address::from_str("0x0000000000000000000000000000000000000aaa").unwrap(), + raindex: Address::from_str("0x0000000000000000000000000000000000000aaa").unwrap(), label: "main", }, TestTarget { chain_id: 42161, - orderbook: Address::from_str("0x0000000000000000000000000000000000000bbb").unwrap(), + raindex: Address::from_str("0x0000000000000000000000000000000000000bbb").unwrap(), label: "alt", }, TestTarget { chain_id: 10, - orderbook: Address::from_str("0x0000000000000000000000000000000000000ccc").unwrap(), + raindex: Address::from_str("0x0000000000000000000000000000000000000ccc").unwrap(), label: "other", }, ]; @@ -381,14 +381,14 @@ mod tests { fn insert_for_target(conn: &Connection, target: &TestTarget, base_idx: i64) { let chain = target.chain_id; - let orderbook = encode_prefixed(target.orderbook); + let raindex = encode_prefixed(target.raindex); let label = target.label; let raw_tx = format!("raw_tx_{label}"); conn.execute( r#"INSERT INTO raw_events ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -411,7 +411,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), raw_tx, base_idx, 1000 + base_idx, @@ -428,7 +428,7 @@ mod tests { conn.execute( r#"INSERT INTO deposits ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -453,7 +453,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), deposit_tx, base_idx + 1, 1000 + base_idx + 1, @@ -471,7 +471,7 @@ mod tests { conn.execute( r#"INSERT INTO withdrawals ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -498,7 +498,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), withdraw_tx, base_idx + 2, 1000 + base_idx + 2, @@ -517,7 +517,7 @@ mod tests { conn.execute( r#"INSERT INTO order_events ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -548,7 +548,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), order_tx, base_idx + 3, 1000 + base_idx + 3, @@ -568,7 +568,7 @@ mod tests { conn.execute( r#"INSERT INTO order_ios ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, io_index, @@ -587,7 +587,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), order_tx, base_idx + 3, 0, @@ -602,7 +602,7 @@ mod tests { conn.execute( r#"INSERT INTO take_orders ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -631,7 +631,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), take_tx, base_idx + 4, 1000 + base_idx + 4, @@ -650,7 +650,7 @@ mod tests { conn.execute( r#"INSERT INTO take_order_contexts ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index, @@ -665,7 +665,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), take_tx, base_idx + 4, 0, @@ -677,7 +677,7 @@ mod tests { conn.execute( r#"INSERT INTO context_values ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index, @@ -694,7 +694,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), take_tx, base_idx + 4, 0, @@ -708,7 +708,7 @@ mod tests { conn.execute( r#"INSERT INTO clear_v3_events ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -753,7 +753,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), clear_tx, base_idx + 5, 1000 + base_idx + 5, @@ -780,7 +780,7 @@ mod tests { conn.execute( r#"INSERT INTO after_clear_v2_events ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -805,7 +805,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), clear_tx, base_idx + 6, 1000 + base_idx + 6, @@ -823,7 +823,7 @@ mod tests { conn.execute( r#"INSERT INTO meta_events ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, block_number, @@ -844,7 +844,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), meta_tx, base_idx + 7, 1000 + base_idx + 7, @@ -859,7 +859,7 @@ mod tests { conn.execute( r#"INSERT INTO erc20_tokens ( chain_id, - orderbook_address, + raindex_address, token_address, name, symbol, @@ -874,7 +874,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), format!("token_addr_{label}"), format!("Token {label}"), format!("SYM{label}"), @@ -887,7 +887,7 @@ mod tests { conn.execute( r#"INSERT INTO interpreter_store_sets ( chain_id, - orderbook_address, + raindex_address, store_address, transaction_hash, log_index, @@ -910,7 +910,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), format!("store_addr_{label}"), store_tx, base_idx + 8, @@ -926,7 +926,7 @@ mod tests { conn.execute( r#"INSERT INTO target_watermarks ( chain_id, - orderbook_address, + raindex_address, last_block, last_hash, updated_at @@ -939,7 +939,7 @@ mod tests { );"#, params![ chain, - orderbook.as_str(), + raindex.as_str(), 2_000 + base_idx, format!("hash_{label}"), 1_700_000_000_000i64 + base_idx * 1_000, @@ -951,19 +951,19 @@ mod tests { #[tokio::test] async fn export_includes_only_targeted_rows() { let executor = TestExecutor::new(); - let main_target = OrderbookIdentifier { + let main_target = RaindexIdentifier { chain_id: 42161, - orderbook_address: Address::from_str("0x0000000000000000000000000000000000000aaa") + raindex_address: Address::from_str("0x0000000000000000000000000000000000000aaa") .unwrap(), }; - let alt_target = OrderbookIdentifier { + let alt_target = RaindexIdentifier { chain_id: 42161, - orderbook_address: Address::from_str("0x0000000000000000000000000000000000000bbb") + raindex_address: Address::from_str("0x0000000000000000000000000000000000000bbb") .unwrap(), }; - let other_target = OrderbookIdentifier { + let other_target = RaindexIdentifier { chain_id: 10, - orderbook_address: Address::from_str("0x0000000000000000000000000000000000000ccc") + raindex_address: Address::from_str("0x0000000000000000000000000000000000000ccc") .unwrap(), }; @@ -980,9 +980,9 @@ mod tests { .unwrap() .expect("other target should have rows"); - let expected_main = expected_dump(42161, main_target.orderbook_address, "main", 10); - let expected_alt = expected_dump(42161, alt_target.orderbook_address, "alt", 20); - let expected_other = expected_dump(10, other_target.orderbook_address, "other", 30); + let expected_main = expected_dump(42161, main_target.raindex_address, "main", 10); + let expected_alt = expected_dump(42161, alt_target.raindex_address, "alt", 20); + let expected_other = expected_dump(10, other_target.raindex_address, "other", 30); let norm = |s: &str| normalize_sql(s).to_lowercase(); assert_eq!(norm(&sql_main), norm(&expected_main), "main dump mismatch"); @@ -997,13 +997,13 @@ mod tests { #[tokio::test] async fn export_returns_none_when_no_rows() { let executor = TestExecutor::new(); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 1, - orderbook_address: Address::from_str("0x0000000000000000000000000000000000000ddd") + raindex_address: Address::from_str("0x0000000000000000000000000000000000000ddd") .unwrap(), }; - let export = export_data_only(&executor, &ob_id).await.unwrap(); + let export = export_data_only(&executor, &raindex_id).await.unwrap(); assert!( export.is_none(), "expected None when there are no rows for the target" @@ -1013,12 +1013,12 @@ mod tests { #[test] fn export_omits_skipped_tables() { let executor = TestExecutor::new(); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, - orderbook_address: Address::from_str("0x0000000000000000000000000000000000000aaa") + raindex_address: Address::from_str("0x0000000000000000000000000000000000000aaa") .unwrap(), }; - let orderbook = encode_prefixed(ob_id.orderbook_address); + let raindex = encode_prefixed(raindex_id.raindex_address); { let conn = executor.conn.lock().unwrap(); @@ -1028,16 +1028,16 @@ mod tests { ) .expect("insert db_metadata row"); conn.execute( - "INSERT INTO sync_status (chain_id, orderbook_address, last_synced_block) VALUES (?1, ?2, ?3);", - params![ob_id.chain_id as i64, orderbook.as_str(), 456_i64], + "INSERT INTO sync_status (chain_id, raindex_address, last_synced_block) VALUES (?1, ?2, ?3);", + params![raindex_id.chain_id as i64, raindex.as_str(), 456_i64], ) .expect("insert sync_status row"); } - let sql = executor::block_on(export_data_only(&executor, &ob_id)) + let sql = executor::block_on(export_data_only(&executor, &raindex_id)) .unwrap() .expect("target should have rows"); - let expected = expected_dump(42161, ob_id.orderbook_address, "main", 10); + let expected = expected_dump(42161, raindex_id.raindex_address, "main", 10); assert_eq!( normalize_sql(&sql), @@ -1058,43 +1058,39 @@ mod tests { #[test] fn has_target_filters_detects_required_columns() { - let columns = vec![ - column("chain_id"), - column("orderbook_address"), - column("foo"), - ]; + let columns = vec![column("chain_id"), column("raindex_address"), column("foo")]; assert!(has_target_filters(&columns)); - let missing_orderbook = vec![column("chain_id"), column("foo")]; - assert!(!has_target_filters(&missing_orderbook)); + let missing_raindex = vec![column("chain_id"), column("foo")]; + assert!(!has_target_filters(&missing_raindex)); - let missing_chain = vec![column("orderbook_address"), column("foo")]; + let missing_chain = vec![column("raindex_address"), column("foo")]; assert!(!has_target_filters(&missing_chain)); } #[test] fn build_select_statement_orders_columns_and_params() { let columns = vec![ - column("orderbook_address"), + column("raindex_address"), column("chain_id"), column("alpha"), column("beta"), ]; - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, - orderbook_address: Address::from_str("0x00112233445566778899aabbccddeeff00112233") + raindex_address: Address::from_str("0x00112233445566778899aabbccddeeff00112233") .unwrap(), }; - let stmt = build_select_statement("deposits", &columns, &ob_id); + let stmt = build_select_statement("deposits", &columns, &raindex_id); assert_eq!( stmt.sql(), - "SELECT \"orderbook_address\", \"chain_id\", \"alpha\", \"beta\" FROM \"deposits\" WHERE chain_id = ?1 AND orderbook_address = ?2 ORDER BY \"chain_id\", \"orderbook_address\", \"alpha\", \"beta\";" + "SELECT \"raindex_address\", \"chain_id\", \"alpha\", \"beta\" FROM \"deposits\" WHERE chain_id = ?1 AND raindex_address = ?2 ORDER BY \"chain_id\", \"raindex_address\", \"alpha\", \"beta\";" ); let params = stmt.params(); assert_eq!(params.len(), 2); - assert_eq!(params[0], SqlValue::from(ob_id.chain_id as u64)); - assert_eq!(params[1], SqlValue::from(ob_id.orderbook_address)); + assert_eq!(params[0], SqlValue::from(raindex_id.chain_id as u64)); + assert_eq!(params[1], SqlValue::from(raindex_id.raindex_address)); } #[test] @@ -1164,7 +1160,7 @@ mod tests { } } - fn expected_dump(chain_id: u32, orderbook: Address, label: &str, base_idx: i64) -> String { + fn expected_dump(chain_id: u32, raindex: Address, label: &str, base_idx: i64) -> String { let base = base_idx; let dep_idx = base + 1; let with_idx = base + 2; @@ -1179,25 +1175,25 @@ mod tests { let ts = |offset: i64| 1_700_000_000 + offset; let meta_hex = format!("0x{}", hex::encode(label.as_bytes())); - let orderbook = encode_prefixed(orderbook); + let raindex = encode_prefixed(raindex); let watermark_block = 2_000 + base_idx; let watermark_ms = 1_700_000_000_000i64 + base_idx * 1_000; let mut out = String::from("BEGIN;\n"); out.push_str(&format!( - "INSERT INTO \"target_watermarks\" (\"chain_id\", \"orderbook_address\", \"last_block\", \"last_hash\", \"updated_at\") VALUES ({}, '{}', {}, 'hash_{}', {});\n", + "INSERT INTO \"target_watermarks\" (\"chain_id\", \"raindex_address\", \"last_block\", \"last_hash\", \"updated_at\") VALUES ({}, '{}', {}, 'hash_{}', {});\n", chain_id, - orderbook, + raindex, watermark_block, label, watermark_ms )); out.push_str(&format!( - "INSERT INTO \"raw_events\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"address\", \"topics\", \"data\", \"raw_json\") VALUES ({}, '{}', 'raw_tx_{}', {}, {}, {}, 'address_{}', '[\"topic_{}\"]', 'data_{}', '{{\"event\":\"raw_{}\"}}');\n", + "INSERT INTO \"raw_events\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"address\", \"topics\", \"data\", \"raw_json\") VALUES ({}, '{}', 'raw_tx_{}', {}, {}, {}, 'address_{}', '[\"topic_{}\"]', 'data_{}', '{{\"event\":\"raw_{}\"}}');\n", chain_id, - orderbook, + raindex, label, base, block(base), @@ -1209,9 +1205,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"deposits\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"token\", \"vault_id\", \"deposit_amount\", \"deposit_amount_uint256\") VALUES ({}, '{}', 'dep_tx_{}', {}, {}, {}, 'sender_{}', 'token_{}', 'vault_{}', 'amount_{}', 'uint_{}');\n", + "INSERT INTO \"deposits\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"token\", \"vault_id\", \"deposit_amount\", \"deposit_amount_uint256\") VALUES ({}, '{}', 'dep_tx_{}', {}, {}, {}, 'sender_{}', 'token_{}', 'vault_{}', 'amount_{}', 'uint_{}');\n", chain_id, - orderbook, + raindex, label, dep_idx, block(dep_idx), @@ -1224,9 +1220,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"withdrawals\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"token\", \"vault_id\", \"target_amount\", \"withdraw_amount\", \"withdraw_amount_uint256\") VALUES ({}, '{}', 'with_tx_{}', {}, {}, {}, 'withdraw_sender_{}', 'withdraw_token_{}', 'withdraw_vault_{}', 'target_amount_{}', 'withdraw_amount_{}', 'withdraw_uint_{}');\n", + "INSERT INTO \"withdrawals\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"token\", \"vault_id\", \"target_amount\", \"withdraw_amount\", \"withdraw_amount_uint256\") VALUES ({}, '{}', 'with_tx_{}', {}, {}, {}, 'withdraw_sender_{}', 'withdraw_token_{}', 'withdraw_vault_{}', 'target_amount_{}', 'withdraw_amount_{}', 'withdraw_uint_{}');\n", chain_id, - orderbook, + raindex, label, with_idx, block(with_idx), @@ -1240,9 +1236,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"order_events\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"interpreter_address\", \"store_address\", \"order_hash\", \"event_type\", \"order_owner\", \"order_nonce\", \"order_bytes\") VALUES ({}, '{}', 'order_tx_{}', {}, {}, {}, 'order_sender_{}', 'interp_{}', 'store_{}', 'order_hash_{}', 'event_{}', 'order_owner_{}', 'order_nonce_{}', 'order_bytes_{}');\n", + "INSERT INTO \"order_events\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"interpreter_address\", \"store_address\", \"order_hash\", \"event_type\", \"order_owner\", \"order_nonce\", \"order_bytes\") VALUES ({}, '{}', 'order_tx_{}', {}, {}, {}, 'order_sender_{}', 'interp_{}', 'store_{}', 'order_hash_{}', 'event_{}', 'order_owner_{}', 'order_nonce_{}', 'order_bytes_{}');\n", chain_id, - orderbook, + raindex, label, order_idx, block(order_idx), @@ -1258,9 +1254,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"order_ios\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"io_index\", \"io_type\", \"token\", \"vault_id\") VALUES ({}, '{}', 'order_tx_{}', {}, 0, 'io_type_{}', 'io_token_{}', 'io_vault_{}');\n", + "INSERT INTO \"order_ios\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"io_index\", \"io_type\", \"token\", \"vault_id\") VALUES ({}, '{}', 'order_tx_{}', {}, 0, 'io_type_{}', 'io_token_{}', 'io_vault_{}');\n", chain_id, - orderbook, + raindex, label, order_idx, label, @@ -1269,9 +1265,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"take_orders\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"order_owner\", \"order_nonce\", \"input_io_index\", \"output_io_index\", \"taker_input\", \"taker_output\") VALUES ({}, '{}', 'take_tx_{}', {}, {}, {}, 'taker_{}', 'taker_owner_{}', 'taker_nonce_{}', 0, 1, 'taker_input_{}', 'taker_output_{}');\n", + "INSERT INTO \"take_orders\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"order_owner\", \"order_nonce\", \"input_io_index\", \"output_io_index\", \"taker_input\", \"taker_output\") VALUES ({}, '{}', 'take_tx_{}', {}, {}, {}, 'taker_{}', 'taker_owner_{}', 'taker_nonce_{}', 0, 1, 'taker_input_{}', 'taker_output_{}');\n", chain_id, - orderbook, + raindex, label, take_idx, block(take_idx), @@ -1284,27 +1280,27 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"take_order_contexts\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"context_index\", \"context_value\") VALUES ({}, '{}', 'take_tx_{}', {}, 0, 'context_entry_{}');\n", + "INSERT INTO \"take_order_contexts\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"context_index\", \"context_value\") VALUES ({}, '{}', 'take_tx_{}', {}, 0, 'context_entry_{}');\n", chain_id, - orderbook, + raindex, label, take_idx, label )); out.push_str(&format!( - "INSERT INTO \"context_values\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"context_index\", \"value_index\", \"value\") VALUES ({}, '{}', 'take_tx_{}', {}, 0, 0, 'context_value_{}');\n", + "INSERT INTO \"context_values\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"context_index\", \"value_index\", \"value\") VALUES ({}, '{}', 'take_tx_{}', {}, 0, 0, 'context_value_{}');\n", chain_id, - orderbook, + raindex, label, take_idx, label )); out.push_str(&format!( - "INSERT INTO \"clear_v3_events\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"alice_order_hash\", \"alice_order_owner\", \"alice_input_io_index\", \"alice_output_io_index\", \"alice_bounty_vault_id\", \"alice_input_vault_id\", \"alice_output_vault_id\", \"bob_order_hash\", \"bob_order_owner\", \"bob_input_io_index\", \"bob_output_io_index\", \"bob_bounty_vault_id\", \"bob_input_vault_id\", \"bob_output_vault_id\") VALUES ({}, '{}', 'clear_tx_{}', {}, {}, {}, 'clear_sender_{}', 'alice_hash_{}', 'alice_owner_{}', 0, 1, 'alice_bounty_{}', 'alice_input_{}', 'alice_output_{}', 'bob_hash_{}', 'bob_owner_{}', 2, 3, 'bob_bounty_{}', 'bob_input_{}', 'bob_output_{}');\n", + "INSERT INTO \"clear_v3_events\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"alice_order_hash\", \"alice_order_owner\", \"alice_input_io_index\", \"alice_output_io_index\", \"alice_bounty_vault_id\", \"alice_input_vault_id\", \"alice_output_vault_id\", \"bob_order_hash\", \"bob_order_owner\", \"bob_input_io_index\", \"bob_output_io_index\", \"bob_bounty_vault_id\", \"bob_input_vault_id\", \"bob_output_vault_id\") VALUES ({}, '{}', 'clear_tx_{}', {}, {}, {}, 'clear_sender_{}', 'alice_hash_{}', 'alice_owner_{}', 0, 1, 'alice_bounty_{}', 'alice_input_{}', 'alice_output_{}', 'bob_hash_{}', 'bob_owner_{}', 2, 3, 'bob_bounty_{}', 'bob_input_{}', 'bob_output_{}');\n", chain_id, - orderbook, + raindex, label, clear_idx, block(clear_idx), @@ -1323,9 +1319,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"after_clear_v2_events\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"alice_output\", \"bob_output\", \"alice_input\", \"bob_input\") VALUES ({}, '{}', 'clear_tx_{}', {}, {}, {}, 'after_sender_{}', 'alice_output_amount_{}', 'bob_output_amount_{}', 'alice_input_amount_{}', 'bob_input_amount_{}');\n", + "INSERT INTO \"after_clear_v2_events\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"alice_output\", \"bob_output\", \"alice_input\", \"bob_input\") VALUES ({}, '{}', 'clear_tx_{}', {}, {}, {}, 'after_sender_{}', 'alice_output_amount_{}', 'bob_output_amount_{}', 'alice_input_amount_{}', 'bob_input_amount_{}');\n", chain_id, - orderbook, + raindex, label, after_idx, block(after_idx), @@ -1338,9 +1334,9 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"meta_events\" (\"chain_id\", \"orderbook_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"subject\", \"meta\") VALUES ({}, '{}', 'meta_tx_{}', {}, {}, {}, 'meta_sender_{}', 'subject_{}', '{}');\n", + "INSERT INTO \"meta_events\" (\"chain_id\", \"raindex_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"sender\", \"subject\", \"meta\") VALUES ({}, '{}', 'meta_tx_{}', {}, {}, {}, 'meta_sender_{}', 'subject_{}', '{}');\n", chain_id, - orderbook, + raindex, label, meta_idx, block(meta_idx), @@ -1351,18 +1347,18 @@ mod tests { )); out.push_str(&format!( - "INSERT INTO \"erc20_tokens\" (\"chain_id\", \"orderbook_address\", \"token_address\", \"name\", \"symbol\", \"decimals\") VALUES ({}, '{}', 'token_addr_{}', 'Token {}', 'SYM{}', 18);\n", + "INSERT INTO \"erc20_tokens\" (\"chain_id\", \"raindex_address\", \"token_address\", \"name\", \"symbol\", \"decimals\") VALUES ({}, '{}', 'token_addr_{}', 'Token {}', 'SYM{}', 18);\n", chain_id, - orderbook, + raindex, label, label, label )); out.push_str(&format!( - "INSERT INTO \"interpreter_store_sets\" (\"chain_id\", \"orderbook_address\", \"store_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"namespace\", \"key\", \"value\") VALUES ({}, '{}', 'store_addr_{}', 'store_tx_{}', {}, {}, {}, 'store_namespace_{}', 'store_key_{}', 'store_value_{}');\n", + "INSERT INTO \"interpreter_store_sets\" (\"chain_id\", \"raindex_address\", \"store_address\", \"transaction_hash\", \"log_index\", \"block_number\", \"block_timestamp\", \"namespace\", \"key\", \"value\") VALUES ({}, '{}', 'store_addr_{}', 'store_tx_{}', {}, {}, {}, 'store_namespace_{}', 'store_key_{}', 'store_value_{}');\n", chain_id, - orderbook, + raindex, label, label, store_idx, diff --git a/crates/common/src/local_db/fetch.rs b/crates/common/src/local_db/fetch.rs index cb35b7de70..d4c485e5e2 100644 --- a/crates/common/src/local_db/fetch.rs +++ b/crates/common/src/local_db/fetch.rs @@ -6,7 +6,7 @@ use crate::{ use alloy::primitives::{Address, U256}; use alloy::rpc::types::Filter; use futures::{StreamExt, TryStreamExt}; -use rain_orderbook_bindings::topics::{ORDERBOOK_EVENT_TOPICS, STORE_SET_TOPICS}; +use raindex_bindings::topics::{RAINDEX_EVENT_TOPICS, STORE_SET_TOPICS}; use std::collections::{HashMap, HashSet}; use thiserror::Error; @@ -140,7 +140,7 @@ async fn collect_logs( Ok(events) } -pub async fn fetch_orderbook_events( +pub async fn fetch_raindex_events( rpc_client: &RpcClient, address: Address, from_block: u64, @@ -151,7 +151,7 @@ pub async fn fetch_orderbook_events( .address(address) .from_block(from_block) .to_block(to_block) - .event_signature(ORDERBOOK_EVENT_TOPICS.to_vec()); + .event_signature(RAINDEX_EVENT_TOPICS.to_vec()); collect_logs(rpc_client, &filter, config).await } @@ -443,7 +443,7 @@ mod tests { use alloy::rpc::types::FilterBlockError; use alloy::sol_types::SolEvent; use httpmock::prelude::*; - use rain_orderbook_bindings::{IInterpreterStoreV3::Set, IRaindexV6::AddOrderV3}; + use raindex_bindings::{IInterpreterStoreV3::Set, IRaindexV6::AddOrderV3}; use serde_json::json; use std::str::FromStr; use std::sync::atomic::{AtomicUsize, Ordering}; @@ -523,7 +523,7 @@ mod tests { } #[tokio::test] - async fn fetch_orderbook_events_fetches_and_sorts() { + async fn fetch_raindex_events_fetches_and_sorts() { let server = MockServer::start(); let response_body = json!({ @@ -590,7 +590,7 @@ mod tests { }); let addr = Address::from_str("0x0000000000000000000000000000000000000abc").unwrap(); - let events = fetch_orderbook_events( + let events = fetch_raindex_events( &RpcClient::new_with_urls(vec![Url::parse(&server.url("/")).unwrap()]).unwrap(), addr, 1, @@ -757,10 +757,10 @@ mod tests { } #[tokio::test] - async fn fetch_orderbook_events_returns_error_for_inverted_range() { + async fn fetch_raindex_events_returns_error_for_inverted_range() { let addr = Address::from_str("0x0000000000000000000000000000000000000abc").unwrap(); let err = - fetch_orderbook_events(&RpcClient::mock(), addr, 10, 1, &FetchConfig::default()) + fetch_raindex_events(&RpcClient::mock(), addr, 10, 1, &FetchConfig::default()) .await .unwrap_err(); match err { @@ -776,7 +776,7 @@ mod tests { } #[tokio::test] - async fn fetch_orderbook_events_sorts_numeric_log_index_within_block() { + async fn fetch_raindex_events_sorts_numeric_log_index_within_block() { let server = MockServer::start(); let response_body = json!({ @@ -846,7 +846,7 @@ mod tests { let addr = Address::from_str("0x0000000000000000000000000000000000000abc").unwrap(); - let events = fetch_orderbook_events( + let events = fetch_raindex_events( &RpcClient::new_with_urls(vec![Url::parse(&server.url("/")).unwrap()]).unwrap(), addr, 1, diff --git a/crates/common/src/local_db/insert.rs b/crates/common/src/local_db/insert.rs index b2a62ca97d..180e6f7b95 100644 --- a/crates/common/src/local_db/insert.rs +++ b/crates/common/src/local_db/insert.rs @@ -1,6 +1,6 @@ use super::decode::{DecodedEvent, DecodedEventData, InterpreterStoreSetEvent}; use super::query::{SqlStatement, SqlStatementBatch, SqlValue}; -use super::OrderbookIdentifier; +use super::RaindexIdentifier; use crate::{erc20::TokenInfo, rpc_client::LogEntryResponse}; use alloy::primitives::Bytes; use alloy::sol_types::SolValue; @@ -10,11 +10,11 @@ use alloy::{ }; use itertools::Itertools; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{ +use raindex_bindings::IRaindexV6::{ AddOrderV3, AfterClearV2, ClearV3, DepositV2, OrderV4, RemoveOrderV3, TakeOrderV3, WithdrawV2, IOV2, }; -use rain_orderbook_bindings::OrderBook::MetaV1_2; +use raindex_bindings::Raindex::MetaV1_2; use std::collections::HashMap; use std::convert::TryInto; use thiserror::Error; @@ -67,7 +67,7 @@ fn vault_id_by_index<'a>( } struct EventContext { - ob_id: OrderbookIdentifier, + raindex_id: RaindexIdentifier, block_number: u64, block_timestamp: u64, transaction_hash: B256, @@ -75,11 +75,11 @@ struct EventContext { } fn event_context( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, event: &DecodedEventData, ) -> Result { Ok(EventContext { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), block_number: u256_to_u64(&event.block_number, "block_number")?, block_timestamp: u256_to_u64(&event.block_timestamp, "block_timestamp")?, transaction_hash: event.transaction_hash, @@ -88,14 +88,14 @@ fn event_context( } pub fn decoded_events_to_statements( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, events: &[DecodedEventData], decimals_by_token: &HashMap, ) -> Result { let mut batch = SqlStatementBatch::new(); for event in events { - let context = event_context(ob_id, event)?; + let context = event_context(raindex_id, event)?; match &event.decoded_data { DecodedEvent::DepositV2(decoded) => { batch.add(generate_deposit_statement( @@ -150,7 +150,7 @@ pub fn decoded_events_to_statements( } pub fn raw_events_to_statements( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, raw_events: &[LogEntryResponse], ) -> Result { struct RawEventRow<'a> { @@ -199,7 +199,7 @@ pub fn raw_events_to_statements( batch.add(SqlStatement::new_with_params( r#"INSERT INTO raw_events ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -222,8 +222,8 @@ pub fn raw_events_to_statements( ); "#, vec![ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), SqlValue::from(row.block_number), block_timestamp, SqlValue::from(row.event.transaction_hash), @@ -241,7 +241,7 @@ pub fn raw_events_to_statements( /// Build upsert SQL for erc20_tokens. Only include successfully fetched tokens. pub fn generate_erc20_token_statements( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, tokens: &[(Address, TokenInfo)], ) -> SqlStatementBatch { let mut batch = SqlStatementBatch::new(); @@ -250,7 +250,7 @@ pub fn generate_erc20_token_statements( batch.add(SqlStatement::new_with_params( r#"INSERT INTO erc20_tokens ( chain_id, - orderbook_address, + raindex_address, token_address, name, symbol, @@ -263,11 +263,11 @@ pub fn generate_erc20_token_statements( ?5, ?6 ) - ON CONFLICT(chain_id, orderbook_address, token_address) DO UPDATE SET decimals = excluded.decimals, name = excluded.name, symbol = excluded.symbol; + ON CONFLICT(chain_id, raindex_address, token_address) DO UPDATE SET decimals = excluded.decimals, name = excluded.name, symbol = excluded.symbol; "#, [ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), SqlValue::from(*addr), SqlValue::from(info.name.clone()), SqlValue::from(info.symbol.clone()), @@ -311,7 +311,7 @@ fn generate_deposit_statement( Ok(SqlStatement::new_with_params( r#"INSERT INTO deposits ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -336,8 +336,8 @@ fn generate_deposit_statement( ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -355,7 +355,7 @@ fn generate_withdraw_statement(context: &EventContext, decoded: &WithdrawV2) -> SqlStatement::new_with_params( r#"INSERT INTO withdrawals ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -382,8 +382,8 @@ fn generate_withdraw_statement(context: &EventContext, decoded: &WithdrawV2) -> ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -402,7 +402,7 @@ fn generate_add_order_statement(context: &EventContext, decoded: &AddOrderV3) -> SqlStatement::new_with_params( r#"INSERT INTO order_events ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -433,8 +433,8 @@ fn generate_add_order_statement(context: &EventContext, decoded: &AddOrderV3) -> ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -457,7 +457,7 @@ fn generate_remove_order_statement( SqlStatement::new_with_params( r#"INSERT INTO order_events ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -488,8 +488,8 @@ fn generate_remove_order_statement( ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -515,7 +515,7 @@ fn generate_take_order_statement( Ok(SqlStatement::new_with_params( r#"INSERT INTO take_orders ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -544,8 +544,8 @@ fn generate_take_order_statement( ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -567,7 +567,7 @@ fn generate_take_order_context_statements( ) -> SqlStatementBatch { const INSERT_CONTEXT_SQL: &str = r#"INSERT INTO take_order_contexts ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index, @@ -596,8 +596,8 @@ fn generate_take_order_context_statements( batch.add(SqlStatement::new_with_params( INSERT_CONTEXT_SQL, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(transaction_hash), SqlValue::from(log_index), SqlValue::from(context_index as u64), @@ -615,7 +615,7 @@ fn generate_take_order_context_value_statements( ) -> SqlStatementBatch { const INSERT_VALUE_SQL: &str = r#"INSERT INTO context_values ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index, @@ -641,8 +641,8 @@ fn generate_take_order_context_value_statements( batch.add(SqlStatement::new_with_params( INSERT_VALUE_SQL, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(transaction_hash), SqlValue::from(log_index), SqlValue::from(context_index as u64), @@ -696,7 +696,7 @@ fn generate_clear_v3_statement( Ok(SqlStatement::new_with_params( r#"INSERT INTO clear_v3_events ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -741,8 +741,8 @@ fn generate_clear_v3_statement( ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -770,7 +770,7 @@ fn generate_after_clear_statement(context: &EventContext, decoded: &AfterClearV2 SqlStatement::new_with_params( r#"INSERT INTO after_clear_v2_events ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -795,8 +795,8 @@ fn generate_after_clear_statement(context: &EventContext, decoded: &AfterClearV2 ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -814,7 +814,7 @@ fn generate_meta_statement(context: &EventContext, decoded: &MetaV1_2) -> SqlSta SqlStatement::new_with_params( r#"INSERT INTO meta_events ( chain_id, - orderbook_address, + raindex_address, block_number, block_timestamp, transaction_hash, @@ -835,8 +835,8 @@ fn generate_meta_statement(context: &EventContext, decoded: &MetaV1_2) -> SqlSta ); "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), SqlValue::from(context.transaction_hash), @@ -855,7 +855,7 @@ fn generate_store_set_statement( SqlStatement::new_with_params( r#"INSERT INTO interpreter_store_sets ( chain_id, - orderbook_address, + raindex_address, store_address, block_number, block_timestamp, @@ -875,7 +875,7 @@ fn generate_store_set_statement( ?8, ?9, ?10 -) ON CONFLICT(chain_id, orderbook_address, transaction_hash, log_index) DO UPDATE SET +) ON CONFLICT(chain_id, raindex_address, transaction_hash, log_index) DO UPDATE SET store_address = excluded.store_address, block_number = excluded.block_number, block_timestamp = excluded.block_timestamp, @@ -884,8 +884,8 @@ fn generate_store_set_statement( value = excluded.value; "#, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(decoded.store_address), SqlValue::from(context.block_number), SqlValue::from(context.block_timestamp), @@ -901,7 +901,7 @@ fn generate_store_set_statement( fn generate_order_ios_statements(context: &EventContext, order: &OrderV4) -> SqlStatementBatch { const INSERT_IO_SQL: &str = r#"INSERT INTO order_ios ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, io_index, @@ -928,8 +928,8 @@ fn generate_order_ios_statements(context: &EventContext, order: &OrderV4) -> Sql batch.add(SqlStatement::new_with_params( INSERT_IO_SQL, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(transaction_hash), SqlValue::from(log_index), SqlValue::from(index as u64), @@ -944,8 +944,8 @@ fn generate_order_ios_statements(context: &EventContext, order: &OrderV4) -> Sql batch.add(SqlStatement::new_with_params( INSERT_IO_SQL, vec![ - SqlValue::from(context.ob_id.chain_id), - SqlValue::from(context.ob_id.orderbook_address), + SqlValue::from(context.raindex_id.chain_id), + SqlValue::from(context.raindex_id.raindex_address), SqlValue::from(transaction_hash), SqlValue::from(log_index), SqlValue::from(index as u64), @@ -967,8 +967,8 @@ mod tests { use crate::rpc_client::LogEntryResponse; use alloy::hex; use alloy::primitives::{address, b256, Address, Bytes, FixedBytes, B256, U256}; - use rain_orderbook_bindings::IInterpreterStoreV3::Set; - use rain_orderbook_bindings::IRaindexV6::{ + use raindex_bindings::IInterpreterStoreV3::Set; + use raindex_bindings::IRaindexV6::{ ClearConfigV2, ClearStateChangeV2, EvaluableV4, SignedContextV1, TakeOrderConfigV4, }; use std::collections::HashMap; @@ -1215,7 +1215,7 @@ mod tests { #[test] fn store_set_sql_generation() { let event = sample_store_set_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::InterpreterStoreSet(decoded) = &event.decoded_data else { unreachable!() }; @@ -1228,12 +1228,12 @@ mod tests { assert_eq!(params.len(), 10); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!( matches!(params[2], SqlValue::Text(ref v) if v == &hex::encode_prefixed(decoded.store_address)) @@ -1263,7 +1263,7 @@ mod tests { #[test] fn deposit_statement_generation() { let event = sample_deposit_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::DepositV2(decoded) = &event.decoded_data else { unreachable!() }; @@ -1277,12 +1277,12 @@ mod tests { assert_eq!(params.len(), 11); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[2], SqlValue::U64(v) if v == context.block_number)); assert!(matches!(params[3], SqlValue::U64(v) if v == context.block_timestamp)); @@ -1302,7 +1302,7 @@ mod tests { #[test] fn add_order_sql_includes_evaluable_addresses() { let event = sample_add_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::AddOrderV3(decoded) = &event.decoded_data else { unreachable!() }; @@ -1315,12 +1315,12 @@ mod tests { assert_eq!(params.len(), 13); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[5], SqlValue::U64(v) if v == context.log_index)); let expected_sender = hex::encode_prefixed(decoded.sender); @@ -1343,7 +1343,7 @@ mod tests { #[test] fn remove_order_sql_includes_evaluable_addresses() { let event = sample_remove_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::RemoveOrderV3(decoded) = &event.decoded_data else { unreachable!() }; @@ -1355,12 +1355,12 @@ mod tests { assert_eq!(params.len(), 13); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[5], SqlValue::U64(v) if v == context.log_index)); let expected_sender = hex::encode_prefixed(decoded.sender); @@ -1376,7 +1376,7 @@ mod tests { #[test] fn take_order_sql_generation() { let event = sample_take_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::TakeOrderV3(decoded) = &event.decoded_data else { unreachable!() }; @@ -1387,12 +1387,12 @@ mod tests { assert_eq!(params.len(), 13); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[2], SqlValue::U64(v) if v == context.block_number)); assert!(matches!(params[3], SqlValue::U64(v) if v == context.block_timestamp)); @@ -1425,7 +1425,7 @@ mod tests { #[test] fn after_clear_sql_generation() { let event = sample_after_clear_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::AfterClearV2(decoded) = &event.decoded_data else { unreachable!() }; @@ -1438,12 +1438,12 @@ mod tests { assert_eq!(params.len(), 11); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[2], SqlValue::U64(v) if v == context.block_number)); assert!(matches!(params[3], SqlValue::U64(v) if v == context.block_timestamp)); @@ -1460,7 +1460,7 @@ mod tests { #[test] fn meta_sql_generation() { let event = sample_meta_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::MetaV1_2(decoded) = &event.decoded_data else { unreachable!() }; @@ -1471,12 +1471,12 @@ mod tests { assert_eq!(params.len(), 9); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[2], SqlValue::U64(v) if v == context.block_number)); assert!(matches!(params[3], SqlValue::U64(v) if v == context.block_timestamp)); @@ -1492,7 +1492,7 @@ mod tests { #[test] fn clear_v3_sql_generation() { let event = sample_clear_event(); - let context = event_context(&OrderbookIdentifier::new(1, Address::ZERO), &event).unwrap(); + let context = event_context(&RaindexIdentifier::new(1, Address::ZERO), &event).unwrap(); let DecodedEvent::ClearV3(decoded) = &event.decoded_data else { unreachable!() }; @@ -1503,12 +1503,12 @@ mod tests { assert_eq!(params.len(), 21); assert!(matches!( params[0], - SqlValue::U64(v) if v == context.ob_id.chain_id as u64 + SqlValue::U64(v) if v == context.raindex_id.chain_id as u64 )); assert!(matches!( params[1], SqlValue::Text(ref v) - if v == &hex::encode_prefixed(context.ob_id.orderbook_address) + if v == &hex::encode_prefixed(context.raindex_id.raindex_address) )); assert!(matches!(params[2], SqlValue::U64(v) if v == context.block_number)); assert!(matches!(params[3], SqlValue::U64(v) if v == context.block_timestamp)); @@ -1528,7 +1528,7 @@ mod tests { decimals.insert(deposit.token, 6); } let batch = decoded_events_to_statements( - &OrderbookIdentifier::new(1, Address::from([0x11; 20])), + &RaindexIdentifier::new(1, Address::from([0x11; 20])), &[deposit_event, clear_event], &decimals, ) @@ -1553,7 +1553,7 @@ mod tests { }), ); let batch = decoded_events_to_statements( - &OrderbookIdentifier::new(1, Address::from([0x11; 20])), + &RaindexIdentifier::new(1, Address::from([0x11; 20])), &[unknown_event], &HashMap::new(), ) @@ -1586,9 +1586,8 @@ mod tests { ), ]; - let orderbook = Address::from([0x11; 20]); - let batch = - generate_erc20_token_statements(&OrderbookIdentifier::new(1, orderbook), &tokens); + let raindex = Address::from([0x11; 20]); + let batch = generate_erc20_token_statements(&RaindexIdentifier::new(1, raindex), &tokens); assert_eq!(batch.len(), tokens.len()); for (statement, (expected_addr, expected_info)) in @@ -1596,16 +1595,14 @@ mod tests { { let sql = statement.sql(); assert!(sql.contains("INSERT INTO erc20_tokens")); - assert!( - sql.contains("ON CONFLICT(chain_id, orderbook_address, token_address) DO UPDATE") - ); + assert!(sql.contains("ON CONFLICT(chain_id, raindex_address, token_address) DO UPDATE")); let params = statement.params(); assert_eq!(params.len(), 6); assert!(matches!(params[0], SqlValue::U64(1u64))); assert!(matches!( ¶ms[1], - SqlValue::Text(addr) if addr == &format!("0x{:x}", orderbook) + SqlValue::Text(addr) if addr == &format!("0x{:x}", raindex) )); assert!(matches!( ¶ms[2], @@ -1668,9 +1665,8 @@ mod tests { }, )]; - let orderbook = Address::from([0x22; 20]); - let batch = - generate_erc20_token_statements(&OrderbookIdentifier::new(5, orderbook), &tokens); + let raindex = Address::from([0x22; 20]); + let batch = generate_erc20_token_statements(&RaindexIdentifier::new(5, raindex), &tokens); assert_eq!(batch.len(), 1); let statement = &batch.statements()[0]; let sql = statement.sql(); @@ -1681,7 +1677,7 @@ mod tests { assert!(matches!(params[0], SqlValue::U64(5u64))); assert!(matches!( ¶ms[1], - SqlValue::Text(orderbook_param) if orderbook_param == &format!("0x{:x}", orderbook) + SqlValue::Text(raindex_param) if raindex_param == &format!("0x{:x}", raindex) )); assert!(matches!( ¶ms[2], @@ -1752,10 +1748,9 @@ mod tests { }, ]; - let orderbook_address = Address::from([0x10; 20]); + let raindex_address = Address::from([0x10; 20]); let batch = - raw_events_to_statements(&OrderbookIdentifier::new(1, orderbook_address), &events) - .unwrap(); + raw_events_to_statements(&RaindexIdentifier::new(1, raindex_address), &events).unwrap(); assert_eq!(batch.len(), 3); let hashes: Vec<_> = batch @@ -1814,7 +1809,7 @@ mod tests { }]; let result = raw_events_to_statements( - &OrderbookIdentifier::new(1, Address::from([0x10; 20])), + &RaindexIdentifier::new(1, Address::from([0x10; 20])), &events, ); assert!(matches!( diff --git a/crates/common/src/local_db/mod.rs b/crates/common/src/local_db/mod.rs index 6ecc106a22..89f7270e67 100644 --- a/crates/common/src/local_db/mod.rs +++ b/crates/common/src/local_db/mod.rs @@ -20,8 +20,8 @@ use decode::DecodeError; pub use fetch::{FetchConfig, FetchConfigError}; use insert::InsertError; use query::{LocalDbQueryError, SqlBuildError}; -use rain_orderbook_app_settings::remote::manifest::FetchManifestError; -use rain_orderbook_app_settings::yaml::YamlError; +use raindex_app_settings::remote::manifest::FetchManifestError; +use raindex_app_settings::yaml::YamlError; use serde::{Deserialize, Serialize}; use std::array::TryFromSliceError; use std::num::ParseIntError; @@ -56,8 +56,8 @@ pub enum LocalDbError { #[error("Missing local-db sync config for network '{network}'")] MissingLocalDbSyncForNetwork { network: String }, - #[error("Missing local-db remote for orderbook '{orderbook_key}'")] - MissingLocalDbRemote { orderbook_key: String }, + #[error("Missing local-db remote for raindex '{raindex_key}'")] + MissingLocalDbRemote { raindex_key: String }, #[error("Invalid block number '{value}'")] InvalidBlockNumber { @@ -83,10 +83,10 @@ pub enum LocalDbError { #[error("Configuration error: {message}")] Config { message: String }, - #[error("Missing runner target for chain {chain_id} orderbook {orderbook_address}")] + #[error("Missing runner target for chain {chain_id} raindex {raindex_address}")] MissingRunnerTarget { chain_id: u32, - orderbook_address: Address, + raindex_address: Address, }, #[error( @@ -218,9 +218,9 @@ impl LocalDbError { LocalDbError::Rpc(err) => format!("RPC error: {}", err), LocalDbError::JsonParse(err) => format!("Failed to parse JSON response: {}", err), LocalDbError::MissingField { field } => format!("Missing expected field: {}", field), - LocalDbError::MissingLocalDbRemote { orderbook_key } => format!( - "Missing local-db remote configuration for orderbook '{}'", - orderbook_key + LocalDbError::MissingLocalDbRemote { raindex_key } => format!( + "Missing local-db remote configuration for raindex '{}'", + raindex_key ), LocalDbError::InvalidBlockNumber { value, .. } => { format!("Invalid block number provided: {}", value) @@ -251,10 +251,10 @@ impl LocalDbError { LocalDbError::Config { message } => format!("Configuration error: {}", message), LocalDbError::MissingRunnerTarget { chain_id, - orderbook_address, + raindex_address, } => format!( - "Missing runner target for chain {} orderbook {:#x}", - chain_id, orderbook_address + "Missing runner target for chain {} raindex {:#x}", + chain_id, raindex_address ), LocalDbError::RunnerNetworkChainIdMismatch { network_key, @@ -343,18 +343,18 @@ impl LocalDbError { #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[cfg_attr(target_family = "wasm", derive(Tsify))] -pub struct OrderbookIdentifier { +pub struct RaindexIdentifier { pub chain_id: u32, - pub orderbook_address: Address, + pub raindex_address: Address, } #[cfg(target_family = "wasm")] -impl_wasm_traits!(OrderbookIdentifier); +impl_wasm_traits!(RaindexIdentifier); -impl OrderbookIdentifier { - pub fn new(chain_id: u32, orderbook_address: Address) -> Self { +impl RaindexIdentifier { + pub fn new(chain_id: u32, raindex_address: Address) -> Self { Self { chain_id, - orderbook_address, + raindex_address, } } } diff --git a/crates/common/src/local_db/pipeline/adapters/apply.rs b/crates/common/src/local_db/pipeline/adapters/apply.rs index a62656011e..fad3b1c284 100644 --- a/crates/common/src/local_db/pipeline/adapters/apply.rs +++ b/crates/common/src/local_db/pipeline/adapters/apply.rs @@ -9,7 +9,7 @@ use crate::local_db::query::fetch_erc20_tokens_by_addresses::Erc20TokenRow; use crate::local_db::query::upsert_target_watermark::upsert_target_watermark_stmt; use crate::local_db::query::upsert_vault_balances::upsert_vault_balances_batch; use crate::local_db::query::{LocalDbQueryExecutor, SqlStatement, SqlStatementBatch}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use crate::local_db::{decode::DecodedEventData, LocalDbError}; use crate::rpc_client::LogEntryResponse; use alloy::primitives::{Address, B256}; @@ -18,7 +18,7 @@ use std::collections::HashMap; #[derive(Debug, Clone)] pub struct ApplyPipelineTargetInfo { - pub ob_id: OrderbookIdentifier, + pub raindex_id: RaindexIdentifier, pub start_block: u64, pub target_block: u64, pub hash: B256, @@ -30,8 +30,8 @@ pub struct ApplyPipelineTargetInfo { /// - Build a transactional batch containing: /// - Raw events INSERTs. /// - Token upserts for provided `(Address, TokenInfo)` pairs. -/// - Decoded event INSERTs for all orderbook-scoped tables, binding the -/// target orderbook. +/// - Decoded event INSERTs for all raindex-scoped tables, binding the +/// target raindex. /// - Vault balance change/running balance upserts. /// - Watermark update to the `target_block` (and later last hash). /// - Persist the batch with a single-writer gate; must assert that the batch @@ -66,24 +66,24 @@ pub trait ApplyPipeline { let mut batch = SqlStatementBatch::new(); // Raw events first - let raw_batch = build_raw_event_sql(&target_info.ob_id, raw_logs)?; + let raw_batch = build_raw_event_sql(&target_info.raindex_id, raw_logs)?; batch.extend(raw_batch); // Token upserts for the missing set only if !tokens_to_upsert.is_empty() { - let upserts = build_token_upserts(&target_info.ob_id, tokens_to_upsert); + let upserts = build_token_upserts(&target_info.raindex_id, tokens_to_upsert); batch.extend(upserts); } - // Decoded orderbook/store events + // Decoded raindex/store events let decoded_batch = - build_decoded_event_sql(&target_info.ob_id, decoded_events, &decimals_by_token)?; + build_decoded_event_sql(&target_info.raindex_id, decoded_events, &decimals_by_token)?; batch.extend(decoded_batch); // Vault balance change/running balance updates if target_info.start_block <= target_info.target_block { batch.extend(upsert_vault_balances_batch( - &target_info.ob_id, + &target_info.raindex_id, target_info.start_block, target_info.target_block, )); @@ -91,7 +91,7 @@ pub trait ApplyPipeline { // Watermark update to target block batch.add(upsert_target_watermark_stmt( - &target_info.ob_id, + &target_info.raindex_id, target_info.target_block, target_info.hash.into(), )); @@ -118,7 +118,7 @@ pub trait ApplyPipeline { async fn export_dump( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _raindex_id: &RaindexIdentifier, _end_block: u64, ) -> Result<(), LocalDbError> where @@ -145,19 +145,19 @@ impl ApplyPipeline for DefaultApplyPipeline {} mod tests { use super::*; use crate::local_db::query::{LocalDbQueryError, SqlStatement, SqlValue}; - use crate::local_db::OrderbookIdentifier; + use crate::local_db::RaindexIdentifier; use alloy::primitives::{b256, Bytes, B256, U256}; const SAMPLE_HASH_B256: B256 = b256!("0x111122223333444455556666777788889999aaaabbbbccccddddeeeeffff0000"); fn build_target_info( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, start_block: u64, target_block: u64, ) -> ApplyPipelineTargetInfo { ApplyPipelineTargetInfo { - ob_id: ob_id.clone(), + raindex_id: raindex_id.clone(), start_block, target_block, hash: SAMPLE_HASH_B256, @@ -221,13 +221,13 @@ mod tests { } } - fn sample_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(137, Address::from([0u8; 20])) + fn sample_raindex_id() -> RaindexIdentifier { + RaindexIdentifier::new(137, Address::from([0u8; 20])) } fn deposit_event(addr: Address) -> DecodedEventData { use crate::local_db::decode::EventType; - use rain_orderbook_bindings::IRaindexV6::DepositV2; + use raindex_bindings::IRaindexV6::DepositV2; DecodedEventData { event_type: EventType::DepositV2, block_number: U256::from(1), @@ -247,7 +247,7 @@ mod tests { fn withdraw_event(addr: Address) -> DecodedEventData { use crate::local_db::decode::EventType; - use rain_orderbook_bindings::IRaindexV6::WithdrawV2; + use raindex_bindings::IRaindexV6::WithdrawV2; DecodedEventData { event_type: EventType::WithdrawV2, block_number: U256::from(0x10), @@ -270,13 +270,13 @@ mod tests { #[test] fn build_batch_contains_watermark() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([3u8; 20]); // existing token with decimals 18 let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token, name: "Token".into(), symbol: "TKN".into(), @@ -287,7 +287,7 @@ mod tests { let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 123), + &build_target_info(&raindex_id, 1, 123), &[], &decoded, &existing, @@ -355,10 +355,10 @@ mod tests { #[test] fn empty_work_window_only_watermark() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let batch = pipeline - .build_batch(&build_target_info(&ob_id, 1, 42), &[], &[], &[], &[]) + .build_batch(&build_target_info(&raindex_id, 1, 42), &[], &[], &[], &[]) .expect("batch ok"); // Expect vault balance refresh plus the watermark and ANALYZE when there is no work. @@ -380,13 +380,13 @@ mod tests { use rain_math_float::Float; let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([7u8; 20]); // Existing says 6 decimals let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token, name: "Token".into(), symbol: "T6".into(), @@ -405,7 +405,7 @@ mod tests { let decoded = vec![deposit_event(token)]; let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 100), + &build_target_info(&raindex_id, 1, 100), &[], &decoded, &existing, @@ -420,7 +420,7 @@ mod tests { .find(|s| s.sql().starts_with("INSERT INTO deposits")) .expect("deposit insert present"); - // Params: [chain_id, orderbook, block_number, block_timestamp, tx_hash, log_index, sender, token, vault_id, deposit_amount, deposit_amount_uint256] + // Params: [chain_id, raindex, block_number, block_timestamp, tx_hash, log_index, sender, token, vault_id, deposit_amount, deposit_amount_uint256] let deposit_amount_param = stmt.params().get(9).expect("param 10 present"); let expected = Float::from_fixed_decimal(U256::from(1000u64), 18) .unwrap() @@ -443,13 +443,13 @@ mod tests { use rain_math_float::Float; let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([10u8; 20]); // Existing has an invalid address string let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: Address::ZERO, name: "Bad".into(), symbol: "BAD".into(), @@ -468,7 +468,7 @@ mod tests { let decoded = vec![deposit_event(token)]; let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 100), + &build_target_info(&raindex_id, 1, 100), &[], &decoded, &existing, @@ -496,12 +496,18 @@ mod tests { #[test] fn missing_decimals_yields_error() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([9u8; 20]); let decoded = vec![deposit_event(token)]; let err = pipeline - .build_batch(&build_target_info(&ob_id, 1, 1), &[], &decoded, &[], &[]) + .build_batch( + &build_target_info(&raindex_id, 1, 1), + &[], + &decoded, + &[], + &[], + ) .unwrap_err(); use crate::local_db::insert::InsertError; @@ -516,14 +522,14 @@ mod tests { #[test] fn token_upserts_generated_for_provided_tokens() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); // Existing has A; upserts contain B let token_a = Address::from([1u8; 20]); let token_b = Address::from([2u8; 20]); let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token_a, name: "A".into(), symbol: "A".into(), @@ -540,7 +546,7 @@ mod tests { let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 1), + &build_target_info(&raindex_id, 1, 1), &[], &[], &existing, @@ -572,12 +578,12 @@ mod tests { #[test] fn watermark_param_matches_target_block() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let target_block = 12345u64; let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, target_block), + &build_target_info(&raindex_id, 1, target_block), &[], &[], &[], @@ -615,13 +621,13 @@ mod tests { use rain_math_float::Float; let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([13u8; 20]); // Only existing provides decimals let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token, name: "E".into(), symbol: "E".into(), @@ -631,7 +637,7 @@ mod tests { let decoded = vec![deposit_event(token)]; let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 100), + &build_target_info(&raindex_id, 1, 100), &[], &decoded, &existing, @@ -697,7 +703,7 @@ mod tests { use rain_math_float::Float; let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([11u8; 20]); // Provide two upserts for same token with differing decimals; later should win @@ -723,7 +729,7 @@ mod tests { let decoded = vec![deposit_event(token)]; let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 100), + &build_target_info(&raindex_id, 1, 100), &[], &decoded, &[], @@ -760,7 +766,7 @@ mod tests { #[test] fn token_upserts_chain_id_param_matches_target() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([5u8; 20]); let upserts = vec![( @@ -773,7 +779,13 @@ mod tests { )]; let batch = pipeline - .build_batch(&build_target_info(&ob_id, 1, 1), &[], &[], &[], &upserts) + .build_batch( + &build_target_info(&raindex_id, 1, 1), + &[], + &[], + &[], + &upserts, + ) .expect("batch ok"); let stmt = batch @@ -783,10 +795,10 @@ mod tests { .expect("token upsert present"); match stmt.params().first() { Some(crate::local_db::query::SqlValue::U64(chain)) => { - assert_eq!(*chain, ob_id.chain_id as u64); + assert_eq!(*chain, raindex_id.chain_id as u64); } Some(crate::local_db::query::SqlValue::I64(chain)) => { - assert_eq!(*chain as u64, ob_id.chain_id as u64); + assert_eq!(*chain as u64, raindex_id.chain_id as u64); } other => panic!("unexpected chain_id param: {other:?}"), } @@ -795,7 +807,7 @@ mod tests { #[test] fn raw_events_sorted_by_block_then_log() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); // Two raw logs out of order let mk = |block: u64, log_index: u64| { @@ -817,7 +829,13 @@ mod tests { let b = mk(10, 3); let batch = pipeline - .build_batch(&build_target_info(&ob_id, 1, 10), &[a, b], &[], &[], &[]) + .build_batch( + &build_target_info(&raindex_id, 1, 10), + &[a, b], + &[], + &[], + &[], + ) .expect("batch ok"); let raws: Vec<_> = batch @@ -845,7 +863,7 @@ mod tests { #[test] fn only_raw_logs_emitted_when_no_tokens_or_decoded() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let mk = |block: u64, log_index: u64| LogEntryResponse { address: Address::from([0x11; 20]), @@ -870,7 +888,7 @@ mod tests { let raw = [mk(1, 0), mk(1, 1)]; let batch = pipeline - .build_batch(&build_target_info(&ob_id, 1, 2), &raw, &[], &[], &[]) + .build_batch(&build_target_info(&raindex_id, 1, 2), &raw, &[], &[], &[]) .expect("batch ok"); let texts: Vec<_> = batch.statements().iter().map(|s| s.sql()).collect(); @@ -889,9 +907,9 @@ mod tests { #[test] fn watermark_emitted_exactly_once() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let batch = pipeline - .build_batch(&build_target_info(&ob_id, 1, 77), &[], &[], &[], &[]) + .build_batch(&build_target_info(&raindex_id, 1, 77), &[], &[], &[], &[]) .expect("batch ok"); let count = batch .statements() @@ -904,12 +922,12 @@ mod tests { #[test] fn analyze_emitted_exactly_once_and_is_last() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([3u8; 20]); let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token, name: "Token".into(), symbol: "TKN".into(), @@ -919,7 +937,7 @@ mod tests { let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 100), + &build_target_info(&raindex_id, 1, 100), &[], &decoded, &existing, @@ -948,7 +966,7 @@ mod tests { #[test] fn statements_order_raw_then_tokens_then_decoded_then_watermark() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); // Build one raw, one token upsert, one decoded deposit let mk_raw = |block: u64, log_index: u64| LogEntryResponse { @@ -984,7 +1002,7 @@ mod tests { let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 9), + &build_target_info(&raindex_id, 1, 9), &[mk_raw(9, 0)], &decoded, &[], @@ -1021,12 +1039,12 @@ mod tests { #[test] fn deterministic_batch_shape_for_identical_inputs() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([3u8; 20]); let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token, name: "Token".into(), symbol: "TKN".into(), @@ -1036,7 +1054,7 @@ mod tests { let b1 = pipeline .build_batch( - &build_target_info(&ob_id, 1, 5), + &build_target_info(&raindex_id, 1, 5), &[], &decoded, &existing, @@ -1045,7 +1063,7 @@ mod tests { .expect("b1 ok"); let b2 = pipeline .build_batch( - &build_target_info(&ob_id, 1, 5), + &build_target_info(&raindex_id, 1, 5), &[], &decoded, &existing, @@ -1063,12 +1081,12 @@ mod tests { #[test] fn includes_withdraw_decoded_events() { let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([12u8; 20]); let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 5), + &build_target_info(&raindex_id, 1, 5), &[], &[withdraw_event(token)], &[], @@ -1088,15 +1106,15 @@ mod tests { use rain_math_float::Float; let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); // Two tokens: A gets decimals from existing, B from upserts let token_a = Address::from([21u8; 20]); let token_b = Address::from([22u8; 20]); let existing = vec![Erc20TokenRow { - chain_id: ob_id.chain_id as u32, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id as u32, + raindex_address: raindex_id.raindex_address, token_address: token_a, name: "A".into(), symbol: "A".into(), @@ -1114,7 +1132,7 @@ mod tests { let decoded = vec![deposit_event(token_a), deposit_event(token_b)]; let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 100), + &build_target_info(&raindex_id, 1, 100), &[], &decoded, &existing, @@ -1168,12 +1186,12 @@ mod tests { use alloy::{hex, primitives::U256}; let pipeline = DefaultApplyPipeline::new(); - let ob_id = sample_ob_id(); + let raindex_id = sample_raindex_id(); let token = Address::from([15u8; 20]); let batch = pipeline .build_batch( - &build_target_info(&ob_id, 1, 5), + &build_target_info(&raindex_id, 1, 5), &[], &[withdraw_event(token)], &[], diff --git a/crates/common/src/local_db/pipeline/adapters/bootstrap.rs b/crates/common/src/local_db/pipeline/adapters/bootstrap.rs index 74482ff0b9..53def3a0d4 100644 --- a/crates/common/src/local_db/pipeline/adapters/bootstrap.rs +++ b/crates/common/src/local_db/pipeline/adapters/bootstrap.rs @@ -1,4 +1,4 @@ -use crate::local_db::query::clear_orderbook_data::clear_orderbook_data_batch; +use crate::local_db::query::clear_raindex_data::clear_raindex_data_batch; use crate::local_db::query::clear_tables::clear_tables_stmt; use crate::local_db::query::create_tables::create_tables_stmt; use crate::local_db::query::create_tables::REQUIRED_TABLES; @@ -11,14 +11,14 @@ use crate::local_db::query::insert_db_metadata::insert_db_metadata_stmt; use crate::local_db::query::integrity_check::{integrity_check_stmt, IntegrityCheckRow}; use crate::local_db::query::{LocalDbQueryExecutor, SqlStatementBatch}; use crate::local_db::LocalDbError; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use async_trait::async_trait; -use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; +use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; use std::collections::HashSet; #[derive(Debug, Clone)] pub struct BootstrapConfig { - pub ob_id: OrderbookIdentifier, + pub raindex_id: RaindexIdentifier, pub dump_stmt: Option, pub latest_block: u64, pub block_number_threshold: u32, @@ -71,7 +71,7 @@ pub trait BootstrapPipeline { async fn inspect_state( &self, db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result where DB: LocalDbQueryExecutor + ?Sized, @@ -87,8 +87,9 @@ pub trait BootstrapPipeline { .all(|&t| existing_set.contains(&t.to_ascii_lowercase())); let last_synced_block = if existing_set.contains("target_watermarks") { - let rows: Vec = - db.query_json(&fetch_target_watermark_stmt(ob_id)).await?; + let rows: Vec = db + .query_json(&fetch_target_watermark_stmt(raindex_id)) + .await?; rows.first().map(|r| r.last_block) } else { None @@ -130,15 +131,15 @@ pub trait BootstrapPipeline { Ok(is_healthy) } - async fn clear_orderbook_data( + async fn clear_raindex_data( &self, db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result<(), LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, { - let batch = clear_orderbook_data_batch(ob_id); + let batch = clear_raindex_data_batch(raindex_id); db.execute_batch(&batch).await?; Ok(()) } @@ -433,11 +434,11 @@ mod tests { .unwrap(); // Watermark row present - let ob_id = OrderbookIdentifier::new(1, Address::ZERO); - let watermark_stmt = fetch_target_watermark_stmt(&ob_id); + let raindex_id = RaindexIdentifier::new(1, Address::ZERO); + let watermark_stmt = fetch_target_watermark_stmt(&raindex_id); let watermark_json = json!([TargetWatermarkRow { - chain_id: ob_id.chain_id, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id, + raindex_address: raindex_id.raindex_address, last_block: 123, last_hash: Bytes::from_str("0xbeef").unwrap(), updated_at: 1, @@ -447,7 +448,7 @@ mod tests { .with_json(&fetch_tables_stmt(), tables_json) .with_json(&watermark_stmt, watermark_json); - let state = adapter.inspect_state(&db, &ob_id).await.unwrap(); + let state = adapter.inspect_state(&db, &raindex_id).await.unwrap(); assert!(state.has_required_tables); assert_eq!(state.last_synced_block, Some(123)); } @@ -456,8 +457,8 @@ mod tests { async fn inspect_state_missing_tables_means_not_ready_and_no_watermark_query() { let adapter = TestBootstrapPipeline::new(); let db = MockDb::default().with_json(&fetch_tables_stmt(), json!([])); - let ob_id = OrderbookIdentifier::new(1, Address::ZERO); - let state = adapter.inspect_state(&db, &ob_id).await.unwrap(); + let raindex_id = RaindexIdentifier::new(1, Address::ZERO); + let state = adapter.inspect_state(&db, &raindex_id).await.unwrap(); assert!(!state.has_required_tables); assert_eq!(state.last_synced_block, None); } @@ -483,11 +484,11 @@ mod tests { .unwrap(); let db = MockDb::default().with_json(&fetch_tables_stmt(), tables_json); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 1, - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, }; - let state = adapter.inspect_state(&db, &ob_id).await.unwrap(); + let state = adapter.inspect_state(&db, &raindex_id).await.unwrap(); assert!(!state.has_required_tables); assert_eq!(state.last_synced_block, None); } @@ -505,14 +506,14 @@ mod tests { ) .unwrap(); - let ob_id = OrderbookIdentifier::new(1, Address::ZERO); - let watermark_stmt = fetch_target_watermark_stmt(&ob_id); + let raindex_id = RaindexIdentifier::new(1, Address::ZERO); + let watermark_stmt = fetch_target_watermark_stmt(&raindex_id); let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json(&watermark_stmt, json!([])); - let state = adapter.inspect_state(&db, &ob_id).await.unwrap(); + let state = adapter.inspect_state(&db, &raindex_id).await.unwrap(); assert!(state.has_required_tables); assert_eq!(state.last_synced_block, None); } @@ -536,11 +537,11 @@ mod tests { ) .unwrap(); - let ob_id = OrderbookIdentifier::new(1, Address::ZERO); - let watermark_stmt = fetch_target_watermark_stmt(&ob_id); + let raindex_id = RaindexIdentifier::new(1, Address::ZERO); + let watermark_stmt = fetch_target_watermark_stmt(&raindex_id); let watermark_json = json!([TargetWatermarkRow { - chain_id: ob_id.chain_id, - orderbook_address: ob_id.orderbook_address, + chain_id: raindex_id.chain_id, + raindex_address: raindex_id.raindex_address, last_block: 42, last_hash: Bytes::from_str("0xbeef").unwrap(), updated_at: 1, @@ -550,7 +551,7 @@ mod tests { .with_json(&fetch_tables_stmt(), tables_json) .with_json(&watermark_stmt, watermark_json); - let state = adapter.inspect_state(&db, &ob_id).await.unwrap(); + let state = adapter.inspect_state(&db, &raindex_id).await.unwrap(); assert!(state.has_required_tables); assert_eq!(state.last_synced_block, Some(42)); } @@ -559,11 +560,11 @@ mod tests { async fn inspect_state_propagates_fetch_tables_error() { let adapter = TestBootstrapPipeline::new(); let db = MockDb::default(); // no json for fetch_tables_stmt() - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 1, - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, }; - let err = adapter.inspect_state(&db, &ob_id).await.unwrap_err(); + let err = adapter.inspect_state(&db, &raindex_id).await.unwrap_err(); match err { LocalDbError::LocalDbQueryError(..) => {} other => panic!("unexpected error: {other:?}"), @@ -585,12 +586,12 @@ mod tests { .unwrap(); let db = MockDb::default().with_json(&fetch_tables_stmt(), tables_json); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 1, - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, }; // Intentionally do not provide json for watermark_stmt -> should error - let err = adapter.inspect_state(&db, &ob_id).await.unwrap_err(); + let err = adapter.inspect_state(&db, &raindex_id).await.unwrap_err(); match err { LocalDbError::LocalDbQueryError(..) => {} other => panic!("unexpected error: {other:?}"), @@ -701,7 +702,7 @@ mod tests { let adapter = TestBootstrapPipeline::new(); let db = MockDb::default(); let cfg = BootstrapConfig { - ob_id: OrderbookIdentifier::new(1, Address::ZERO), + raindex_id: RaindexIdentifier::new(1, Address::ZERO), dump_stmt: None, latest_block: 0, block_number_threshold: 10_000, @@ -728,18 +729,18 @@ mod tests { } #[tokio::test] - async fn clear_orderbook_data_executes_expected_statement() { + async fn clear_raindex_data_executes_expected_statement() { let adapter = TestBootstrapPipeline::new(); - let ob_id = OrderbookIdentifier::new(42161, Address::from([0x11; 20])); + let raindex_id = RaindexIdentifier::new(42161, Address::from([0x11; 20])); let db = RecordingTextExecutor::succeed(); adapter - .clear_orderbook_data(&db, &ob_id) + .clear_raindex_data(&db, &raindex_id) .await - .expect("clear_orderbook_data should succeed"); + .expect("clear_raindex_data should succeed"); let captured = db.captured_sql(); - let expected: Vec = clear_orderbook_data_batch(&ob_id) + let expected: Vec = clear_raindex_data_batch(&raindex_id) .statements() .iter() .map(|stmt| stmt.sql().to_string()) @@ -748,16 +749,16 @@ mod tests { } #[tokio::test] - async fn clear_orderbook_data_propagates_error() { + async fn clear_raindex_data_propagates_error() { let adapter = TestBootstrapPipeline::new(); - let ob_id = OrderbookIdentifier::new(10, Address::from([0x22; 20])); + let raindex_id = RaindexIdentifier::new(10, Address::from([0x22; 20])); let inner_error = LocalDbQueryError::database("boom"); let db = RecordingTextExecutor::fail(LocalDbError::from(inner_error.clone())); let err = adapter - .clear_orderbook_data(&db, &ob_id) + .clear_raindex_data(&db, &raindex_id) .await - .expect_err("clear_orderbook_data should propagate error"); + .expect_err("clear_raindex_data should propagate error"); match err { LocalDbError::LocalDbQueryError(actual) => { @@ -767,7 +768,7 @@ mod tests { } let captured = db.captured_sql(); - let expected: Vec = clear_orderbook_data_batch(&ob_id) + let expected: Vec = clear_raindex_data_batch(&raindex_id) .statements() .iter() .map(|stmt| stmt.sql().to_string()) diff --git a/crates/common/src/local_db/pipeline/adapters/events.rs b/crates/common/src/local_db/pipeline/adapters/events.rs index ab0c71c1d8..95008d14c1 100644 --- a/crates/common/src/local_db/pipeline/adapters/events.rs +++ b/crates/common/src/local_db/pipeline/adapters/events.rs @@ -3,7 +3,7 @@ use async_trait::async_trait; use url::Url; use crate::local_db::decode::{decode_events, DecodedEvent, DecodedEventData}; -use crate::local_db::fetch::{fetch_orderbook_events, fetch_store_events}; +use crate::local_db::fetch::{fetch_raindex_events, fetch_store_events}; use crate::local_db::pipeline::EventsPipeline; use crate::local_db::{FetchConfig, LocalDbError}; use crate::rpc_client::{LogEntryResponse, RpcClient}; @@ -51,21 +51,14 @@ impl EventsPipeline for DefaultEventsPipeline { Ok(block.hash) } - async fn fetch_orderbook( + async fn fetch_raindex( &self, - orderbook_address: Address, + raindex_address: Address, from_block: u64, to_block: u64, cfg: &FetchConfig, ) -> Result, LocalDbError> { - fetch_orderbook_events( - &self.rpc_client, - orderbook_address, - from_block, - to_block, - cfg, - ) - .await + fetch_raindex_events(&self.rpc_client, raindex_address, from_block, to_block, cfg).await } async fn fetch_stores( @@ -93,7 +86,7 @@ mod tests { use alloy::primitives::{b256, Bytes, U256}; use alloy::sol_types::SolEvent; use httpmock::MockServer; - use rain_orderbook_bindings::OrderBook::MetaV1_2; + use raindex_bindings::Raindex::MetaV1_2; use serde_json::json; use std::str::FromStr; diff --git a/crates/common/src/local_db/pipeline/adapters/tokens.rs b/crates/common/src/local_db/pipeline/adapters/tokens.rs index f83c4464ea..5abe2d16a8 100644 --- a/crates/common/src/local_db/pipeline/adapters/tokens.rs +++ b/crates/common/src/local_db/pipeline/adapters/tokens.rs @@ -3,7 +3,7 @@ use crate::local_db::pipeline::TokensPipeline; use crate::local_db::query::fetch_erc20_tokens_by_addresses::{build_fetch_stmt, Erc20TokenRow}; use crate::local_db::query::LocalDbQueryExecutor; use crate::local_db::token_fetch::fetch_erc20_metadata_concurrent; -use crate::local_db::{FetchConfig, LocalDbError, OrderbookIdentifier}; +use crate::local_db::{FetchConfig, LocalDbError, RaindexIdentifier}; use crate::rpc_client::RpcClient; use alloy::primitives::Address; use async_trait::async_trait; @@ -35,13 +35,13 @@ impl TokensPipeline for DefaultTokensPipeline { async fn load_existing( &self, db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, token_addrs_lower: &[Address], ) -> Result, LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, { - let Some(stmt) = build_fetch_stmt(ob_id, token_addrs_lower)? else { + let Some(stmt) = build_fetch_stmt(raindex_id, token_addrs_lower)? else { return Ok(vec![]); }; let rows: Vec = db.query_json(&stmt).await?; @@ -70,7 +70,7 @@ mod tests { // Assertions for the incoming statement expect_in_clause: bool, expect_chain_id: Option, - expect_orderbook: Option, + expect_raindex: Option, expect_addr_count: Option, // Optional explicit expected address parameter values (in order) expect_addr_values: Option>, @@ -106,18 +106,18 @@ mod tests { other => panic!("expected first param U64({cid}), got {other:?}"), } } - if let Some(expected_orderbook) = self.expect_orderbook.as_ref() { + if let Some(expected_raindex) = self.expect_raindex.as_ref() { match stmt.params().get(1) { Some(crate::local_db::query::SqlValue::Text(actual)) => { - assert_eq!(actual, &expected_orderbook.to_ascii_lowercase()); + assert_eq!(actual, &expected_raindex.to_ascii_lowercase()); } other => { - panic!("expected second param Text({expected_orderbook}), got {other:?}") + panic!("expected second param Text({expected_raindex}), got {other:?}") } } } if let Some(n) = self.expect_addr_count { - // There should be chain id + orderbook + n address params + // There should be chain id + raindex + n address params assert_eq!(stmt.params().len(), 2 + n); } if let Some(expected) = &self.expect_addr_values { @@ -155,12 +155,12 @@ mod tests { #[tokio::test] async fn load_existing_empty_addresses_short_circuits() { - let orderbook = Address::from([0xbe; 20]); + let raindex = Address::from([0xbe; 20]); let db = MockDb { rows: vec![], expect_in_clause: false, expect_chain_id: None, - expect_orderbook: None, + expect_raindex: None, expect_addr_count: None, expect_addr_values: None, fail_query: false, @@ -168,7 +168,7 @@ mod tests { }; let pipeline = DefaultTokensPipeline::mock(); let out = pipeline - .load_existing(&db, &OrderbookIdentifier::new(137, orderbook), &[]) + .load_existing(&db, &RaindexIdentifier::new(137, raindex), &[]) .await .expect("ok"); assert!(out.is_empty()); @@ -176,12 +176,12 @@ mod tests { #[tokio::test] async fn load_existing_builds_query_and_returns_rows() { - let orderbook = Address::from([0xab; 20]); + let raindex = Address::from([0xab; 20]); let token_addr = Address::from([0xac; 20]); let other_addr = Address::from([0xad; 20]); let row = Erc20TokenRow { chain_id: 137, - orderbook_address: orderbook, + raindex_address: raindex, token_address: token_addr, name: "Token".to_string(), symbol: "TKN".to_string(), @@ -191,7 +191,7 @@ mod tests { rows: vec![row.clone()], expect_in_clause: true, expect_chain_id: Some(137), - expect_orderbook: Some(orderbook.to_string()), + expect_raindex: Some(raindex.to_string()), expect_addr_count: Some(2), expect_addr_values: Some(vec![ hex::encode_prefixed(token_addr), @@ -203,7 +203,7 @@ mod tests { let pipeline = DefaultTokensPipeline::mock(); let addrs = vec![token_addr, other_addr]; let out = pipeline - .load_existing(&db, &OrderbookIdentifier::new(137, orderbook), &addrs) + .load_existing(&db, &RaindexIdentifier::new(137, raindex), &addrs) .await .expect("ok"); assert_eq!(out, vec![row]); @@ -211,13 +211,13 @@ mod tests { #[tokio::test] async fn load_existing_propagates_db_error() { - let orderbook = Address::from([0xcd; 20]); + let raindex = Address::from([0xcd; 20]); let token_addr = Address::from([0xae; 20]); let db = MockDb { rows: vec![], expect_in_clause: true, expect_chain_id: Some(1), - expect_orderbook: Some(orderbook.to_string()), + expect_raindex: Some(raindex.to_string()), expect_addr_count: Some(1), expect_addr_values: Some(vec![hex::encode_prefixed(token_addr)]), fail_query: true, @@ -225,7 +225,7 @@ mod tests { }; let pipeline = DefaultTokensPipeline::mock(); let err = pipeline - .load_existing(&db, &OrderbookIdentifier::new(1, orderbook), &[token_addr]) + .load_existing(&db, &RaindexIdentifier::new(1, raindex), &[token_addr]) .await .expect_err("should fail"); match err { @@ -239,13 +239,13 @@ mod tests { #[tokio::test] async fn load_existing_deserialization_error_bubbles() { - let orderbook = Address::from([0xde; 20]); + let raindex = Address::from([0xde; 20]); let token_addr = Address::from([0xaf; 20]); let db = MockDb { rows: vec![], expect_in_clause: true, expect_chain_id: Some(1), - expect_orderbook: Some(orderbook.to_string()), + expect_raindex: Some(raindex.to_string()), expect_addr_count: Some(1), expect_addr_values: Some(vec![hex::encode_prefixed(token_addr)]), fail_query: false, @@ -253,7 +253,7 @@ mod tests { }; let pipeline = DefaultTokensPipeline::mock(); let err = pipeline - .load_existing(&db, &OrderbookIdentifier::new(1, orderbook), &[token_addr]) + .load_existing(&db, &RaindexIdentifier::new(1, raindex), &[token_addr]) .await .expect_err("should fail"); match err { @@ -267,14 +267,14 @@ mod tests { #[tokio::test] async fn load_existing_keeps_duplicate_addresses_in_order() { - let orderbook = Address::from([0xef; 20]); + let raindex = Address::from([0xef; 20]); let addr_a = Address::from([0xaa; 20]); let addr_b = Address::from([0xbb; 20]); let db = MockDb { rows: vec![], expect_in_clause: true, expect_chain_id: Some(137), - expect_orderbook: Some(orderbook.to_string()), + expect_raindex: Some(raindex.to_string()), expect_addr_count: Some(3), expect_addr_values: Some(vec![ hex::encode_prefixed(addr_a), @@ -288,7 +288,7 @@ mod tests { let addrs = vec![addr_a, addr_a, addr_b]; // We only care that params keep duplicates in order; rows are empty let out = pipeline - .load_existing(&db, &OrderbookIdentifier::new(137, orderbook), &addrs) + .load_existing(&db, &RaindexIdentifier::new(137, raindex), &addrs) .await .expect("ok"); assert!(out.is_empty()); @@ -298,7 +298,7 @@ mod tests { mod non_wasm_tests { use super::*; use alloy::primitives::Address; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn fetch_missing_delegates_to_concurrent_fetcher() { diff --git a/crates/common/src/local_db/pipeline/adapters/window.rs b/crates/common/src/local_db/pipeline/adapters/window.rs index 5369691d25..e0c3d7c5c4 100644 --- a/crates/common/src/local_db/pipeline/adapters/window.rs +++ b/crates/common/src/local_db/pipeline/adapters/window.rs @@ -3,7 +3,7 @@ use crate::local_db::query::fetch_target_watermark::{ fetch_target_watermark_stmt, TargetWatermarkRow, }; use crate::local_db::query::LocalDbQueryExecutor; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; use async_trait::async_trait; #[derive(Debug, Default, Clone, Copy)] @@ -36,7 +36,7 @@ impl WindowPipeline for DefaultWindowPipeline { async fn compute( &self, db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, cfg: &SyncConfig, latest_block: u64, ) -> Result<(u64, u64), LocalDbError> @@ -46,7 +46,7 @@ impl WindowPipeline for DefaultWindowPipeline { // 1) Read watermark let last_synced_block = { let rows: Vec = db - .query_json(&fetch_target_watermark_stmt(ob_id)) + .query_json(&fetch_target_watermark_stmt(raindex_id)) .await .map_err(LocalDbError::from)?; rows.first().map(|r| r.last_block).unwrap_or(0) @@ -117,7 +117,7 @@ mod tests { Some(crate::local_db::query::SqlValue::U64(v)) => *v as u32, _ => 0, }; - let orderbook_address = match params.get(1) { + let raindex_address = match params.get(1) { Some(crate::local_db::query::SqlValue::Text(v)) => v.clone(), _ => format!("0x{:040x}", 0u128), }; @@ -126,7 +126,7 @@ mod tests { } else { serde_json::to_string(&vec![TargetWatermarkRow { chain_id, - orderbook_address: Address::from_str(&orderbook_address).unwrap(), + raindex_address: Address::from_str(&raindex_address).unwrap(), last_block: self.last_synced, last_hash: Bytes::from_str("0xbeef").unwrap(), updated_at: 1, @@ -148,10 +148,10 @@ mod tests { } } - fn sample_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier { + fn sample_raindex_id() -> RaindexIdentifier { + RaindexIdentifier { chain_id: 1, - orderbook_address: Address::from([0u8; 20]), + raindex_address: Address::from([0u8; 20]), } } @@ -175,7 +175,7 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, target) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, None, None), 200) + .compute(&db, &sample_raindex_id(), &cfg(100, 0, None, None), 200) .await .unwrap(); assert_eq!(start, 100); @@ -190,7 +190,7 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, _) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, None, None), 200) + .compute(&db, &sample_raindex_id(), &cfg(100, 0, None, None), 200) .await .unwrap(); assert_eq!(start, 151); @@ -204,7 +204,12 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, _) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, Some(100), None), 200) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 0, Some(100), None), + 200, + ) .await .unwrap(); assert_eq!(start, 151); @@ -218,7 +223,7 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, _) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, Some(50), None), 200) + .compute(&db, &sample_raindex_id(), &cfg(100, 0, Some(50), None), 200) .await .unwrap(); assert_eq!(start, 100); @@ -233,7 +238,7 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // latest=1000, depth=20 => safe_head= max(100, 980)=980 let (_, target) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 20, None, None), 1000) + .compute(&db, &sample_raindex_id(), &cfg(100, 20, None, None), 1000) .await .unwrap(); assert_eq!(target, 980); @@ -248,7 +253,12 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // safe_head = 980 let (_, target) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 20, None, Some(2000)), 1000) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 20, None, Some(2000)), + 1000, + ) .await .unwrap(); assert_eq!(target, 980); @@ -262,7 +272,7 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let err = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, None, None), 200) + .compute(&db, &sample_raindex_id(), &cfg(100, 0, None, None), 200) .await .unwrap_err(); match err { @@ -279,7 +289,12 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let (start, _) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, Some(150), None), 200) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 0, Some(150), None), + 200, + ) .await .unwrap(); assert_eq!(start, 151); @@ -294,7 +309,12 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // safe_head = 980; end_override = 500 -> target = 500 let (_, target) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 20, None, Some(500)), 1000) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 20, None, Some(500)), + 1000, + ) .await .unwrap(); assert_eq!(target, 500); @@ -309,7 +329,7 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // latest=100, depth=200 => latest-depth saturates to 0; max(deploy=90, 0) = 90 let (_, target) = pipe - .compute(&db, &sample_ob_id(), &cfg(90, 200, None, None), 100) + .compute(&db, &sample_raindex_id(), &cfg(90, 200, None, None), 100) .await .unwrap(); assert_eq!(target, 90); @@ -323,7 +343,7 @@ mod tests { }; let pipe = DefaultWindowPipeline::new(); let err = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, None, None), 200) + .compute(&db, &sample_raindex_id(), &cfg(100, 0, None, None), 200) .await .unwrap_err(); match err { @@ -343,7 +363,12 @@ mod tests { let pipe = DefaultWindowPipeline::new(); // base start = 201; end_override = 150; depth=0 so safe_head is high and does not clamp let (start, target) = pipe - .compute(&db, &sample_ob_id(), &cfg(100, 0, None, Some(150)), 1000) + .compute( + &db, + &sample_raindex_id(), + &cfg(100, 0, None, Some(150)), + 1000, + ) .await .unwrap(); assert_eq!(start, 201); diff --git a/crates/common/src/local_db/pipeline/engine.rs b/crates/common/src/local_db/pipeline/engine.rs index 804a8be53f..a704c22f30 100644 --- a/crates/common/src/local_db/pipeline/engine.rs +++ b/crates/common/src/local_db/pipeline/engine.rs @@ -11,7 +11,7 @@ use crate::local_db::decode::{ use crate::local_db::query::fetch_erc20_tokens_by_addresses::Erc20TokenRow; use crate::local_db::query::fetch_store_addresses::{fetch_store_addresses_stmt, StoreAddressRow}; use crate::local_db::query::{LocalDbQueryExecutor, SqlStatement, SqlStatementBatch}; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; use crate::rpc_client::LogEntryResponse; use alloy::primitives::Address; use std::collections::{BTreeSet, HashSet}; @@ -31,7 +31,7 @@ pub struct SyncEngine { /// Runner-supplied inputs that are static for the duration of a sync cycle. #[derive(Debug, Clone)] pub struct SyncInputs { - pub ob_id: OrderbookIdentifier, + pub raindex_id: RaindexIdentifier, pub metadata_rpcs: Vec, pub cfg: SyncConfig, pub dump_str: Option, @@ -69,7 +69,7 @@ where if start_block > target_block { self.status.send(SyncPhase::Idle).await?; return Ok(SyncOutcome { - ob_id: input.ob_id.clone(), + raindex_id: input.raindex_id.clone(), start_block, target_block, fetched_logs: 0, @@ -77,11 +77,11 @@ where }); } - let (orderbook_logs, decoded_orderbook_events) = self - .gather_orderbook(input, start_block, target_block) + let (raindex_logs, decoded_raindex_events) = self + .gather_raindex(input, start_block, target_block) .await?; - let mut all_raw_logs = orderbook_logs; - let mut decoded_events = decoded_orderbook_events; + let mut all_raw_logs = raindex_logs; + let mut decoded_events = decoded_raindex_events; let (store_logs, mut decoded_store_events, existing_tokens, token_addresses) = self .load_store_logs_and_existing_tokens( @@ -109,7 +109,7 @@ where db, ApplyContext { target_info: &ApplyPipelineTargetInfo { - ob_id: input.ob_id.clone(), + raindex_id: input.raindex_id.clone(), start_block, target_block, hash: target_hash, @@ -123,7 +123,7 @@ where .await?; Ok(SyncOutcome { - ob_id: input.ob_id.clone(), + raindex_id: input.raindex_id.clone(), start_block, target_block, fetched_logs: all_raw_logs.len(), @@ -153,7 +153,7 @@ where .engine_run( db, &BootstrapConfig { - ob_id: input.ob_id.clone(), + raindex_id: input.raindex_id.clone(), dump_stmt: input.dump_str.as_ref().map(|value| { let mut batch_stmt = SqlStatementBatch::new(); for line in value.lines() { @@ -183,31 +183,31 @@ where { self.status.send(SyncPhase::ComputingSyncWindow).await?; self.window - .compute(db, &input.ob_id, &input.cfg, latest_block) + .compute(db, &input.raindex_id, &input.cfg, latest_block) .await } - async fn gather_orderbook( + async fn gather_raindex( &self, input: &SyncInputs, start_block: u64, target_block: u64, ) -> Result<(Vec, Vec>), LocalDbError> { - self.status.send(SyncPhase::FetchingOrderbookLogs).await?; - let orderbook_logs = self + self.status.send(SyncPhase::FetchingRaindexLogs).await?; + let raindex_logs = self .events - .fetch_orderbook( - input.ob_id.orderbook_address, + .fetch_raindex( + input.raindex_id.raindex_address, start_block, target_block, &input.cfg.fetch, ) .await?; - self.status.send(SyncPhase::DecodingOrderbookLogs).await?; - let decoded_events = self.events.decode(&orderbook_logs)?; + self.status.send(SyncPhase::DecodingRaindexLogs).await?; + let decoded_events = self.events.decode(&raindex_logs)?; - Ok((orderbook_logs, decoded_events)) + Ok((raindex_logs, decoded_events)) } async fn load_store_logs_and_existing_tokens( @@ -230,7 +230,7 @@ where DB: LocalDbQueryExecutor + ?Sized, { let mut store_addresses = collect_store_addresses(decoded_events); - let existing_store_rows = load_known_store_addresses(db, &input.ob_id).await?; + let existing_store_rows = load_known_store_addresses(db, &input.raindex_id).await?; for row in existing_store_rows { if !row.store_address.is_zero() { store_addresses.insert(row.store_address); @@ -242,7 +242,7 @@ where let tokens_fut = self .tokens - .load_existing(db, &input.ob_id, &token_addresses_vec); + .load_existing(db, &input.raindex_id, &token_addresses_vec); let store_addresses_vec: Vec
= store_addresses.into_iter().collect(); let store_fetch_fut = async { @@ -324,7 +324,11 @@ where self.status.send(SyncPhase::RunningPostSyncExport).await?; self.apply - .export_dump(db, &ctx.target_info.ob_id, ctx.target_info.target_block) + .export_dump( + db, + &ctx.target_info.raindex_id, + ctx.target_info.target_block, + ) .await } } @@ -339,12 +343,12 @@ struct ApplyContext<'a> { async fn load_known_store_addresses( db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result, LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, { - db.query_json(&fetch_store_addresses_stmt(ob_id)) + db.query_json(&fetch_store_addresses_stmt(raindex_id)) .await .map_err(Into::into) } @@ -366,7 +370,7 @@ mod tests { use crate::local_db::FetchConfig; use alloy::primitives::{b256, Address, Bytes, FixedBytes, B256, U256}; use async_trait::async_trait; - use rain_orderbook_bindings::IInterpreterStoreV3::Set; + use raindex_bindings::IInterpreterStoreV3::Set; use serde_json; use std::collections::VecDeque; use std::sync::{Arc, Mutex}; @@ -408,7 +412,7 @@ mod tests { token: Address, tx: u8, ) -> DecodedEventData { - use rain_orderbook_bindings::IRaindexV6::DepositV2; + use raindex_bindings::IRaindexV6::DepositV2; DecodedEventData { event_type: EventType::DepositV2, block_number: U256::from(block), @@ -432,7 +436,7 @@ mod tests { output_token: Address, tx: u8, ) -> DecodedEventData { - use rain_orderbook_bindings::IRaindexV6::{AddOrderV3, EvaluableV4, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{AddOrderV3, EvaluableV4, OrderV4, IOV2}; DecodedEventData { event_type: EventType::AddOrderV3, block_number: U256::from(block), @@ -486,16 +490,16 @@ mod tests { } } - fn base_target() -> OrderbookIdentifier { - OrderbookIdentifier { + fn base_target() -> RaindexIdentifier { + RaindexIdentifier { chain_id: 42161, - orderbook_address: addr(0xAB), + raindex_address: addr(0xAB), } } fn base_inputs() -> SyncInputs { SyncInputs { - ob_id: base_target(), + raindex_id: base_target(), metadata_rpcs: vec![Url::parse("https://rpc.example.com").unwrap()], cfg: SyncConfig { deployment_block: 1, @@ -575,7 +579,7 @@ mod tests { async fn inspect_state( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _raindex_id: &RaindexIdentifier, ) -> Result where DB: LocalDbQueryExecutor + ?Sized, @@ -597,10 +601,10 @@ mod tests { Ok(()) } - async fn clear_orderbook_data( + async fn clear_raindex_data( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, ) -> Result<(), LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, @@ -644,7 +648,7 @@ mod tests { #[derive(Default)] struct MockWindowInner { - calls: Mutex>, + calls: Mutex>, results: Mutex>>, } @@ -653,7 +657,7 @@ mod tests { *self.inner.results.lock().unwrap() = VecDeque::from(results); } - fn calls(&self) -> Vec<(OrderbookIdentifier, u64, u64, u64)> { + fn calls(&self) -> Vec<(RaindexIdentifier, u64, u64, u64)> { self.inner.calls.lock().unwrap().clone() } } @@ -663,7 +667,7 @@ mod tests { async fn compute( &self, _db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, cfg: &SyncConfig, latest_block: u64, ) -> Result<(u64, u64), LocalDbError> @@ -671,7 +675,7 @@ mod tests { DB: LocalDbQueryExecutor + ?Sized, { self.inner.calls.lock().unwrap().push(( - ob_id.clone(), + raindex_id.clone(), cfg.deployment_block, latest_block, cfg.finality.depth as u64, @@ -693,11 +697,11 @@ mod tests { #[derive(Default)] struct MockEventsInner { latest_blocks: Mutex>>, - orderbook_results: Mutex, LocalDbError>>>, + raindex_results: Mutex, LocalDbError>>>, store_results: Mutex, LocalDbError>>>, decode_results: Mutex>, LocalDbError>>>, block_hashes: Mutex>>, - orderbook_calls: Mutex>, + raindex_calls: Mutex>, store_calls: Mutex, u64, u64)>>, store_barrier: Mutex>>, store_completed: Mutex, @@ -708,12 +712,8 @@ mod tests { *self.inner.latest_blocks.lock().unwrap() = VecDeque::from(blocks); } - fn push_orderbook_result(&self, result: Result, LocalDbError>) { - self.inner - .orderbook_results - .lock() - .unwrap() - .push_back(result); + fn push_raindex_result(&self, result: Result, LocalDbError>) { + self.inner.raindex_results.lock().unwrap().push_back(result); } fn push_store_result(&self, result: Result, LocalDbError>) { @@ -731,8 +731,8 @@ mod tests { self.inner.block_hashes.lock().unwrap().push_back(result); } - fn orderbook_calls(&self) -> Vec<(Address, u64, u64)> { - self.inner.orderbook_calls.lock().unwrap().clone() + fn raindex_calls(&self) -> Vec<(Address, u64, u64)> { + self.inner.raindex_calls.lock().unwrap().clone() } fn store_calls(&self) -> Vec<(Vec
, u64, u64)> { @@ -759,20 +759,20 @@ mod tests { .unwrap_or(Ok(0)) } - async fn fetch_orderbook( + async fn fetch_raindex( &self, - orderbook_address: Address, + raindex_address: Address, from_block: u64, to_block: u64, _cfg: &FetchConfig, ) -> Result, LocalDbError> { - self.inner.orderbook_calls.lock().unwrap().push(( - orderbook_address, - from_block, - to_block, - )); self.inner - .orderbook_results + .raindex_calls + .lock() + .unwrap() + .push((raindex_address, from_block, to_block)); + self.inner + .raindex_results .lock() .unwrap() .pop_front() @@ -880,7 +880,7 @@ mod tests { async fn load_existing( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _raindex_id: &RaindexIdentifier, token_addrs_lower: &[Address], ) -> Result, LocalDbError> where @@ -943,7 +943,7 @@ mod tests { export_results: Mutex>>, build_calls: Mutex>, persist_calls: Mutex>, - export_calls: Mutex>, + export_calls: Mutex>, } impl MockApply { @@ -967,7 +967,7 @@ mod tests { self.inner.persist_calls.lock().unwrap().clone() } - fn export_calls(&self) -> Vec<(OrderbookIdentifier, u64)> { + fn export_calls(&self) -> Vec<(RaindexIdentifier, u64)> { self.inner.export_calls.lock().unwrap().clone() } } @@ -1028,7 +1028,7 @@ mod tests { async fn export_dump( &self, _db: &DB, - target: &OrderbookIdentifier, + target: &RaindexIdentifier, end_block: u64, ) -> Result<(), LocalDbError> where @@ -1148,7 +1148,7 @@ mod tests { fn token_row(token: Address) -> Erc20TokenRow { Erc20TokenRow { chain_id: base_target().chain_id, - orderbook_address: base_target().orderbook_address, + raindex_address: base_target().raindex_address, token_address: token, name: "Token".into(), symbol: "TOK".into(), @@ -1170,9 +1170,9 @@ mod tests { let token_a = addr(0x01); let token_b = addr(0x02); let store = addr(0x90); - let orderbook_logs = vec![ - log_entry(base_target().orderbook_address, 10, 1, 1), - log_entry(base_target().orderbook_address, 11, 0, 2), + let raindex_logs = vec![ + log_entry(base_target().raindex_address, 10, 1, 1), + log_entry(base_target().raindex_address, 11, 0, 2), ]; let store_logs = vec![log_entry(store, 12, 0, 3)]; @@ -1181,9 +1181,7 @@ mod tests { "0x0000000000000000000000000000000000000000000000000000000000000001" ))); harness.window.set_results(vec![Ok((10, 12))]); - harness - .events - .push_orderbook_result(Ok(orderbook_logs.clone())); + harness.events.push_raindex_result(Ok(raindex_logs.clone())); harness.events.push_decode_result(Ok(vec![ deposit_event(10, 1, token_a, 1), add_order_event(11, 0, store, token_a, token_b, 2), @@ -1203,10 +1201,10 @@ mod tests { let outcome = harness.run(&inputs).await.expect("run succeeds"); - assert_eq!(outcome.ob_id.chain_id, inputs.ob_id.chain_id); + assert_eq!(outcome.raindex_id.chain_id, inputs.raindex_id.chain_id); assert_eq!( - outcome.ob_id.orderbook_address, - inputs.ob_id.orderbook_address + outcome.raindex_id.raindex_address, + inputs.raindex_id.raindex_address ); assert_eq!(outcome.start_block, 10); assert_eq!(outcome.target_block, 12); @@ -1220,8 +1218,8 @@ mod tests { SyncPhase::FetchingLatestBlock, SyncPhase::RunningBootstrap, SyncPhase::ComputingSyncWindow, - SyncPhase::FetchingOrderbookLogs, - SyncPhase::DecodingOrderbookLogs, + SyncPhase::FetchingRaindexLogs, + SyncPhase::DecodingRaindexLogs, SyncPhase::FetchingStoreLogs, SyncPhase::DecodingStoreLogs, SyncPhase::FetchingTokenMetadata, @@ -1282,7 +1280,7 @@ mod tests { ] ); - assert!(harness.events.orderbook_calls().is_empty()); + assert!(harness.events.raindex_calls().is_empty()); assert!(harness.apply.build_calls().is_empty()); } @@ -1292,8 +1290,8 @@ mod tests { let store = addr(0x50); harness.events.set_latest_blocks(vec![Ok(20)]); harness.window.set_results(vec![Ok((5, 6))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 5, 0, 1, @@ -1334,8 +1332,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(8)]); harness.window.set_results(vec![Ok((2, 4))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 2, 0, 1, @@ -1368,8 +1366,8 @@ mod tests { ])]); harness.events.set_latest_blocks(vec![Ok(9)]); harness.window.set_results(vec![Ok((3, 5))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 3, 0, 1, @@ -1404,8 +1402,8 @@ mod tests { let token_b = addr(0x02); harness.events.set_latest_blocks(vec![Ok(50)]); harness.window.set_results(vec![Ok((10, 12))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 10, 0, 1, @@ -1435,8 +1433,8 @@ mod tests { let token_b = addr(0x02); harness.events.set_latest_blocks(vec![Ok(22)]); harness.window.set_results(vec![Ok((5, 6))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 5, 0, 1, @@ -1455,12 +1453,12 @@ mod tests { } #[tokio::test] - async fn run_fetches_orderbook_with_window_range() { + async fn run_fetches_raindex_with_window_range() { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(200)]); harness.window.set_results(vec![Ok((42, 123))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 42, 0, 1, @@ -1475,7 +1473,7 @@ mod tests { harness.run(&base_inputs()).await.expect("run succeeds"); - let calls = harness.events.orderbook_calls(); + let calls = harness.events.raindex_calls(); assert_eq!(calls.len(), 1); let (_addr, start, end) = calls[0]; assert_eq!(start, 42); @@ -1500,9 +1498,9 @@ mod tests { ])]); harness.events.set_latest_blocks(vec![Ok(50)]); harness.window.set_results(vec![Ok((10, 12))]); - harness.events.push_orderbook_result(Ok(vec![ - log_entry(base_target().orderbook_address, 10, 0, 1), - log_entry(base_target().orderbook_address, 11, 0, 2), + harness.events.push_raindex_result(Ok(vec![ + log_entry(base_target().raindex_address, 10, 0, 1), + log_entry(base_target().raindex_address, 11, 0, 2), ])); harness.events.push_decode_result(Ok(vec![ add_order_event(10, 0, store1, addr(0x10), addr(0x11), 1), @@ -1538,9 +1536,9 @@ mod tests { let token = addr(0x0A); harness.events.set_latest_blocks(vec![Ok(60)]); harness.window.set_results(vec![Ok((7, 9))]); - harness.events.push_orderbook_result(Ok(vec![ - log_entry(base_target().orderbook_address, 7, 0, 1), - log_entry(base_target().orderbook_address, 8, 0, 2), + harness.events.push_raindex_result(Ok(vec![ + log_entry(base_target().raindex_address, 7, 0, 1), + log_entry(base_target().raindex_address, 8, 0, 2), ])); harness.events.push_decode_result(Ok(vec![ deposit_event(7, 0, token, 1), @@ -1572,8 +1570,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(1000)]); harness.window.set_results(vec![Ok((100, 105))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 100, 0, 1, @@ -1593,9 +1591,9 @@ mod tests { let calls = harness.apply.export_calls(); assert_eq!(calls.len(), 1); - let (ob_id, end_block) = &calls[0]; - assert_eq!(ob_id.chain_id, ob_id.chain_id); - assert_eq!(ob_id.orderbook_address, ob_id.orderbook_address); + let (raindex_id, end_block) = &calls[0]; + assert_eq!(raindex_id.chain_id, raindex_id.chain_id); + assert_eq!(raindex_id.raindex_address, raindex_id.raindex_address); assert_eq!(*end_block, 105); } @@ -1604,8 +1602,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(30)]); harness.window.set_results(vec![Ok((3, 3))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 3, 0, 1, @@ -1642,8 +1640,8 @@ mod tests { let store = addr(0xAA); harness.events.set_latest_blocks(vec![Ok(40)]); harness.window.set_results(vec![Ok((12, 15))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 12, 0, 1, @@ -1719,12 +1717,12 @@ mod tests { } #[tokio::test] - async fn run_propagates_orderbook_decode_error() { + async fn run_propagates_raindex_decode_error() { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(20)]); harness.window.set_results(vec![Ok((1, 5))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1748,8 +1746,8 @@ mod tests { let store = addr(0x77); harness.events.set_latest_blocks(vec![Ok(30)]); harness.window.set_results(vec![Ok((1, 3))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1796,17 +1794,17 @@ mod tests { } #[tokio::test] - async fn run_propagates_fetch_orderbook_error() { + async fn run_propagates_fetch_raindex_error() { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(10)]); harness.window.set_results(vec![Ok((1, 2))]); harness .events - .push_orderbook_result(Err(LocalDbError::CustomError("orderbook fail".into()))); + .push_raindex_result(Err(LocalDbError::CustomError("raindex fail".into()))); let err = harness.run(&base_inputs()).await.expect_err("should fail"); match err { - LocalDbError::CustomError(msg) => assert_eq!(msg, "orderbook fail"), + LocalDbError::CustomError(msg) => assert_eq!(msg, "raindex fail"), other => panic!("unexpected error: {other:?}"), } } @@ -1817,8 +1815,8 @@ mod tests { let store = addr(0x70); harness.events.set_latest_blocks(vec![Ok(20)]); harness.window.set_results(vec![Ok((1, 3))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1847,8 +1845,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(10)]); harness.window.set_results(vec![Ok((1, 1))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1872,8 +1870,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(10)]); harness.window.set_results(vec![Ok((1, 1))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1902,8 +1900,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(15)]); harness.window.set_results(vec![Ok((1, 2))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1933,8 +1931,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(15)]); harness.window.set_results(vec![Ok((1, 2))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -1964,8 +1962,8 @@ mod tests { let harness = EngineHarness::new(); harness.events.set_latest_blocks(vec![Ok(15)]); harness.window.set_results(vec![Ok((1, 2))]); - harness.events.push_orderbook_result(Ok(vec![log_entry( - base_target().orderbook_address, + harness.events.push_raindex_result(Ok(vec![log_entry( + base_target().raindex_address, 1, 0, 1, @@ -2058,12 +2056,12 @@ mod tests { }, ]; let executor = MockExecutor::success(rows.clone()); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 42161, - orderbook_address: Address::repeat_byte(0xAA), + raindex_address: Address::repeat_byte(0xAA), }; - let actual = load_known_store_addresses(&executor, &ob_id) + let actual = load_known_store_addresses(&executor, &raindex_id) .await .expect("fetch rows"); @@ -2072,7 +2070,7 @@ mod tests { assert_eq!(calls.len(), 1); let stmt = &calls[0]; assert_eq!(stmt.params().len(), 2); - assert_eq!(stmt.params()[0], SqlValue::U64(ob_id.chain_id as u64)); + assert_eq!(stmt.params()[0], SqlValue::U64(raindex_id.chain_id as u64)); assert_eq!( stmt.params()[1], SqlValue::Text("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string()) @@ -2082,12 +2080,12 @@ mod tests { #[tokio::test] async fn load_known_store_addresses_returns_empty_vec() { let executor = MockExecutor::success(Vec::new()); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 10, - orderbook_address: Address::repeat_byte(0xBB), + raindex_address: Address::repeat_byte(0xBB), }; - let actual = load_known_store_addresses(&executor, &ob_id) + let actual = load_known_store_addresses(&executor, &raindex_id) .await .expect("fetch rows"); assert!(actual.is_empty()); @@ -2096,12 +2094,12 @@ mod tests { #[tokio::test] async fn load_known_store_addresses_propagates_query_error() { let executor = MockExecutor::failure(LocalDbQueryError::database("boom")); - let ob_id = OrderbookIdentifier { + let raindex_id = RaindexIdentifier { chain_id: 1, - orderbook_address: Address::repeat_byte(0xCC), + raindex_address: Address::repeat_byte(0xCC), }; - let err = load_known_store_addresses(&executor, &ob_id) + let err = load_known_store_addresses(&executor, &raindex_id) .await .expect_err("should propagate error"); match err { diff --git a/crates/common/src/local_db/pipeline/mod.rs b/crates/common/src/local_db/pipeline/mod.rs index 51b0ac0c59..ee5360f9ee 100644 --- a/crates/common/src/local_db/pipeline/mod.rs +++ b/crates/common/src/local_db/pipeline/mod.rs @@ -11,7 +11,7 @@ pub mod adapters; pub mod engine; pub mod runner; -use super::OrderbookIdentifier; +use super::RaindexIdentifier; use crate::erc20::TokenInfo; use crate::local_db::decode::{DecodedEvent, DecodedEventData}; use crate::local_db::query::{ @@ -51,7 +51,7 @@ pub struct FinalityConfig { /// Static configuration supplied to a sync cycle. #[derive(Debug, Clone)] pub struct SyncConfig { - /// Block where the orderbook was deployed; the start block never goes + /// Block where the raindex was deployed; the start block never goes /// below this. pub deployment_block: u64, /// Fetch configuration (batch sizes, concurrency, etc.). @@ -66,12 +66,12 @@ pub struct SyncConfig { #[derive(Debug, Clone)] pub struct SyncOutcome { /// Target that was synced. - pub ob_id: OrderbookIdentifier, + pub raindex_id: RaindexIdentifier, /// Start block (inclusive) that was used. pub start_block: u64, /// Target block (inclusive) that was used. pub target_block: u64, - /// Count of raw logs fetched across orderbook and stores. + /// Count of raw logs fetched across raindex and stores. pub fetched_logs: usize, /// Count of decoded events materialized during the cycle. pub decoded_events: usize, @@ -85,8 +85,8 @@ pub enum SyncPhase { FetchingLatestBlock, RunningBootstrap, ComputingSyncWindow, - FetchingOrderbookLogs, - DecodingOrderbookLogs, + FetchingRaindexLogs, + DecodingRaindexLogs, FetchingStoreLogs, DecodingStoreLogs, FetchingTokenMetadata, @@ -104,8 +104,8 @@ impl SyncPhase { Self::FetchingLatestBlock => "Fetching latest block", Self::RunningBootstrap => "Running bootstrap", Self::ComputingSyncWindow => "Computing sync window", - Self::FetchingOrderbookLogs => "Fetching orderbook logs", - Self::DecodingOrderbookLogs => "Decoding orderbook logs", + Self::FetchingRaindexLogs => "Fetching raindex logs", + Self::DecodingRaindexLogs => "Decoding raindex logs", Self::FetchingStoreLogs => "Fetching interpreter store logs", Self::DecodingStoreLogs => "Decoding interpreter store logs", Self::FetchingTokenMetadata => "Fetching missing token metadata", @@ -147,7 +147,7 @@ pub trait WindowPipeline { async fn compute( &self, db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, cfg: &SyncConfig, latest_block: u64, ) -> Result<(u64, u64), LocalDbError> @@ -159,7 +159,7 @@ pub trait WindowPipeline { /// /// Responsibilities (concrete): /// - Decode via shared ABI into stable `DecodedEventData`. -/// - Provide a uniform surface for fetching orderbook/store logs. +/// - Provide a uniform surface for fetching raindex/store logs. /// /// Policy (environment-specific): /// - Backend selection: browser uses regular/public RPCs; producer uses @@ -172,10 +172,10 @@ pub trait EventsPipeline { /// Fetches the canonical block hash for the provided block number. async fn block_hash(&self, block_number: u64) -> Result; - /// Fetches orderbook logs within the inclusive block range. - async fn fetch_orderbook( + /// Fetches raindex logs within the inclusive block range. + async fn fetch_raindex( &self, - orderbook_address: Address, + raindex_address: Address, from_block: u64, to_block: u64, cfg: &FetchConfig, @@ -206,14 +206,14 @@ pub trait EventsPipeline { /// is handled by the Apply pipeline. /// /// Invariants: -/// - Upserts must be idempotent and keyed by `(chain_id, orderbook_address, token_address)`. +/// - Upserts must be idempotent and keyed by `(chain_id, raindex_address, token_address)`. #[async_trait(?Send)] pub trait TokensPipeline { /// Loads existing token rows for the provided lowercase addresses. async fn load_existing( &self, db: &DB, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, token_addrs: &[Address], ) -> Result, LocalDbError> where diff --git a/crates/common/src/local_db/pipeline/runner/environment.rs b/crates/common/src/local_db/pipeline/runner/environment.rs index 0fba849006..0f80a0e0aa 100644 --- a/crates/common/src/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/local_db/pipeline/runner/environment.rs @@ -5,8 +5,8 @@ use crate::local_db::pipeline::adapters::bootstrap::BootstrapPipeline; use crate::local_db::pipeline::engine::SyncEngine; use crate::local_db::pipeline::{EventsPipeline, StatusBus, TokensPipeline, WindowPipeline}; use crate::local_db::LocalDbError; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; -use rain_orderbook_app_settings::remote::manifest::ManifestMap; +use raindex_app_settings::raindex::RaindexCfg; +use raindex_app_settings::remote::manifest::ManifestMap; use std::collections::HashMap; use std::future::Future; use std::pin::Pin; @@ -18,7 +18,7 @@ pub type ManifestFuture = PinnedDbFuture; pub type DumpFuture = PinnedDbFuture; pub type ManifestFetcher = - Arc) -> ManifestFuture + Send + Sync>; + Arc) -> ManifestFuture + Send + Sync>; pub type DumpDownloader = Arc DumpFuture + Send + Sync>; pub type EngineBuilder = Arc< dyn Fn(&RunnerTarget) -> Result, LocalDbError> + Send + Sync, @@ -64,9 +64,9 @@ where pub async fn fetch_manifests( &self, - orderbooks: &HashMap, + raindexes: &HashMap, ) -> Result { - (self.manifest_fetcher)(orderbooks).await + (self.manifest_fetcher)(raindexes).await } pub async fn download_dump(&self, url: &Url) -> Result { @@ -123,9 +123,9 @@ where } pub fn default_manifest_fetcher() -> ManifestFetcher { - Arc::new(|orderbooks: &HashMap| { - let orderbooks = orderbooks.clone(); - Box::pin(async move { get_manifests(&orderbooks).await }) + Arc::new(|raindexes: &HashMap| { + let raindexes = raindexes.clone(); + Box::pin(async move { get_manifests(&raindexes).await }) }) } @@ -150,15 +150,15 @@ mod tests { use crate::local_db::pipeline::{FinalityConfig, SyncConfig, SyncPhase, WindowOverrides}; use crate::local_db::query::sql_statement_batch::SqlStatementBatch; use crate::local_db::query::LocalDbQueryExecutor; - use crate::local_db::{LocalDbError, OrderbookIdentifier}; + use crate::local_db::{LocalDbError, RaindexIdentifier}; use crate::rpc_client::LogEntryResponse; use alloy::primitives::{address, b256, Address, B256}; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::MANIFEST_VERSION; - use rain_orderbook_app_settings::local_db_remotes::LocalDbRemoteCfg; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::default_document; + use raindex_app_settings::local_db_manifest::MANIFEST_VERSION; + use raindex_app_settings::local_db_remotes::LocalDbRemoteCfg; + use raindex_app_settings::raindex::RaindexCfg; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::default_document; use std::collections::HashMap; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; @@ -178,13 +178,13 @@ mod tests { fn sample_target() -> RunnerTarget { let fetch = FetchConfig::new(1, 1, 1, 1, 0, 0).expect("fetch config"); RunnerTarget { - orderbook_key: "sample".to_string(), + raindex_key: "sample".to_string(), manifest_url: Url::parse("https://example.com/manifest.yaml").unwrap(), network_key: "network-a".to_string(), inputs: SyncInputs { - ob_id: OrderbookIdentifier { + raindex_id: RaindexIdentifier { chain_id: 1, - orderbook_address: address!("0000000000000000000000000000000000000001"), + raindex_address: address!("0000000000000000000000000000000000000001"), }, metadata_rpcs: vec![Url::parse("https://rpc.example.com").unwrap()], cfg: SyncConfig { @@ -246,7 +246,7 @@ mod tests { async fn inspect_state( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _raindex_id: &RaindexIdentifier, ) -> Result where DB: LocalDbQueryExecutor + ?Sized, @@ -268,10 +268,10 @@ mod tests { Ok(()) } - async fn clear_orderbook_data( + async fn clear_raindex_data( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, ) -> Result<(), LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, @@ -307,7 +307,7 @@ mod tests { async fn compute( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, _cfg: &SyncConfig, latest_block: u64, ) -> Result<(u64, u64), LocalDbError> @@ -324,9 +324,9 @@ mod tests { Ok(0) } - async fn fetch_orderbook( + async fn fetch_raindex( &self, - _orderbook_address: Address, + _raindex_address: Address, _from_block: u64, _to_block: u64, _cfg: &crate::local_db::FetchConfig, @@ -366,7 +366,7 @@ mod tests { async fn load_existing( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _raindex_id: &RaindexIdentifier, _token_addrs_lower: &[Address], ) -> Result< Vec, @@ -426,7 +426,7 @@ mod tests { let counter = Arc::new(AtomicUsize::new(0)); let manifest_map = Arc::new(HashMap::new()); let counter_fetcher = counter.clone(); - let fetcher: ManifestFetcher = Arc::new(move |_orderbooks| { + let fetcher: ManifestFetcher = Arc::new(move |_raindexes| { let counter = counter_fetcher.clone(); let manifest_map = Arc::clone(&manifest_map); Box::pin(async move { @@ -453,15 +453,15 @@ mod tests { }), ); - let orderbooks: HashMap = HashMap::new(); - let result = block_on(environment.fetch_manifests(&orderbooks)).expect("manifest map"); + let raindexes: HashMap = HashMap::new(); + let result = block_on(environment.fetch_manifests(&raindexes)).expect("manifest map"); assert!(result.is_empty()); assert_eq!(counter.load(Ordering::SeqCst), 1); } #[test] fn fetch_manifests_propagates_errors() { - let fetcher: ManifestFetcher = Arc::new(|_orderbooks| { + let fetcher: ManifestFetcher = Arc::new(|_raindexes| { Box::pin(async { Err(LocalDbError::HttpStatus { status: 500 }) }) }); let downloader: DumpDownloader = Arc::new(|_url| Box::pin(async { Ok(String::new()) })); @@ -479,8 +479,8 @@ mod tests { )) }), ); - let orderbooks: HashMap = HashMap::new(); - let err = block_on(environment.fetch_manifests(&orderbooks)).unwrap_err(); + let raindexes: HashMap = HashMap::new(); + let err = block_on(environment.fetch_manifests(&raindexes)).unwrap_err(); match err { LocalDbError::HttpStatus { status } => assert_eq!(status, 500), other => panic!("unexpected error {other:?}"), @@ -490,7 +490,7 @@ mod tests { #[test] fn download_dump_uses_environment_downloader() { let fetcher: ManifestFetcher = - Arc::new(|_orderbooks| Box::pin(async { Ok(HashMap::new()) })); + Arc::new(|_raindexes| Box::pin(async { Ok(HashMap::new()) })); let downloader: DumpDownloader = Arc::new(|_url| Box::pin(async { Ok("hello".to_string()) })); let environment = RunnerEnvironment::new( @@ -516,7 +516,7 @@ mod tests { #[test] fn download_dump_propagates_errors() { let fetcher: ManifestFetcher = - Arc::new(|_orderbooks| Box::pin(async { Ok(HashMap::new()) })); + Arc::new(|_raindexes| Box::pin(async { Ok(HashMap::new()) })); let downloader: DumpDownloader = Arc::new(|_url| { Box::pin(async { Err(LocalDbError::IoError(std::io::Error::other( @@ -548,7 +548,7 @@ mod tests { let marker = Arc::new(AtomicUsize::new(0)); let marker_clone = marker.clone(); let environment = RunnerEnvironment::new( - Arc::new(|_orderbooks| Box::pin(async { Ok(HashMap::new()) })), + Arc::new(|_raindexes| Box::pin(async { Ok(HashMap::new()) })), Arc::new(|_url| Box::pin(async { Ok("dump".into()) })), Arc::new(move |_target: &RunnerTarget| { marker_clone.fetch_add(1, Ordering::SeqCst); @@ -608,7 +608,7 @@ mod tests { StubApply, StubStatus, > = RunnerEnvironment::new( - Arc::new(|_orderbooks| Box::pin(async { Ok(HashMap::new()) })), + Arc::new(|_raindexes| Box::pin(async { Ok(HashMap::new()) })), Arc::new(|_url| Box::pin(async { Ok(String::new()) })), builder, ); @@ -623,7 +623,7 @@ mod tests { fn runner_environment_clone_shares_dependencies() { let fetch_counter = Arc::new(AtomicUsize::new(0)); let fetch_counter_clone = fetch_counter.clone(); - let fetcher: ManifestFetcher = Arc::new(move |_orderbooks| { + let fetcher: ManifestFetcher = Arc::new(move |_raindexes| { let counter = fetch_counter_clone.clone(); Box::pin(async move { counter.fetch_add(1, Ordering::SeqCst); @@ -689,8 +689,8 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a @@ -702,19 +702,19 @@ orderbooks: } #[cfg(not(target_family = "wasm"))] - fn update_remote_url(orderbooks: &mut HashMap, key: &str, url: &Url) { - if let Some(orderbook) = orderbooks.get_mut(key) { + fn update_remote_url(raindexes: &mut HashMap, key: &str, url: &Url) { + if let Some(raindex) = raindexes.get_mut(key) { let remote = LocalDbRemoteCfg { document: default_document(), - key: orderbook + key: raindex .local_db_remote .as_ref() - .expect("orderbook remote present") + .expect("raindex has remote") .key .clone(), url: url.clone(), }; - orderbook.local_db_remote = Some(Arc::new(remote)); + raindex.local_db_remote = Some(Arc::new(remote)); } } @@ -725,11 +725,11 @@ orderbooks: let manifest_yaml = format!( r#" manifest-version: {version} -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x00000000000000000000000000000000000000a1" dump-url: "{base}/dump.sql.gz" end-block: 123 @@ -749,10 +749,10 @@ networks: let mut parsed = parse_runner_settings(&sample_settings_yaml()).expect("sample settings"); let manifest_url = Url::parse(&server.base_url()).unwrap(); - update_remote_url(&mut parsed.orderbooks, "ob-a", &manifest_url); + update_remote_url(&mut parsed.raindexes, "raindex-a", &manifest_url); let fetcher = default_manifest_fetcher(); - let manifests = block_on(fetcher(&parsed.orderbooks)).expect("manifest map"); + let manifests = block_on(fetcher(&parsed.raindexes)).expect("manifest map"); assert_eq!(manifests.len(), 1); assert!(manifests.contains_key(&manifest_url)); } diff --git a/crates/common/src/local_db/pipeline/runner/mod.rs b/crates/common/src/local_db/pipeline/runner/mod.rs index 87e045567d..c03e25e507 100644 --- a/crates/common/src/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/local_db/pipeline/runner/mod.rs @@ -3,7 +3,7 @@ pub mod remotes; pub mod utils; use crate::local_db::pipeline::SyncOutcome; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; /// Stage at which a target can fail during a runner invocation. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -24,8 +24,8 @@ pub struct TargetSuccess { /// Failure result for a single target. #[derive(Debug)] pub struct TargetFailure { - pub ob_id: OrderbookIdentifier, - pub orderbook_key: Option, + pub raindex_id: RaindexIdentifier, + pub raindex_key: Option, pub stage: TargetStage, pub error: LocalDbError, } diff --git a/crates/common/src/local_db/pipeline/runner/remotes.rs b/crates/common/src/local_db/pipeline/runner/remotes.rs index de0e209908..0b0b5a022b 100644 --- a/crates/common/src/local_db/pipeline/runner/remotes.rs +++ b/crates/common/src/local_db/pipeline/runner/remotes.rs @@ -2,25 +2,25 @@ use super::utils::RunnerTarget; use crate::local_db::LocalDbError; use flate2::read::GzDecoder; use itertools::Itertools; -use rain_orderbook_app_settings::local_db_manifest::ManifestOrderbook; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; -use rain_orderbook_app_settings::remote::manifest::{fetch_multiple_manifests, ManifestMap}; +use raindex_app_settings::local_db_manifest::ManifestRaindex; +use raindex_app_settings::raindex::RaindexCfg; +use raindex_app_settings::remote::manifest::{fetch_multiple_manifests, ManifestMap}; use std::collections::HashMap; use std::io::Read; use url::Url; pub(crate) fn collect_manifest_urls( - orderbooks: &HashMap, + raindexes: &HashMap, ) -> Result, LocalDbError> { - let urls = orderbooks + let urls = raindexes .iter() - .map(|(key, orderbook)| { - orderbook + .map(|(key, raindex)| { + raindex .local_db_remote .as_ref() .map(|remote| remote.url.clone()) .ok_or_else(|| LocalDbError::MissingLocalDbRemote { - orderbook_key: key.clone(), + raindex_key: key.clone(), }) }) .collect::, _>>()?; @@ -28,11 +28,11 @@ pub(crate) fn collect_manifest_urls( Ok(urls.into_iter().unique().collect()) } -/// Fetches manifests for all distinct remotes referenced by the orderbooks. +/// Fetches manifests for all distinct remotes referenced by the raindexes. pub async fn get_manifests( - orderbooks: &HashMap, + raindexes: &HashMap, ) -> Result { - let urls = collect_manifest_urls(orderbooks)?; + let urls = collect_manifest_urls(raindexes)?; if urls.is_empty() { return Ok(HashMap::new()); } @@ -62,13 +62,13 @@ pub async fn download_and_gunzip(url: &Url) -> Result { pub fn lookup_manifest_entry( manifest_map: &ManifestMap, target: &RunnerTarget, -) -> Option { +) -> Option { manifest_map .get(&target.manifest_url) .and_then(|manifest| { manifest.find( - target.inputs.ob_id.chain_id, - target.inputs.ob_id.orderbook_address, + target.inputs.raindex_id.chain_id, + target.inputs.raindex_id.raindex_address, ) }) .cloned() @@ -80,14 +80,14 @@ mod tests { use alloy::primitives::{address, Bytes}; use flate2::write::GzEncoder; use httpmock::prelude::*; - use rain_orderbook_app_settings::local_db_manifest::{ - LocalDbManifest, ManifestNetwork, ManifestOrderbook, MANIFEST_VERSION, + use raindex_app_settings::local_db_manifest::{ + LocalDbManifest, ManifestNetwork, ManifestRaindex, MANIFEST_VERSION, }; - use rain_orderbook_app_settings::local_db_remotes::LocalDbRemoteCfg; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::remote::manifest::{FetchManifestError, ManifestMap}; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::default_document; + use raindex_app_settings::local_db_remotes::LocalDbRemoteCfg; + use raindex_app_settings::raindex::RaindexCfg; + use raindex_app_settings::remote::manifest::{FetchManifestError, ManifestMap}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::default_document; use std::collections::{HashMap, HashSet}; use std::io::Write; use std::sync::Arc; @@ -137,20 +137,20 @@ local-db-sync: finality-depth: 24 bootstrap-block-threshold: 5000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a local-db-remote: remote-a deployment-block: 111 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: network-b subgraph: network-b local-db-remote: remote-b deployment-block: 222 - ob-c: + raindex-c: address: 0x00000000000000000000000000000000000000c3 network: network-a subgraph: network-a @@ -169,16 +169,16 @@ orderbooks: Runtime::new().expect("tokio runtime") } - fn collect_urls_from_orderbooks(orderbooks: &HashMap) -> Vec { - collect_manifest_urls(orderbooks).expect("urls") + fn collect_urls_from_raindexes(raindexes: &HashMap) -> Vec { + collect_manifest_urls(raindexes).expect("urls") } - fn update_remote_url(orderbooks: &mut HashMap, key: &str, url: &Url) { - if let Some(orderbook) = orderbooks.get_mut(key) { - let remote_key = orderbook + fn update_remote_url(raindexes: &mut HashMap, key: &str, url: &Url) { + if let Some(raindex) = raindexes.get_mut(key) { + let remote_key = raindex .local_db_remote .as_ref() - .expect("orderbook has remote") + .expect("raindex has remote") .key .clone(); let remote = LocalDbRemoteCfg { @@ -186,20 +186,20 @@ orderbooks: key: remote_key, url: url.clone(), }; - orderbook.local_db_remote = Some(Arc::new(remote)); + raindex.local_db_remote = Some(Arc::new(remote)); } } fn sample_runner_target() -> (RunnerTarget, ManifestMap) { let parsed = parsed_settings(); - let targets = build_runner_targets(&parsed.orderbooks, &parsed.syncs).unwrap(); + let targets = build_runner_targets(&parsed.raindexes, &parsed.syncs).unwrap(); let target = targets .into_iter() - .find(|t| t.orderbook_key == "ob-a") - .expect("target ob-a"); + .find(|t| t.raindex_key == "raindex-a") + .expect("target raindex-a"); - let manifest_entry = ManifestOrderbook { - address: target.inputs.ob_id.orderbook_address, + let manifest_entry = ManifestRaindex { + address: target.inputs.raindex_id.raindex_address, dump_url: Url::parse("https://example.com/dump.sql.gz").unwrap(), end_block: 123, end_block_hash: Bytes::from_static(&[0x01, 0x02, 0x03]), @@ -212,8 +212,8 @@ orderbooks: networks: HashMap::from([( "network-a".to_string(), ManifestNetwork { - chain_id: target.inputs.ob_id.chain_id, - orderbooks: vec![manifest_entry.clone()], + chain_id: target.inputs.raindex_id.chain_id, + raindexes: vec![manifest_entry.clone()], }, )]), }; @@ -225,7 +225,7 @@ orderbooks: #[test] fn collect_manifest_urls_deduplicates() { let parsed = parsed_settings(); - let urls = collect_urls_from_orderbooks(&parsed.orderbooks); + let urls = collect_urls_from_raindexes(&parsed.raindexes); assert_eq!(urls.len(), 2); let unique: HashSet = urls.into_iter().collect(); @@ -238,13 +238,13 @@ orderbooks: } #[test] - fn collect_manifest_urls_handles_empty_orderbooks() { + fn collect_manifest_urls_handles_empty_raindexes() { let urls = collect_manifest_urls(&HashMap::new()).expect("empty vector"); assert!(urls.is_empty()); } #[test] - fn get_manifests_returns_empty_map_for_no_orderbooks() { + fn get_manifests_returns_empty_map_for_no_raindexes() { let rt = build_runtime(); let manifests = rt .block_on(get_manifests(&HashMap::new())) @@ -261,11 +261,11 @@ orderbooks: let manifest_one = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "https://example.com/dump1.sql.gz" end-block: 100 @@ -275,11 +275,11 @@ networks: let manifest_two = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: goerli: chain-id: 5 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000002" dump-url: "https://example.com/dump2.sql.gz" end-block: 200 @@ -304,12 +304,12 @@ networks: let mut parsed = parsed_settings(); let url_one = Url::parse(&server_one.base_url()).unwrap(); let url_two = Url::parse(&server_two.base_url()).unwrap(); - update_remote_url(&mut parsed.orderbooks, "ob-a", &url_one); - update_remote_url(&mut parsed.orderbooks, "ob-c", &url_one); - update_remote_url(&mut parsed.orderbooks, "ob-b", &url_two); + update_remote_url(&mut parsed.raindexes, "raindex-a", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-c", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-b", &url_two); let manifests = rt - .block_on(get_manifests(&parsed.orderbooks)) + .block_on(get_manifests(&parsed.raindexes)) .expect("manifests fetched"); assert_eq!(manifests.len(), 2); assert!(manifests.contains_key(&url_one)); @@ -325,13 +325,13 @@ networks: let manifest_one = format!( r#" manifest-version: {MANIFEST_VERSION} -db-schema-version: 2 +db-schema-version: 3 networks: {{}} "# ); let manifest_two = r#" manifest-version: 2 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; @@ -352,11 +352,11 @@ networks: {} let mut parsed = parsed_settings(); let url_one = Url::parse(&server_one.base_url()).unwrap(); let url_two = Url::parse(&server_two.base_url()).unwrap(); - update_remote_url(&mut parsed.orderbooks, "ob-a", &url_one); - update_remote_url(&mut parsed.orderbooks, "ob-c", &url_one); - update_remote_url(&mut parsed.orderbooks, "ob-b", &url_two); + update_remote_url(&mut parsed.raindexes, "raindex-a", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-c", &url_one); + update_remote_url(&mut parsed.raindexes, "raindex-b", &url_two); - let err = rt.block_on(get_manifests(&parsed.orderbooks)).unwrap_err(); + let err = rt.block_on(get_manifests(&parsed.raindexes)).unwrap_err(); match err { LocalDbError::ManifestFetch(FetchManifestError::Yaml(_)) => {} other => panic!("expected YAML manifest error, got {other:?}"), @@ -368,11 +368,11 @@ networks: {} let rt = build_runtime(); let mut parsed = parsed_settings(); let unreachable = Url::parse("nosuch://unreachable.example/manifest.yaml").unwrap(); - update_remote_url(&mut parsed.orderbooks, "ob-a", &unreachable); - update_remote_url(&mut parsed.orderbooks, "ob-b", &unreachable); - update_remote_url(&mut parsed.orderbooks, "ob-c", &unreachable); + update_remote_url(&mut parsed.raindexes, "raindex-a", &unreachable); + update_remote_url(&mut parsed.raindexes, "raindex-b", &unreachable); + update_remote_url(&mut parsed.raindexes, "raindex-c", &unreachable); - let err = rt.block_on(get_manifests(&parsed.orderbooks)).unwrap_err(); + let err = rt.block_on(get_manifests(&parsed.raindexes)).unwrap_err(); match err { LocalDbError::ManifestFetch(FetchManifestError::ReqwestError(_)) => {} other => panic!("expected HTTP manifest error, got {other:?}"), @@ -453,13 +453,13 @@ networks: {} fn lookup_manifest_entry_found() { let (target, manifest_map) = sample_runner_target(); let entry = lookup_manifest_entry(&manifest_map, &target).expect("entry found"); - assert_eq!(entry.address, target.inputs.ob_id.orderbook_address); + assert_eq!(entry.address, target.inputs.raindex_id.raindex_address); } #[test] fn lookup_manifest_entry_missing_address() { let (mut target, mut manifest_map) = sample_runner_target(); - target.inputs.ob_id.orderbook_address = + target.inputs.raindex_id.raindex_address = address!("000000000000000000000000000000000000dead"); assert!(lookup_manifest_entry(&manifest_map, &target).is_none()); @@ -472,7 +472,7 @@ networks: {} let (target, mut manifest_map) = sample_runner_target(); if let Some(manifest) = manifest_map.get_mut(&target.manifest_url) { if let Some(network) = manifest.networks.get_mut("network-a") { - network.chain_id = target.inputs.ob_id.chain_id + 1; + network.chain_id = target.inputs.raindex_id.chain_id + 1; } } diff --git a/crates/common/src/local_db/pipeline/runner/utils.rs b/crates/common/src/local_db/pipeline/runner/utils.rs index f2cdcef940..23c06c75eb 100644 --- a/crates/common/src/local_db/pipeline/runner/utils.rs +++ b/crates/common/src/local_db/pipeline/runner/utils.rs @@ -1,46 +1,46 @@ use crate::local_db::fetch::FetchConfig; use crate::local_db::pipeline::engine::SyncInputs; use crate::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; use itertools::Itertools; -use rain_orderbook_app_settings::local_db_sync::LocalDbSyncCfg; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; -use rain_orderbook_app_settings::yaml::orderbook::{OrderbookYaml, OrderbookYamlValidation}; -use rain_orderbook_app_settings::yaml::YamlParsable; +use raindex_app_settings::local_db_sync::LocalDbSyncCfg; +use raindex_app_settings::raindex::RaindexCfg; +use raindex_app_settings::yaml::raindex::{RaindexYaml, RaindexYamlValidation}; +use raindex_app_settings::yaml::YamlParsable; use std::collections::HashMap; use url::Url; /// Parsed settings required by the runner orchestration layer. #[derive(Debug, Clone)] pub struct ParsedRunnerSettings { - pub orderbooks: HashMap, + pub raindexes: HashMap, pub syncs: HashMap, } /// Scheduling metadata for a single engine invocation. #[derive(Debug, Clone)] pub struct RunnerTarget { - pub orderbook_key: String, + pub raindex_key: String, pub manifest_url: Url, pub network_key: String, pub inputs: SyncInputs, } -/// Parses the provided YAML string into orderbooks and per-network sync settings. +/// Parses the provided YAML string into raindexes and per-network sync settings. pub fn parse_runner_settings(settings_yaml: &str) -> Result { - let orderbook_yaml = OrderbookYaml::new( + let raindex_yaml = RaindexYaml::new( vec![settings_yaml.to_owned()], - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), )?; - parse_runner_settings_from_yaml(&orderbook_yaml) + parse_runner_settings_from_yaml(&raindex_yaml) } pub fn parse_runner_settings_from_yaml( - yaml: &OrderbookYaml, + yaml: &RaindexYaml, ) -> Result { - let orderbooks = yaml.get_orderbooks()?; + let raindexes = yaml.get_raindexes()?; let syncs = yaml.get_local_db_syncs()?; - Ok(ParsedRunnerSettings { orderbooks, syncs }) + Ok(ParsedRunnerSettings { raindexes, syncs }) } pub(crate) fn map_sync_to_engine( @@ -60,14 +60,14 @@ pub(crate) fn map_sync_to_engine( Ok((fetch, finality)) } -/// Builds runner targets for all configured orderbooks. +/// Builds runner targets for all configured raindexes. pub fn build_runner_targets( - orderbooks: &HashMap, + raindexes: &HashMap, syncs: &HashMap, ) -> Result, LocalDbError> { - let mut targets = Vec::with_capacity(orderbooks.len()); - for (key, orderbook) in orderbooks { - let network_key = orderbook.network.key.clone(); + let mut targets = Vec::with_capacity(raindexes.len()); + for (key, raindex) in raindexes { + let network_key = raindex.network.key.clone(); let sync_cfg = syncs .get(&network_key) @@ -76,10 +76,10 @@ pub fn build_runner_targets( })?; let (fetch, finality) = map_sync_to_engine(sync_cfg)?; let inputs = SyncInputs { - ob_id: OrderbookIdentifier::new(orderbook.network.chain_id, orderbook.address), - metadata_rpcs: orderbook.network.rpcs.clone(), + raindex_id: RaindexIdentifier::new(raindex.network.chain_id, raindex.address), + metadata_rpcs: raindex.network.rpcs.clone(), cfg: SyncConfig { - deployment_block: orderbook.deployment_block, + deployment_block: raindex.deployment_block, fetch, finality, window_overrides: WindowOverrides::default(), @@ -89,14 +89,16 @@ pub fn build_runner_targets( manifest_end_block: 0, }; - let remote = orderbook.local_db_remote.as_ref().ok_or_else(|| { - LocalDbError::MissingLocalDbRemote { - orderbook_key: key.clone(), - } - })?; + let remote = + raindex + .local_db_remote + .as_ref() + .ok_or_else(|| LocalDbError::MissingLocalDbRemote { + raindex_key: key.clone(), + })?; targets.push(RunnerTarget { - orderbook_key: key.clone(), + raindex_key: key.clone(), manifest_url: remote.url.clone(), network_key, inputs, @@ -109,7 +111,7 @@ pub fn build_runner_targets( /// Convenience helper retained for existing tests/utilities. pub fn build_sync_inputs_from_yaml(settings_yaml: &str) -> Result, LocalDbError> { let parsed = parse_runner_settings(settings_yaml)?; - let targets = build_runner_targets(&parsed.orderbooks, &parsed.syncs)?; + let targets = build_runner_targets(&parsed.raindexes, &parsed.syncs)?; Ok(targets.into_iter().map(|target| target.inputs).collect()) } @@ -127,9 +129,9 @@ mod tests { use crate::local_db::fetch::FetchConfigError; use crate::local_db::LocalDbError; use alloy::primitives::address; - use rain_orderbook_app_settings::local_db_sync::LocalDbSyncCfg; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::default_document; + use raindex_app_settings::local_db_sync::LocalDbSyncCfg; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::default_document; use url::Url; fn sample_settings_yaml() -> String { @@ -170,20 +172,20 @@ local-db-sync: finality-depth: 24 bootstrap-block-threshold: 5000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a local-db-remote: remote-a deployment-block: 111 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: network-b subgraph: network-b local-db-remote: remote-b deployment-block: 222 - ob-c: + raindex-c: address: 0x00000000000000000000000000000000000000c3 network: network-a subgraph: network-a @@ -211,7 +213,7 @@ subgraphs: mainnet: https://subgraph.network/mainnet local-db-remotes: remote: https://remotes.example.com/mainnet.yaml -orderbooks: +raindexes: book: address: 0x0000000000000000000000000000000000000001 network: mainnet @@ -238,9 +240,9 @@ orderbooks: #[test] fn parse_runner_settings_happy_path() { let parsed = parse_runner_settings(&sample_settings_yaml()).expect("parse succeeds"); - assert_eq!(parsed.orderbooks.len(), 3); + assert_eq!(parsed.raindexes.len(), 3); assert_eq!(parsed.syncs.len(), 2); - assert!(parsed.orderbooks.contains_key("ob-a")); + assert!(parsed.raindexes.contains_key("raindex-a")); assert!(parsed.syncs.contains_key("network-a")); } @@ -261,7 +263,7 @@ orderbooks: let is_missing_networks = matches!( err, LocalDbError::SettingsYaml(ref yaml_err) - if matches!(yaml_err, rain_orderbook_app_settings::yaml::YamlError::Field { .. }) + if matches!(yaml_err, raindex_app_settings::yaml::YamlError::Field { .. }) ); assert!( is_yaml_scan || is_missing_networks, @@ -325,18 +327,18 @@ orderbooks: fn build_runner_targets_success() { let parsed = parsed_settings(); let targets = - build_runner_targets(&parsed.orderbooks, &parsed.syncs).expect("targets build"); + build_runner_targets(&parsed.raindexes, &parsed.syncs).expect("targets build"); assert_eq!(targets.len(), 3); let target_a = targets .iter() - .find(|t| t.orderbook_key == "ob-a") - .expect("target for ob-a exists"); + .find(|t| t.raindex_key == "raindex-a") + .expect("target for raindex-a exists"); assert_eq!(target_a.network_key, "network-a"); - assert_eq!(target_a.inputs.ob_id.chain_id, 1); + assert_eq!(target_a.inputs.raindex_id.chain_id, 1); assert_eq!( - target_a.inputs.ob_id.orderbook_address, + target_a.inputs.raindex_id.raindex_address, address!("00000000000000000000000000000000000000a1") ); assert_eq!(target_a.inputs.cfg.deployment_block, 111); @@ -359,7 +361,7 @@ orderbooks: let mut syncs = parsed.syncs.clone(); syncs.remove("network-a"); - let err = build_runner_targets(&parsed.orderbooks, &syncs).unwrap_err(); + let err = build_runner_targets(&parsed.raindexes, &syncs).unwrap_err(); match err { LocalDbError::MissingLocalDbSyncForNetwork { network } => { assert_eq!(network, "network-a") @@ -376,7 +378,7 @@ orderbooks: sync.batch_size = 0; } - let err = build_runner_targets(&parsed.orderbooks, &syncs).unwrap_err(); + let err = build_runner_targets(&parsed.raindexes, &syncs).unwrap_err(); match err { LocalDbError::FetchConfigError(FetchConfigError::ChunkSizeZero(0)) => {} other => panic!("expected fetch config error, got {other:?}"), @@ -392,11 +394,11 @@ orderbooks: let input_b = inputs .iter() .find(|input| { - input.ob_id.orderbook_address + input.raindex_id.raindex_address == address!("00000000000000000000000000000000000000b2") }) - .expect("input for ob-b exists"); - assert_eq!(input_b.ob_id.chain_id, 2); + .expect("input for raindex-b exists"); + assert_eq!(input_b.raindex_id.chain_id, 2); assert_eq!(input_b.cfg.fetch.max_concurrent_requests(), 2); } @@ -414,7 +416,7 @@ orderbooks: #[test] fn group_targets_by_network_groups_correctly() { let parsed = parsed_settings(); - let targets = build_runner_targets(&parsed.orderbooks, &parsed.syncs).unwrap(); + let targets = build_runner_targets(&parsed.raindexes, &parsed.syncs).unwrap(); let grouped = group_targets_by_network(&targets); assert_eq!(grouped.len(), 2); diff --git a/crates/common/src/local_db/query/clear_orderbook_data/query.sql b/crates/common/src/local_db/query/clear_orderbook_data/query.sql deleted file mode 100644 index 20f2ae8e0a..0000000000 --- a/crates/common/src/local_db/query/clear_orderbook_data/query.sql +++ /dev/null @@ -1,54 +0,0 @@ -BEGIN TRANSACTION; - -DELETE FROM context_values -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM take_order_contexts -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM take_orders -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM order_ios -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM clear_v3_events -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM after_clear_v2_events -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM meta_events -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM interpreter_store_sets -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM raw_events -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM deposits -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM withdrawals -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM order_events -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM erc20_tokens -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM sync_status -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM target_watermarks -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM vault_balance_changes -WHERE chain_id = ?1 AND orderbook_address = ?2; - -DELETE FROM running_vault_balances -WHERE chain_id = ?1 AND orderbook_address = ?2; - -COMMIT; diff --git a/crates/common/src/local_db/query/clear_orderbook_data/mod.rs b/crates/common/src/local_db/query/clear_raindex_data/mod.rs similarity index 88% rename from crates/common/src/local_db/query/clear_orderbook_data/mod.rs rename to crates/common/src/local_db/query/clear_raindex_data/mod.rs index 3b3da1d7dd..636da7da1f 100644 --- a/crates/common/src/local_db/query/clear_orderbook_data/mod.rs +++ b/crates/common/src/local_db/query/clear_raindex_data/mod.rs @@ -1,20 +1,20 @@ use crate::local_db::query::create_tables::REQUIRED_TABLES; use crate::local_db::query::{SqlStatement, SqlStatementBatch, SqlValue}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; -pub const CLEAR_ORDERBOOK_DATA_SQL: &str = include_str!("query.sql"); +pub const CLEAR_RAINDEX_DATA_SQL: &str = include_str!("query.sql"); -pub fn clear_orderbook_data_batch(ob_id: &OrderbookIdentifier) -> SqlStatementBatch { +pub fn clear_raindex_data_batch(raindex_id: &RaindexIdentifier) -> SqlStatementBatch { let statements: Vec = REQUIRED_TABLES .iter() .copied() .filter(|table| *table != "db_metadata") .map(|table| { SqlStatement::new_with_params( - format!("DELETE FROM {table}\nWHERE chain_id = ?1 AND orderbook_address = ?2"), + format!("DELETE FROM {table}\nWHERE chain_id = ?1 AND raindex_address = ?2"), [ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), ], ) }) @@ -48,7 +48,7 @@ mod tests { fn batch_wraps_transaction_and_matches_tables() { let chain_id = 999u32; let addr = Address::from([0xAA; 20]); - let batch = clear_orderbook_data_batch(&OrderbookIdentifier::new(chain_id, addr)); + let batch = clear_raindex_data_batch(&RaindexIdentifier::new(chain_id, addr)); let expected_tables: Vec<&str> = REQUIRED_TABLES .iter() @@ -66,7 +66,7 @@ mod tests { for (idx, table) in expected_tables.iter().enumerate() { let stmt = &statements[idx + 1]; let expected_sql = - format!("DELETE FROM {table}\nWHERE chain_id = ?1 AND orderbook_address = ?2"); + format!("DELETE FROM {table}\nWHERE chain_id = ?1 AND raindex_address = ?2"); assert_eq!(stmt.sql(), expected_sql); assert_eq!( stmt.params(), @@ -80,7 +80,7 @@ mod tests { #[test] fn sql_covers_expected_tables() { - let sql = CLEAR_ORDERBOOK_DATA_SQL.to_ascii_lowercase(); + let sql = CLEAR_RAINDEX_DATA_SQL.to_ascii_lowercase(); let expected_tables: HashSet = REQUIRED_TABLES .iter() .copied() @@ -106,7 +106,7 @@ mod tests { }); let stmt = &stmt_rest[..stmt_end]; let has_chain_guard = stmt.contains("where chain_id = ?1"); - let has_address_guard = stmt.contains("orderbook_address = ?2"); + let has_address_guard = stmt.contains("raindex_address = ?2"); if !(has_chain_guard && has_address_guard) { tables_missing_scope.push(table_name.clone()); } diff --git a/crates/common/src/local_db/query/clear_raindex_data/query.sql b/crates/common/src/local_db/query/clear_raindex_data/query.sql new file mode 100644 index 0000000000..1753b600d4 --- /dev/null +++ b/crates/common/src/local_db/query/clear_raindex_data/query.sql @@ -0,0 +1,54 @@ +BEGIN TRANSACTION; + +DELETE FROM context_values +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM take_order_contexts +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM take_orders +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM order_ios +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM clear_v3_events +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM after_clear_v2_events +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM meta_events +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM interpreter_store_sets +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM raw_events +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM deposits +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM withdrawals +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM order_events +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM erc20_tokens +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM sync_status +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM target_watermarks +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM vault_balance_changes +WHERE chain_id = ?1 AND raindex_address = ?2; + +DELETE FROM running_vault_balances +WHERE chain_id = ?1 AND raindex_address = ?2; + +COMMIT; diff --git a/crates/common/src/local_db/query/create_tables/query.sql b/crates/common/src/local_db/query/create_tables/query.sql index e4cfa4882a..1e09727a18 100644 --- a/crates/common/src/local_db/query/create_tables/query.sql +++ b/crates/common/src/local_db/query/create_tables/query.sql @@ -8,27 +8,27 @@ CREATE TABLE IF NOT EXISTS db_metadata ( updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); --- Per-target watermarks keyed by (chain_id, orderbook_address) +-- Per-target watermarks keyed by (chain_id, raindex_address) CREATE TABLE IF NOT EXISTS target_watermarks ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, last_block INTEGER NOT NULL DEFAULT 0, last_hash TEXT, updated_at INTEGER NOT NULL DEFAULT (CAST(strftime('%s', 'now') AS INTEGER) * 1000), - PRIMARY KEY (chain_id, orderbook_address) + PRIMARY KEY (chain_id, raindex_address) ); CREATE TABLE IF NOT EXISTS sync_status ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, last_synced_block INTEGER NOT NULL DEFAULT 0, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (chain_id, orderbook_address) + PRIMARY KEY (chain_id, raindex_address) ); CREATE TABLE raw_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -37,14 +37,14 @@ CREATE TABLE raw_events ( topics TEXT NOT NULL, data TEXT NOT NULL, raw_json TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); -CREATE INDEX idx_raw_events_block ON raw_events(chain_id, orderbook_address, block_number, log_index); -CREATE INDEX idx_raw_events_address ON raw_events(chain_id, orderbook_address, address); +CREATE INDEX idx_raw_events_block ON raw_events(chain_id, raindex_address, block_number, log_index); +CREATE INDEX idx_raw_events_address ON raw_events(chain_id, raindex_address, address); CREATE TABLE deposits ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -54,12 +54,12 @@ CREATE TABLE deposits ( vault_id TEXT NOT NULL, deposit_amount TEXT NOT NULL, deposit_amount_uint256 TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); CREATE TABLE withdrawals ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -70,12 +70,12 @@ CREATE TABLE withdrawals ( target_amount TEXT NOT NULL, withdraw_amount TEXT NOT NULL, withdraw_amount_uint256 TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); CREATE TABLE order_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -88,27 +88,27 @@ CREATE TABLE order_events ( order_owner TEXT NOT NULL, order_nonce TEXT NOT NULL, order_bytes TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); CREATE TABLE order_ios ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, io_index INTEGER NOT NULL, io_type TEXT NOT NULL, token TEXT NOT NULL, vault_id TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index, io_index, io_type), + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index, io_index, io_type), FOREIGN KEY ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index ) REFERENCES order_events ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index ) @@ -116,7 +116,7 @@ CREATE TABLE order_ios ( CREATE TABLE take_orders ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -128,31 +128,31 @@ CREATE TABLE take_orders ( output_io_index INTEGER NOT NULL, taker_input TEXT NOT NULL, taker_output TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); CREATE TABLE take_order_contexts ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, context_index INTEGER NOT NULL, context_value TEXT NOT NULL, PRIMARY KEY ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index ), FOREIGN KEY ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index ) REFERENCES take_orders ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index ) @@ -160,7 +160,7 @@ CREATE TABLE take_order_contexts ( CREATE TABLE context_values ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, context_index INTEGER NOT NULL, @@ -168,7 +168,7 @@ CREATE TABLE context_values ( value TEXT NOT NULL, PRIMARY KEY ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index, @@ -176,13 +176,13 @@ CREATE TABLE context_values ( ), FOREIGN KEY ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index ) REFERENCES take_order_contexts ( chain_id, - orderbook_address, + raindex_address, transaction_hash, log_index, context_index @@ -191,7 +191,7 @@ CREATE TABLE context_values ( CREATE TABLE clear_v3_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -211,12 +211,12 @@ CREATE TABLE clear_v3_events ( bob_bounty_vault_id TEXT NOT NULL, bob_input_vault_id TEXT NOT NULL, bob_output_vault_id TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); CREATE TABLE after_clear_v2_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -226,12 +226,12 @@ CREATE TABLE after_clear_v2_events ( bob_output TEXT NOT NULL, alice_input TEXT NOT NULL, bob_input TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); CREATE TABLE meta_events ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, block_number INTEGER NOT NULL, @@ -239,51 +239,51 @@ CREATE TABLE meta_events ( sender TEXT NOT NULL, subject TEXT NOT NULL, meta TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); -CREATE INDEX idx_deposits_vault ON deposits(chain_id, orderbook_address, sender, token, vault_id); -CREATE INDEX idx_deposits_block ON deposits(chain_id, orderbook_address, block_number); -CREATE INDEX idx_deposits_token ON deposits(chain_id, orderbook_address, token); +CREATE INDEX idx_deposits_vault ON deposits(chain_id, raindex_address, sender, token, vault_id); +CREATE INDEX idx_deposits_block ON deposits(chain_id, raindex_address, block_number); +CREATE INDEX idx_deposits_token ON deposits(chain_id, raindex_address, token); -CREATE INDEX idx_withdrawals_vault ON withdrawals(chain_id, orderbook_address, sender, token, vault_id); -CREATE INDEX idx_withdrawals_block ON withdrawals(chain_id, orderbook_address, block_number); -CREATE INDEX idx_withdrawals_token ON withdrawals(chain_id, orderbook_address, token); +CREATE INDEX idx_withdrawals_vault ON withdrawals(chain_id, raindex_address, sender, token, vault_id); +CREATE INDEX idx_withdrawals_block ON withdrawals(chain_id, raindex_address, block_number); +CREATE INDEX idx_withdrawals_token ON withdrawals(chain_id, raindex_address, token); -CREATE INDEX idx_order_events_hash ON order_events(chain_id, orderbook_address, order_hash); -CREATE INDEX idx_order_events_owner ON order_events(chain_id, orderbook_address, order_owner); -CREATE INDEX idx_order_events_block ON order_events(chain_id, orderbook_address, block_number); -CREATE INDEX idx_order_events_store ON order_events(chain_id, orderbook_address, store_address); +CREATE INDEX idx_order_events_hash ON order_events(chain_id, raindex_address, order_hash); +CREATE INDEX idx_order_events_owner ON order_events(chain_id, raindex_address, order_owner); +CREATE INDEX idx_order_events_block ON order_events(chain_id, raindex_address, block_number); +CREATE INDEX idx_order_events_store ON order_events(chain_id, raindex_address, store_address); -CREATE INDEX idx_order_ios_token ON order_ios(chain_id, orderbook_address, token); +CREATE INDEX idx_order_ios_token ON order_ios(chain_id, raindex_address, token); -CREATE INDEX idx_take_orders_owner ON take_orders(chain_id, orderbook_address, order_owner); -CREATE INDEX idx_take_orders_block ON take_orders(chain_id, orderbook_address, block_number); +CREATE INDEX idx_take_orders_owner ON take_orders(chain_id, raindex_address, order_owner); +CREATE INDEX idx_take_orders_block ON take_orders(chain_id, raindex_address, block_number); -CREATE INDEX idx_clear_events_alice_bob ON clear_v3_events(chain_id, orderbook_address, alice_order_hash, bob_order_hash); -CREATE INDEX idx_clear_events_block ON clear_v3_events(chain_id, orderbook_address, block_number); -CREATE INDEX idx_clear_alice_vaults ON clear_v3_events(chain_id, orderbook_address, alice_input_vault_id, alice_output_vault_id); -CREATE INDEX idx_clear_bob_vaults ON clear_v3_events(chain_id, orderbook_address, bob_input_vault_id, bob_output_vault_id); +CREATE INDEX idx_clear_events_alice_bob ON clear_v3_events(chain_id, raindex_address, alice_order_hash, bob_order_hash); +CREATE INDEX idx_clear_events_block ON clear_v3_events(chain_id, raindex_address, block_number); +CREATE INDEX idx_clear_alice_vaults ON clear_v3_events(chain_id, raindex_address, alice_input_vault_id, alice_output_vault_id); +CREATE INDEX idx_clear_bob_vaults ON clear_v3_events(chain_id, raindex_address, bob_input_vault_id, bob_output_vault_id); -CREATE INDEX idx_after_clear_block ON after_clear_v2_events(chain_id, orderbook_address, block_number); +CREATE INDEX idx_after_clear_block ON after_clear_v2_events(chain_id, raindex_address, block_number); -CREATE INDEX idx_meta_subject ON meta_events(chain_id, orderbook_address, subject); -CREATE INDEX idx_meta_block ON meta_events(chain_id, orderbook_address, block_number); +CREATE INDEX idx_meta_subject ON meta_events(chain_id, raindex_address, subject); +CREATE INDEX idx_meta_block ON meta_events(chain_id, raindex_address, block_number); CREATE TABLE erc20_tokens ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, token_address TEXT NOT NULL, name TEXT NOT NULL, symbol TEXT NOT NULL, decimals INTEGER NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, token_address) + PRIMARY KEY (chain_id, raindex_address, token_address) ); CREATE INDEX idx_erc20_tokens_token - ON erc20_tokens(chain_id, orderbook_address, token_address); + ON erc20_tokens(chain_id, raindex_address, token_address); CREATE TABLE interpreter_store_sets ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, store_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, log_index INTEGER NOT NULL, @@ -292,15 +292,15 @@ CREATE TABLE interpreter_store_sets ( namespace TEXT NOT NULL, key TEXT NOT NULL, value TEXT NOT NULL, - PRIMARY KEY (chain_id, orderbook_address, transaction_hash, log_index) + PRIMARY KEY (chain_id, raindex_address, transaction_hash, log_index) ); -CREATE INDEX idx_store_sets_store ON interpreter_store_sets(chain_id, orderbook_address, store_address); -CREATE INDEX idx_store_sets_block ON interpreter_store_sets(chain_id, orderbook_address, block_number); -CREATE INDEX idx_store_sets_namespace ON interpreter_store_sets(chain_id, orderbook_address, namespace); +CREATE INDEX idx_store_sets_store ON interpreter_store_sets(chain_id, raindex_address, store_address); +CREATE INDEX idx_store_sets_block ON interpreter_store_sets(chain_id, raindex_address, block_number); +CREATE INDEX idx_store_sets_namespace ON interpreter_store_sets(chain_id, raindex_address, namespace); CREATE TABLE IF NOT EXISTS vault_balance_changes ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, transaction_hash TEXT NOT NULL, owner TEXT NOT NULL, token TEXT NOT NULL, @@ -313,7 +313,7 @@ CREATE TABLE IF NOT EXISTS vault_balance_changes ( running_balance TEXT NOT NULL, PRIMARY KEY ( chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, @@ -323,7 +323,7 @@ CREATE TABLE IF NOT EXISTS vault_balance_changes ( ); CREATE INDEX idx_vbc_timestamp ON vault_balance_changes( chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, @@ -334,7 +334,7 @@ CREATE INDEX idx_vbc_timestamp ON vault_balance_changes( CREATE TABLE IF NOT EXISTS running_vault_balances ( chain_id INTEGER NOT NULL, - orderbook_address TEXT NOT NULL, + raindex_address TEXT NOT NULL, owner TEXT NOT NULL, token TEXT NOT NULL, vault_id TEXT NOT NULL, @@ -342,9 +342,9 @@ CREATE TABLE IF NOT EXISTS running_vault_balances ( last_block INTEGER NOT NULL, last_log_index INTEGER NOT NULL, updated_at INTEGER NOT NULL DEFAULT (CAST(strftime('%s','now') AS INTEGER) * 1000), - PRIMARY KEY (chain_id, orderbook_address, owner, token, vault_id) + PRIMARY KEY (chain_id, raindex_address, owner, token, vault_id) ); -CREATE INDEX idx_rvb_owner ON running_vault_balances(chain_id, orderbook_address, owner); -CREATE INDEX idx_rvb_token ON running_vault_balances(chain_id, orderbook_address, token, vault_id); +CREATE INDEX idx_rvb_owner ON running_vault_balances(chain_id, raindex_address, owner); +CREATE INDEX idx_rvb_token ON running_vault_balances(chain_id, raindex_address, token, vault_id); COMMIT; diff --git a/crates/common/src/local_db/query/create_views/vault_deltas.sql b/crates/common/src/local_db/query/create_views/vault_deltas.sql index 246425b8eb..1422897c69 100644 --- a/crates/common/src/local_db/query/create_views/vault_deltas.sql +++ b/crates/common/src/local_db/query/create_views/vault_deltas.sql @@ -11,7 +11,7 @@ latest_order_events AS ( SELECT 1 FROM add_order_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_hash = oe.order_hash AND ( newer.block_number > oe.block_number @@ -20,7 +20,7 @@ latest_order_events AS ( ) ) SELECT d.chain_id, - d.orderbook_address, + d.raindex_address, d.transaction_hash, d.log_index, d.block_number, @@ -34,7 +34,7 @@ FROM deposits d UNION ALL SELECT w.chain_id, - w.orderbook_address, + w.raindex_address, w.transaction_hash, w.log_index, w.block_number, @@ -49,7 +49,7 @@ FROM withdrawals w UNION ALL -- maker buy: +taker_output SELECT t.chain_id, - t.orderbook_address, + t.raindex_address, t.transaction_hash, t.log_index, t.block_number, @@ -62,7 +62,7 @@ SELECT t.chain_id, FROM take_orders t JOIN add_order_events oe ON oe.chain_id = t.chain_id - AND oe.orderbook_address = t.orderbook_address + AND oe.raindex_address = t.raindex_address AND oe.order_owner = t.order_owner AND oe.order_nonce = t.order_nonce AND (oe.block_number < t.block_number @@ -70,7 +70,7 @@ JOIN add_order_events oe AND NOT EXISTS ( SELECT 1 FROM add_order_events x WHERE x.chain_id = t.chain_id - AND x.orderbook_address = t.orderbook_address + AND x.raindex_address = t.raindex_address AND x.order_owner = t.order_owner AND x.order_nonce = t.order_nonce AND (x.block_number < t.block_number @@ -80,7 +80,7 @@ JOIN add_order_events oe ) JOIN order_ios io ON io.chain_id = oe.chain_id - AND io.orderbook_address = oe.orderbook_address + AND io.raindex_address = oe.raindex_address AND io.transaction_hash = oe.transaction_hash AND io.log_index = oe.log_index AND io.io_index = t.input_io_index @@ -89,7 +89,7 @@ JOIN order_ios io UNION ALL -- maker sell: -taker_input SELECT t.chain_id, - t.orderbook_address, + t.raindex_address, t.transaction_hash, t.log_index, t.block_number, @@ -102,7 +102,7 @@ SELECT t.chain_id, FROM take_orders t JOIN add_order_events oe ON oe.chain_id = t.chain_id - AND oe.orderbook_address = t.orderbook_address + AND oe.raindex_address = t.raindex_address AND oe.order_owner = t.order_owner AND oe.order_nonce = t.order_nonce AND (oe.block_number < t.block_number @@ -110,7 +110,7 @@ JOIN add_order_events oe AND NOT EXISTS ( SELECT 1 FROM add_order_events x WHERE x.chain_id = t.chain_id - AND x.orderbook_address = t.orderbook_address + AND x.raindex_address = t.raindex_address AND x.order_owner = t.order_owner AND x.order_nonce = t.order_nonce AND (x.block_number < t.block_number @@ -120,7 +120,7 @@ JOIN add_order_events oe ) JOIN order_ios io ON io.chain_id = oe.chain_id - AND io.orderbook_address = oe.orderbook_address + AND io.raindex_address = oe.raindex_address AND io.transaction_hash = oe.transaction_hash AND io.log_index = oe.log_index AND io.io_index = t.output_io_index @@ -129,7 +129,7 @@ JOIN order_ios io UNION ALL -- clears (maker-oriented already) SELECT DISTINCT c.chain_id, - c.orderbook_address, + c.raindex_address, c.transaction_hash, c.log_index, c.block_number, @@ -142,23 +142,23 @@ SELECT DISTINCT c.chain_id, FROM clear_v3_events c JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN latest_order_events oeA ON oeA.chain_id = c.chain_id - AND oeA.orderbook_address = c.orderbook_address + AND oeA.raindex_address = c.raindex_address AND oeA.order_hash = c.alice_order_hash JOIN order_ios io_ai ON io_ai.chain_id = oeA.chain_id - AND io_ai.orderbook_address = oeA.orderbook_address + AND io_ai.raindex_address = oeA.raindex_address AND io_ai.transaction_hash = oeA.transaction_hash AND io_ai.log_index = oeA.log_index AND io_ai.io_index = c.alice_input_io_index @@ -166,7 +166,7 @@ JOIN order_ios io_ai UNION ALL SELECT DISTINCT c.chain_id, - c.orderbook_address, + c.raindex_address, c.transaction_hash, c.log_index, c.block_number, @@ -179,23 +179,23 @@ SELECT DISTINCT c.chain_id, FROM clear_v3_events c JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN latest_order_events oeA ON oeA.chain_id = c.chain_id - AND oeA.orderbook_address = c.orderbook_address + AND oeA.raindex_address = c.raindex_address AND oeA.order_hash = c.alice_order_hash JOIN order_ios io_ao ON io_ao.chain_id = oeA.chain_id - AND io_ao.orderbook_address = oeA.orderbook_address + AND io_ao.raindex_address = oeA.raindex_address AND io_ao.transaction_hash = oeA.transaction_hash AND io_ao.log_index = oeA.log_index AND io_ao.io_index = c.alice_output_io_index @@ -203,7 +203,7 @@ JOIN order_ios io_ao UNION ALL SELECT DISTINCT c.chain_id, - c.orderbook_address, + c.raindex_address, c.transaction_hash, c.log_index, c.block_number, @@ -216,23 +216,23 @@ SELECT DISTINCT c.chain_id, FROM clear_v3_events c JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN latest_order_events oeB ON oeB.chain_id = c.chain_id - AND oeB.orderbook_address = c.orderbook_address + AND oeB.raindex_address = c.raindex_address AND oeB.order_hash = c.bob_order_hash JOIN order_ios io_bi ON io_bi.chain_id = oeB.chain_id - AND io_bi.orderbook_address = oeB.orderbook_address + AND io_bi.raindex_address = oeB.raindex_address AND io_bi.transaction_hash = oeB.transaction_hash AND io_bi.log_index = oeB.log_index AND io_bi.io_index = c.bob_input_io_index @@ -240,7 +240,7 @@ JOIN order_ios io_bi UNION ALL SELECT DISTINCT c.chain_id, - c.orderbook_address, + c.raindex_address, c.transaction_hash, c.log_index, c.block_number, @@ -253,23 +253,23 @@ SELECT DISTINCT c.chain_id, FROM clear_v3_events c JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN latest_order_events oeB ON oeB.chain_id = c.chain_id - AND oeB.orderbook_address = c.orderbook_address + AND oeB.raindex_address = c.raindex_address AND oeB.order_hash = c.bob_order_hash JOIN order_ios io_bo ON io_bo.chain_id = oeB.chain_id - AND io_bo.orderbook_address = oeB.orderbook_address + AND io_bo.raindex_address = oeB.raindex_address AND io_bo.transaction_hash = oeB.transaction_hash AND io_bo.log_index = oeB.log_index AND io_bo.io_index = c.bob_output_io_index @@ -280,7 +280,7 @@ SELECT * FROM ( SELECT DISTINCT c.chain_id, - c.orderbook_address, + c.raindex_address, c.transaction_hash, c.log_index, c.block_number, @@ -300,23 +300,23 @@ FROM ( FROM clear_v3_events c JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN latest_order_events oeA ON oeA.chain_id = c.chain_id - AND oeA.orderbook_address = c.orderbook_address + AND oeA.raindex_address = c.raindex_address AND oeA.order_hash = c.alice_order_hash JOIN order_ios io_ao ON io_ao.chain_id = oeA.chain_id - AND io_ao.orderbook_address = oeA.orderbook_address + AND io_ao.raindex_address = oeA.raindex_address AND io_ao.transaction_hash = oeA.transaction_hash AND io_ao.log_index = oeA.log_index AND io_ao.io_index = c.alice_output_io_index @@ -329,7 +329,7 @@ SELECT * FROM ( SELECT DISTINCT c.chain_id, - c.orderbook_address, + c.raindex_address, c.transaction_hash, c.log_index, c.block_number, @@ -349,23 +349,23 @@ FROM ( FROM clear_v3_events c JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN latest_order_events oeB ON oeB.chain_id = c.chain_id - AND oeB.orderbook_address = c.orderbook_address + AND oeB.raindex_address = c.raindex_address AND oeB.order_hash = c.bob_order_hash JOIN order_ios io_bo ON io_bo.chain_id = oeB.chain_id - AND io_bo.orderbook_address = oeB.orderbook_address + AND io_bo.raindex_address = oeB.raindex_address AND io_bo.transaction_hash = oeB.transaction_hash AND io_bo.log_index = oeB.log_index AND io_bo.io_index = c.bob_output_io_index diff --git a/crates/common/src/local_db/query/fetch_all_tokens/mod.rs b/crates/common/src/local_db/query/fetch_all_tokens/mod.rs index 114d1229d3..db608dbcd1 100644 --- a/crates/common/src/local_db/query/fetch_all_tokens/mod.rs +++ b/crates/common/src/local_db/query/fetch_all_tokens/mod.rs @@ -8,7 +8,7 @@ pub const FETCH_ALL_TOKENS_SQL: &str = include_str!("query.sql"); #[serde(rename_all = "camelCase")] pub struct LocalDbToken { pub chain_id: u32, - pub orderbook_address: Address, + pub raindex_address: Address, pub token_address: Address, pub name: String, pub symbol: String, @@ -18,14 +18,14 @@ pub struct LocalDbToken { #[derive(Debug, Clone, Default)] pub struct FetchAllTokensArgs { pub chain_ids: Vec, - pub orderbook_addresses: Vec
, + pub raindex_addresses: Vec
, } const CHAIN_IDS_CLAUSE: &str = "/*CHAIN_IDS_CLAUSE*/"; const CHAIN_IDS_CLAUSE_BODY: &str = "AND chain_id IN ({list})"; -const ORDERBOOKS_CLAUSE: &str = "/*ORDERBOOKS_CLAUSE*/"; -const ORDERBOOKS_CLAUSE_BODY: &str = "AND orderbook_address IN ({list})"; +const RAINDEXES_CLAUSE: &str = "/*RAINDEXES_CLAUSE*/"; +const RAINDEXES_CLAUSE_BODY: &str = "AND raindex_address IN ({list})"; /// Builds the SQL statement used to load all unique ERC20 tokens from the local database. pub fn build_fetch_all_tokens_stmt( @@ -39,9 +39,9 @@ pub fn build_fetch_all_tokens_stmt( args.chain_ids.iter().cloned().map(SqlValue::from), )?; stmt.bind_list_clause( - ORDERBOOKS_CLAUSE, - ORDERBOOKS_CLAUSE_BODY, - args.orderbook_addresses.iter().cloned().map(SqlValue::from), + RAINDEXES_CLAUSE, + RAINDEXES_CLAUSE_BODY, + args.raindex_addresses.iter().cloned().map(SqlValue::from), )?; Ok(stmt) @@ -56,7 +56,7 @@ mod tests { let args = FetchAllTokensArgs::default(); let stmt = build_fetch_all_tokens_stmt(&args).expect("should build"); assert!(!stmt.sql.contains(CHAIN_IDS_CLAUSE)); - assert!(!stmt.sql.contains(ORDERBOOKS_CLAUSE)); + assert!(!stmt.sql.contains(RAINDEXES_CLAUSE)); assert!(stmt.params.is_empty()); } @@ -64,7 +64,7 @@ mod tests { fn builds_stmt_with_chain_ids() { let args = FetchAllTokensArgs { chain_ids: vec![1, 137], - orderbook_addresses: vec![], + raindex_addresses: vec![], }; let stmt = build_fetch_all_tokens_stmt(&args).expect("should build"); assert!(stmt.sql.contains("chain_id IN")); @@ -72,13 +72,13 @@ mod tests { } #[test] - fn builds_stmt_with_orderbook_addresses() { + fn builds_stmt_with_raindex_addresses() { let args = FetchAllTokensArgs { chain_ids: vec![], - orderbook_addresses: vec![Address::from([0xab; 20])], + raindex_addresses: vec![Address::from([0xab; 20])], }; let stmt = build_fetch_all_tokens_stmt(&args).expect("should build"); - assert!(stmt.sql.contains("orderbook_address IN")); + assert!(stmt.sql.contains("raindex_address IN")); assert_eq!(stmt.params.len(), 1); } } diff --git a/crates/common/src/local_db/query/fetch_all_tokens/query.sql b/crates/common/src/local_db/query/fetch_all_tokens/query.sql index 2343c8eaa9..92757f2f5f 100644 --- a/crates/common/src/local_db/query/fetch_all_tokens/query.sql +++ b/crates/common/src/local_db/query/fetch_all_tokens/query.sql @@ -1,7 +1,7 @@ -SELECT DISTINCT chain_id, orderbook_address, token_address, name, symbol, decimals +SELECT DISTINCT chain_id, raindex_address, token_address, name, symbol, decimals FROM erc20_tokens WHERE 1=1 /*CHAIN_IDS_CLAUSE*/ - /*ORDERBOOKS_CLAUSE*/ -ORDER BY chain_id, orderbook_address, token_address; + /*RAINDEXES_CLAUSE*/ +ORDER BY chain_id, raindex_address, token_address; diff --git a/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/mod.rs b/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/mod.rs index 7e166859cb..668e7fd75c 100644 --- a/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/mod.rs +++ b/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlBuildError, SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::Address; use serde::{Deserialize, Serialize}; @@ -10,7 +10,7 @@ pub const FETCH_ERC20_TOKENS_BY_ADDRESSES_SQL: &str = include_str!("query.sql"); #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Erc20TokenRow { pub chain_id: u32, - pub orderbook_address: Address, + pub raindex_address: Address, pub token_address: Address, pub name: String, pub symbol: String, @@ -24,7 +24,7 @@ const ADDRESSES_CLAUSE_BODY: &str = "AND token_address IN ({list})"; /// addresses. Returns `Ok(None)` when the address list is empty to allow /// callers to short-circuit database work. pub fn build_fetch_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, addresses: &[Address], ) -> Result, SqlBuildError> { if addresses.is_empty() { @@ -32,8 +32,8 @@ pub fn build_fetch_stmt( } let mut stmt = SqlStatement::new(FETCH_ERC20_TOKENS_BY_ADDRESSES_SQL); - stmt.push(ob_id.chain_id); - stmt.push(ob_id.orderbook_address); + stmt.push(raindex_id.chain_id); + stmt.push(raindex_id.raindex_address); // IN list for addresses stmt.bind_list_clause( ADDRESSES_CLAUSE, @@ -50,7 +50,7 @@ mod tests { #[test] fn empty_addresses_returns_none() { let q = - build_fetch_stmt(&OrderbookIdentifier::new(1, Address::from([0xbe; 20])), &[]).unwrap(); + build_fetch_stmt(&RaindexIdentifier::new(1, Address::from([0xbe; 20])), &[]).unwrap(); assert!(q.is_none()); } @@ -59,8 +59,8 @@ mod tests { let address_a = Address::from([0xab; 20]); let address_b = Address::from([0xcd; 20]); let addrs = vec![address_a, address_b]; - let orderbook = Address::from([0xbe; 20]); - let stmt = build_fetch_stmt(&OrderbookIdentifier::new(137, orderbook), &addrs) + let raindex = Address::from([0xbe; 20]); + let stmt = build_fetch_stmt(&RaindexIdentifier::new(137, raindex), &addrs) .expect("should build") .unwrap(); @@ -68,7 +68,7 @@ mod tests { assert!(stmt.sql.contains("WHERE chain_id = ?1")); assert!(!stmt.sql.contains(ADDRESSES_CLAUSE)); - // Params: chain id, orderbook address, then addresses + // Params: chain id, raindex address, then addresses assert_eq!(stmt.params.len(), 4); assert_eq!(stmt.params[0], SqlValue::U64(137)); assert_eq!( diff --git a/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/query.sql b/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/query.sql index e3b04f4fec..b8bb21a6dd 100644 --- a/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/query.sql +++ b/crates/common/src/local_db/query/fetch_erc20_tokens_by_addresses/query.sql @@ -1,4 +1,4 @@ -SELECT chain_id, orderbook_address, token_address, name, symbol, decimals +SELECT chain_id, raindex_address, token_address, name, symbol, decimals FROM erc20_tokens -WHERE chain_id = ?1 AND orderbook_address = ?2 +WHERE chain_id = ?1 AND raindex_address = ?2 /*ADDRESSES_CLAUSE*/; diff --git a/crates/common/src/local_db/query/fetch_last_synced_block/mod.rs b/crates/common/src/local_db/query/fetch_last_synced_block/mod.rs index 621ed40ae1..1c17323ae8 100644 --- a/crates/common/src/local_db/query/fetch_last_synced_block/mod.rs +++ b/crates/common/src/local_db/query/fetch_last_synced_block/mod.rs @@ -1,5 +1,5 @@ use super::SqlValue; -use crate::local_db::{query::SqlStatement, OrderbookIdentifier}; +use crate::local_db::{query::SqlStatement, RaindexIdentifier}; use serde::{Deserialize, Serialize}; #[cfg(target_family = "wasm")] use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; @@ -11,8 +11,8 @@ pub const FETCH_LAST_SYNCED_BLOCK_SQL: &str = include_str!("query.sql"); pub struct SyncStatusResponse { #[serde(alias = "chainId")] pub chain_id: u32, - #[serde(alias = "orderbookAddress")] - pub orderbook_address: String, + #[serde(alias = "raindexAddress")] + pub raindex_address: String, #[serde(alias = "lastSyncedBlock")] pub last_synced_block: u64, #[serde(alias = "updatedAt")] @@ -21,12 +21,12 @@ pub struct SyncStatusResponse { #[cfg(target_family = "wasm")] impl_wasm_traits!(SyncStatusResponse); -pub fn fetch_last_synced_block_stmt(ob_id: &OrderbookIdentifier) -> SqlStatement { +pub fn fetch_last_synced_block_stmt(raindex_id: &RaindexIdentifier) -> SqlStatement { SqlStatement::new_with_params( FETCH_LAST_SYNCED_BLOCK_SQL, [ - SqlValue::from(ob_id.chain_id as u64), - SqlValue::from(ob_id.orderbook_address.to_string()), + SqlValue::from(raindex_id.chain_id as u64), + SqlValue::from(raindex_id.raindex_address.to_string()), ], ) } @@ -40,7 +40,7 @@ mod tests { #[test] fn stmt_is_static_and_param_free() { let addr = Address::from([0x22u8; 20]); - let stmt = fetch_last_synced_block_stmt(&OrderbookIdentifier::new(42161, addr)); + let stmt = fetch_last_synced_block_stmt(&RaindexIdentifier::new(42161, addr)); assert_eq!(stmt.sql, FETCH_LAST_SYNCED_BLOCK_SQL); assert_eq!(stmt.params.len(), 2); assert_eq!(stmt.params[0], SqlValue::U64(42161)); diff --git a/crates/common/src/local_db/query/fetch_last_synced_block/query.sql b/crates/common/src/local_db/query/fetch_last_synced_block/query.sql index 60568be2ce..dffe50139d 100644 --- a/crates/common/src/local_db/query/fetch_last_synced_block/query.sql +++ b/crates/common/src/local_db/query/fetch_last_synced_block/query.sql @@ -1,8 +1,8 @@ SELECT chain_id, - orderbook_address, + raindex_address, last_synced_block, updated_at FROM sync_status WHERE chain_id = ?1 - AND orderbook_address = ?2; + AND raindex_address = ?2; diff --git a/crates/common/src/local_db/query/fetch_order_trades/mod.rs b/crates/common/src/local_db/query/fetch_order_trades/mod.rs index f837a23817..63fb3ac8a5 100644 --- a/crates/common/src/local_db/query/fetch_order_trades/mod.rs +++ b/crates/common/src/local_db/query/fetch_order_trades/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlBuildError, SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::{Address, B256, U256}; use serde::{Deserialize, Serialize}; @@ -10,7 +10,7 @@ const QUERY_TEMPLATE: &str = include_str!("query.sql"); #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct LocalDbOrderTrade { pub trade_kind: String, - pub orderbook: Address, + pub raindex: Address, pub order_hash: B256, pub order_owner: Address, pub order_nonce: String, @@ -44,14 +44,14 @@ const END_TS_CLAUSE: &str = "/*END_TS_CLAUSE*/"; const END_TS_BODY: &str = "\nAND tws.block_timestamp <= {param}\n"; pub fn build_fetch_order_trades_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { let mut stmt = SqlStatement::new(QUERY_TEMPLATE); - stmt.push(SqlValue::from(ob_id.chain_id)); - stmt.push(SqlValue::from(ob_id.orderbook_address)); + stmt.push(SqlValue::from(raindex_id.chain_id)); + stmt.push(SqlValue::from(raindex_id.raindex_address)); stmt.push(SqlValue::from(order_hash)); // Optional time filters @@ -94,7 +94,7 @@ mod tests { let order_hash = b256!("0x00000000000000000000000000000000000000000000000000000000deadface"); let stmt = build_fetch_order_trades_stmt( - &OrderbookIdentifier::new(137, Address::ZERO), + &RaindexIdentifier::new(137, Address::ZERO), order_hash, Some(11), Some(22), @@ -105,7 +105,7 @@ mod tests { assert!(!stmt.sql.contains(END_TS_CLAUSE)); assert!(stmt.sql.contains("tws.block_timestamp >=")); assert!(stmt.sql.contains("tws.block_timestamp <=")); - // First three fixed params: chain id (?1), orderbook address (?2), order hash (?3) + // First three fixed params: chain id (?1), raindex address (?2), order hash (?3) assert_eq!(stmt.params.len(), 5); // includes start and end assert_eq!(stmt.params[0], SqlValue::U64(137)); assert_eq!(stmt.params[1], SqlValue::Text(Address::ZERO.to_string())); @@ -120,7 +120,7 @@ mod tests { let order_hash = b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"); let stmt = build_fetch_order_trades_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), order_hash, None, None, @@ -131,7 +131,7 @@ mod tests { assert!(!stmt.sql.contains(START_TS_CLAUSE)); assert!(!stmt.sql.contains(END_TS_CLAUSE)); assert_eq!(stmt.params.len(), 3); - // Order of fixed params: chain id (?1), orderbook (?2), order hash (?3) + // Order of fixed params: chain id (?1), raindex (?2), order hash (?3) assert_eq!(stmt.params[0], SqlValue::U64(1)); assert_eq!(stmt.params[1], SqlValue::Text(Address::ZERO.to_string())); assert_eq!( diff --git a/crates/common/src/local_db/query/fetch_order_trades/query.sql b/crates/common/src/local_db/query/fetch_order_trades/query.sql index d50b5392f4..9705e77436 100644 --- a/crates/common/src/local_db/query/fetch_order_trades/query.sql +++ b/crates/common/src/local_db/query/fetch_order_trades/query.sql @@ -2,13 +2,13 @@ WITH params AS ( SELECT ?1 AS chain_id, - ?2 AS orderbook_address, + ?2 AS raindex_address, ?3 AS order_hash ), order_add_events AS ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.transaction_hash, oe.log_index, oe.block_number, @@ -19,7 +19,7 @@ order_add_events AS ( FROM order_events oe JOIN params p ON oe.chain_id = p.chain_id - AND oe.orderbook_address = p.orderbook_address + AND oe.raindex_address = p.raindex_address AND oe.order_hash = p.order_hash WHERE oe.event_type = 'AddOrderV3' ), @@ -27,7 +27,7 @@ take_trades AS ( SELECT 'take' AS trade_kind, t.chain_id, - t.orderbook_address, + t.raindex_address, oe.order_hash, t.order_owner, t.order_nonce, @@ -45,10 +45,10 @@ take_trades AS ( FROM take_orders t JOIN params p ON t.chain_id = p.chain_id - AND t.orderbook_address = p.orderbook_address + AND t.raindex_address = p.raindex_address JOIN order_add_events oe ON oe.chain_id = t.chain_id - AND oe.orderbook_address = t.orderbook_address + AND oe.raindex_address = t.raindex_address AND oe.order_owner = t.order_owner AND oe.order_nonce = t.order_nonce AND ( @@ -59,7 +59,7 @@ take_trades AS ( SELECT 1 FROM order_add_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_owner = oe.order_owner AND newer.order_nonce = oe.order_nonce AND ( @@ -73,14 +73,14 @@ take_trades AS ( ) JOIN order_ios io_in ON io_in.chain_id = oe.chain_id - AND io_in.orderbook_address = oe.orderbook_address + AND io_in.raindex_address = oe.raindex_address AND io_in.transaction_hash = oe.transaction_hash AND io_in.log_index = oe.log_index AND io_in.io_index = t.input_io_index AND io_in.io_type = 'input' JOIN order_ios io_out ON io_out.chain_id = oe.chain_id - AND io_out.orderbook_address = oe.orderbook_address + AND io_out.raindex_address = oe.raindex_address AND io_out.transaction_hash = oe.transaction_hash AND io_out.log_index = oe.log_index AND io_out.io_index = t.output_io_index @@ -90,7 +90,7 @@ clear_alice AS ( SELECT DISTINCT 'clear' AS trade_kind, c.chain_id, - c.orderbook_address, + c.raindex_address, oe.order_hash, oe.order_owner, oe.order_nonce, @@ -108,10 +108,10 @@ clear_alice AS ( FROM clear_v3_events c JOIN params p ON c.chain_id = p.chain_id - AND c.orderbook_address = p.orderbook_address + AND c.raindex_address = p.raindex_address JOIN order_add_events oe ON oe.chain_id = c.chain_id - AND oe.orderbook_address = c.orderbook_address + AND oe.raindex_address = c.raindex_address AND oe.order_hash = c.alice_order_hash AND ( oe.block_number < c.block_number @@ -121,7 +121,7 @@ clear_alice AS ( SELECT 1 FROM order_add_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_hash = oe.order_hash AND ( newer.block_number < c.block_number @@ -134,26 +134,26 @@ clear_alice AS ( ) JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN order_ios io_in ON io_in.chain_id = oe.chain_id - AND io_in.orderbook_address = oe.orderbook_address + AND io_in.raindex_address = oe.raindex_address AND io_in.transaction_hash = oe.transaction_hash AND io_in.log_index = oe.log_index AND io_in.io_index = c.alice_input_io_index AND io_in.io_type = 'input' JOIN order_ios io_out ON io_out.chain_id = oe.chain_id - AND io_out.orderbook_address = oe.orderbook_address + AND io_out.raindex_address = oe.raindex_address AND io_out.transaction_hash = oe.transaction_hash AND io_out.log_index = oe.log_index AND io_out.io_index = c.alice_output_io_index @@ -164,7 +164,7 @@ clear_bob AS ( SELECT DISTINCT 'clear' AS trade_kind, c.chain_id, - c.orderbook_address, + c.raindex_address, oe.order_hash, oe.order_owner, oe.order_nonce, @@ -182,10 +182,10 @@ clear_bob AS ( FROM clear_v3_events c JOIN params p ON c.chain_id = p.chain_id - AND c.orderbook_address = p.orderbook_address + AND c.raindex_address = p.raindex_address JOIN order_add_events oe ON oe.chain_id = c.chain_id - AND oe.orderbook_address = c.orderbook_address + AND oe.raindex_address = c.raindex_address AND oe.order_hash = c.bob_order_hash AND ( oe.block_number < c.block_number @@ -195,7 +195,7 @@ clear_bob AS ( SELECT 1 FROM order_add_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_hash = oe.order_hash AND ( newer.block_number < c.block_number @@ -208,26 +208,26 @@ clear_bob AS ( ) JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN order_ios io_in ON io_in.chain_id = oe.chain_id - AND io_in.orderbook_address = oe.orderbook_address + AND io_in.raindex_address = oe.raindex_address AND io_in.transaction_hash = oe.transaction_hash AND io_in.log_index = oe.log_index AND io_in.io_index = c.bob_input_io_index AND io_in.io_type = 'input' JOIN order_ios io_out ON io_out.chain_id = oe.chain_id - AND io_out.orderbook_address = oe.orderbook_address + AND io_out.raindex_address = oe.raindex_address AND io_out.transaction_hash = oe.transaction_hash AND io_out.log_index = oe.log_index AND io_out.io_index = c.bob_output_io_index @@ -248,7 +248,7 @@ trade_rows AS ( SELECT ut.trade_kind, ut.chain_id, - ut.orderbook_address, + ut.raindex_address, ut.order_hash, ut.order_owner, ut.order_nonce, @@ -277,20 +277,20 @@ trade_with_snapshots AS ( FROM trade_rows tr LEFT JOIN running_vault_balances mvb_in ON mvb_in.chain_id = tr.chain_id - AND mvb_in.orderbook_address = tr.orderbook_address + AND mvb_in.raindex_address = tr.raindex_address AND mvb_in.owner = tr.order_owner AND mvb_in.token = tr.input_token AND mvb_in.vault_id = tr.input_vault_id LEFT JOIN running_vault_balances mvb_out ON mvb_out.chain_id = tr.chain_id - AND mvb_out.orderbook_address = tr.orderbook_address + AND mvb_out.raindex_address = tr.raindex_address AND mvb_out.owner = tr.order_owner AND mvb_out.token = tr.output_token AND mvb_out.vault_id = tr.output_vault_id ) SELECT tws.trade_kind, - tws.orderbook_address AS orderbook, + tws.raindex_address AS raindex, tws.order_hash, tws.order_owner, tws.order_nonce, @@ -321,7 +321,7 @@ SELECT FROM trade_with_snapshots tws LEFT JOIN vault_balance_changes vbc_input ON vbc_input.chain_id = tws.chain_id - AND vbc_input.orderbook_address = tws.orderbook_address + AND vbc_input.raindex_address = tws.raindex_address AND vbc_input.owner = tws.order_owner AND vbc_input.token = tws.input_token AND vbc_input.vault_id = tws.input_vault_id @@ -329,7 +329,7 @@ LEFT JOIN vault_balance_changes vbc_input AND vbc_input.log_index = tws.log_index LEFT JOIN vault_balance_changes vbc_output ON vbc_output.chain_id = tws.chain_id - AND vbc_output.orderbook_address = tws.orderbook_address + AND vbc_output.raindex_address = tws.raindex_address AND vbc_output.owner = tws.order_owner AND vbc_output.token = tws.output_token AND vbc_output.vault_id = tws.output_vault_id @@ -337,11 +337,11 @@ LEFT JOIN vault_balance_changes vbc_output AND vbc_output.log_index = tws.log_index LEFT JOIN erc20_tokens tok_in ON tok_in.chain_id = tws.chain_id - AND tok_in.orderbook_address = tws.orderbook_address + AND tok_in.raindex_address = tws.raindex_address AND tok_in.token_address = tws.input_token LEFT JOIN erc20_tokens tok_out ON tok_out.chain_id = tws.chain_id - AND tok_out.orderbook_address = tws.orderbook_address + AND tok_out.raindex_address = tws.raindex_address AND tok_out.token_address = tws.output_token WHERE 1 = 1 /*START_TS_CLAUSE*/ diff --git a/crates/common/src/local_db/query/fetch_order_trades_count/mod.rs b/crates/common/src/local_db/query/fetch_order_trades_count/mod.rs index 87b105be91..26cd753556 100644 --- a/crates/common/src/local_db/query/fetch_order_trades_count/mod.rs +++ b/crates/common/src/local_db/query/fetch_order_trades_count/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlBuildError, SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::B256; use serde::{Deserialize, Serialize}; @@ -20,14 +20,14 @@ const END_TS_CLAUSE: &str = "/*END_TS_CLAUSE*/"; const END_TS_BODY: &str = "\nAND block_timestamp <= {param}\n"; pub fn build_fetch_trade_count_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { let mut stmt = SqlStatement::new(QUERY_TEMPLATE); - stmt.push(SqlValue::from(ob_id.chain_id)); - stmt.push(SqlValue::from(ob_id.orderbook_address)); + stmt.push(SqlValue::from(raindex_id.chain_id)); + stmt.push(SqlValue::from(raindex_id.raindex_address)); stmt.push(SqlValue::from(order_hash)); // Optional time filters @@ -75,7 +75,7 @@ mod tests { #[test] fn builds_with_time_filters() { let stmt = build_fetch_trade_count_stmt( - &OrderbookIdentifier::new(137, Address::ZERO), + &RaindexIdentifier::new(137, Address::ZERO), b256!("0x0000000000000000000000000000000000000000000000000000000000ABCDEF"), Some(1000), Some(2000), @@ -101,7 +101,7 @@ mod tests { #[test] fn builds_without_time_filters_when_none() { let stmt = build_fetch_trade_count_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"), None, None, diff --git a/crates/common/src/local_db/query/fetch_order_trades_count/query.sql b/crates/common/src/local_db/query/fetch_order_trades_count/query.sql index 0558e6f1b3..c26ff4a244 100644 --- a/crates/common/src/local_db/query/fetch_order_trades_count/query.sql +++ b/crates/common/src/local_db/query/fetch_order_trades_count/query.sql @@ -4,7 +4,7 @@ FROM ( FROM take_orders t JOIN order_events oe ON oe.chain_id = ?1 - AND oe.orderbook_address = ?2 + AND oe.raindex_address = ?2 AND oe.order_hash = ?3 AND oe.event_type = 'AddOrderV3' AND oe.order_owner = t.order_owner @@ -17,7 +17,7 @@ FROM ( SELECT 1 FROM order_events oe2 WHERE oe2.chain_id = ?1 - AND oe2.orderbook_address = ?2 + AND oe2.raindex_address = ?2 AND oe2.order_hash = ?3 AND oe2.event_type = 'AddOrderV3' AND oe2.order_owner = t.order_owner @@ -32,7 +32,7 @@ FROM ( ) ) WHERE t.chain_id = ?1 - AND t.orderbook_address = ?2 + AND t.raindex_address = ?2 UNION ALL @@ -40,7 +40,7 @@ FROM ( FROM clear_v3_events c JOIN order_events oe ON oe.chain_id = ?1 - AND oe.orderbook_address = ?2 + AND oe.raindex_address = ?2 AND oe.order_hash = c.alice_order_hash AND oe.event_type = 'AddOrderV3' AND ( @@ -51,7 +51,7 @@ FROM ( SELECT 1 FROM order_events oe2 WHERE oe2.chain_id = ?1 - AND oe2.orderbook_address = ?2 + AND oe2.raindex_address = ?2 AND oe2.order_hash = c.alice_order_hash AND oe2.event_type = 'AddOrderV3' AND ( @@ -64,7 +64,7 @@ FROM ( ) ) WHERE c.chain_id = ?1 - AND c.orderbook_address = ?2 + AND c.raindex_address = ?2 AND c.alice_order_hash = ?3 UNION ALL @@ -73,7 +73,7 @@ FROM ( FROM clear_v3_events c JOIN order_events oe ON oe.chain_id = ?1 - AND oe.orderbook_address = ?2 + AND oe.raindex_address = ?2 AND oe.order_hash = c.bob_order_hash AND oe.event_type = 'AddOrderV3' AND ( @@ -84,7 +84,7 @@ FROM ( SELECT 1 FROM order_events oe2 WHERE oe2.chain_id = ?1 - AND oe2.orderbook_address = ?2 + AND oe2.raindex_address = ?2 AND oe2.order_hash = c.bob_order_hash AND oe2.event_type = 'AddOrderV3' AND ( @@ -97,7 +97,7 @@ FROM ( ) ) WHERE c.chain_id = ?1 - AND c.orderbook_address = ?2 + AND c.raindex_address = ?2 AND c.bob_order_hash = ?3 ) AS combined_trades WHERE 1=1 diff --git a/crates/common/src/local_db/query/fetch_order_vaults_volume/mod.rs b/crates/common/src/local_db/query/fetch_order_vaults_volume/mod.rs index cef7efc4d7..1f75499014 100644 --- a/crates/common/src/local_db/query/fetch_order_vaults_volume/mod.rs +++ b/crates/common/src/local_db/query/fetch_order_vaults_volume/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlBuildError, SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::{Address, B256, U256}; use serde::{Deserialize, Serialize}; @@ -25,14 +25,14 @@ const END_TS_CLAUSE: &str = "/*END_TS_CLAUSE*/"; const END_TS_BODY: &str = "\nAND block_timestamp <= {param}\n"; pub fn build_fetch_order_vaults_volume_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { let mut stmt = SqlStatement::new(QUERY_TEMPLATE); - stmt.push(SqlValue::from(ob_id.chain_id)); - stmt.push(SqlValue::from(ob_id.orderbook_address)); + stmt.push(SqlValue::from(raindex_id.chain_id)); + stmt.push(SqlValue::from(raindex_id.raindex_address)); stmt.push(SqlValue::from(order_hash)); let start_param = if let Some(v) = start_timestamp { @@ -74,7 +74,7 @@ mod tests { let order_hash = b256!("0x00000000000000000000000000000000000000000000000000000000deadface"); let stmt = build_fetch_order_vaults_volume_stmt( - &OrderbookIdentifier::new(137, Address::ZERO), + &RaindexIdentifier::new(137, Address::ZERO), order_hash, Some(11), Some(22), @@ -98,7 +98,7 @@ mod tests { let order_hash = b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"); let stmt = build_fetch_order_vaults_volume_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), order_hash, None, None, diff --git a/crates/common/src/local_db/query/fetch_order_vaults_volume/query.sql b/crates/common/src/local_db/query/fetch_order_vaults_volume/query.sql index 869678ca9e..653dddc6c2 100644 --- a/crates/common/src/local_db/query/fetch_order_vaults_volume/query.sql +++ b/crates/common/src/local_db/query/fetch_order_vaults_volume/query.sql @@ -2,13 +2,13 @@ WITH params AS ( SELECT ?1 AS chain_id, - ?2 AS orderbook_address, + ?2 AS raindex_address, ?3 AS order_hash ), order_add_events AS ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.transaction_hash, oe.log_index, oe.block_number, @@ -19,7 +19,7 @@ order_add_events AS ( FROM order_events oe JOIN params p ON oe.chain_id = p.chain_id - AND oe.orderbook_address = p.orderbook_address + AND oe.raindex_address = p.raindex_address AND oe.order_hash = p.order_hash WHERE oe.event_type = 'AddOrderV3' ), @@ -35,10 +35,10 @@ take_trades AS ( FROM take_orders t JOIN params p ON t.chain_id = p.chain_id - AND t.orderbook_address = p.orderbook_address + AND t.raindex_address = p.raindex_address JOIN order_add_events oe ON oe.chain_id = t.chain_id - AND oe.orderbook_address = t.orderbook_address + AND oe.raindex_address = t.raindex_address AND oe.order_owner = t.order_owner AND oe.order_nonce = t.order_nonce AND ( @@ -49,7 +49,7 @@ take_trades AS ( SELECT 1 FROM order_add_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_owner = oe.order_owner AND newer.order_nonce = oe.order_nonce AND ( @@ -63,14 +63,14 @@ take_trades AS ( ) JOIN order_ios io_in ON io_in.chain_id = oe.chain_id - AND io_in.orderbook_address = oe.orderbook_address + AND io_in.raindex_address = oe.raindex_address AND io_in.transaction_hash = oe.transaction_hash AND io_in.log_index = oe.log_index AND io_in.io_index = t.input_io_index AND io_in.io_type = 'input' JOIN order_ios io_out ON io_out.chain_id = oe.chain_id - AND io_out.orderbook_address = oe.orderbook_address + AND io_out.raindex_address = oe.raindex_address AND io_out.transaction_hash = oe.transaction_hash AND io_out.log_index = oe.log_index AND io_out.io_index = t.output_io_index @@ -88,10 +88,10 @@ clear_alice AS ( FROM clear_v3_events c JOIN params p ON c.chain_id = p.chain_id - AND c.orderbook_address = p.orderbook_address + AND c.raindex_address = p.raindex_address JOIN order_add_events oe ON oe.chain_id = c.chain_id - AND oe.orderbook_address = c.orderbook_address + AND oe.raindex_address = c.raindex_address AND oe.order_hash = c.alice_order_hash AND ( oe.block_number < c.block_number @@ -101,7 +101,7 @@ clear_alice AS ( SELECT 1 FROM order_add_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_hash = oe.order_hash AND ( newer.block_number < c.block_number @@ -114,26 +114,26 @@ clear_alice AS ( ) JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN order_ios io_in ON io_in.chain_id = oe.chain_id - AND io_in.orderbook_address = oe.orderbook_address + AND io_in.raindex_address = oe.raindex_address AND io_in.transaction_hash = oe.transaction_hash AND io_in.log_index = oe.log_index AND io_in.io_index = c.alice_input_io_index AND io_in.io_type = 'input' JOIN order_ios io_out ON io_out.chain_id = oe.chain_id - AND io_out.orderbook_address = oe.orderbook_address + AND io_out.raindex_address = oe.raindex_address AND io_out.transaction_hash = oe.transaction_hash AND io_out.log_index = oe.log_index AND io_out.io_index = c.alice_output_io_index @@ -152,10 +152,10 @@ clear_bob AS ( FROM clear_v3_events c JOIN params p ON c.chain_id = p.chain_id - AND c.orderbook_address = p.orderbook_address + AND c.raindex_address = p.raindex_address JOIN order_add_events oe ON oe.chain_id = c.chain_id - AND oe.orderbook_address = c.orderbook_address + AND oe.raindex_address = c.raindex_address AND oe.order_hash = c.bob_order_hash AND ( oe.block_number < c.block_number @@ -165,7 +165,7 @@ clear_bob AS ( SELECT 1 FROM order_add_events newer WHERE newer.chain_id = oe.chain_id - AND newer.orderbook_address = oe.orderbook_address + AND newer.raindex_address = oe.raindex_address AND newer.order_hash = oe.order_hash AND ( newer.block_number < c.block_number @@ -178,26 +178,26 @@ clear_bob AS ( ) JOIN after_clear_v2_events a ON a.chain_id = c.chain_id - AND a.orderbook_address = c.orderbook_address + AND a.raindex_address = c.raindex_address AND a.transaction_hash = c.transaction_hash AND a.log_index = ( SELECT MIN(ac.log_index) FROM after_clear_v2_events ac WHERE ac.chain_id = c.chain_id - AND ac.orderbook_address = c.orderbook_address + AND ac.raindex_address = c.raindex_address AND ac.transaction_hash = c.transaction_hash AND ac.log_index > c.log_index ) JOIN order_ios io_in ON io_in.chain_id = oe.chain_id - AND io_in.orderbook_address = oe.orderbook_address + AND io_in.raindex_address = oe.raindex_address AND io_in.transaction_hash = oe.transaction_hash AND io_in.log_index = oe.log_index AND io_in.io_index = c.bob_input_io_index AND io_in.io_type = 'input' JOIN order_ios io_out ON io_out.chain_id = oe.chain_id - AND io_out.orderbook_address = oe.orderbook_address + AND io_out.raindex_address = oe.raindex_address AND io_out.transaction_hash = oe.transaction_hash AND io_out.log_index = oe.log_index AND io_out.io_index = c.bob_output_io_index @@ -255,5 +255,5 @@ LEFT JOIN input_volumes iv ON av.vault_id = iv.vault_id AND av.token = iv.token LEFT JOIN output_volumes ov ON av.vault_id = ov.vault_id AND av.token = ov.token LEFT JOIN erc20_tokens tok ON tok.chain_id = p.chain_id - AND tok.orderbook_address = p.orderbook_address + AND tok.raindex_address = p.raindex_address AND tok.token_address = av.token; diff --git a/crates/common/src/local_db/query/fetch_orders/mod.rs b/crates/common/src/local_db/query/fetch_orders/mod.rs index 44c9b5275a..cdc779529c 100644 --- a/crates/common/src/local_db/query/fetch_orders/mod.rs +++ b/crates/common/src/local_db/query/fetch_orders/mod.rs @@ -25,7 +25,7 @@ pub struct FetchOrdersTokensFilter { #[derive(Debug, Clone, Default)] pub struct FetchOrdersArgs { pub chain_ids: Vec, - pub orderbook_addresses: Vec
, + pub raindex_addresses: Vec
, pub filter: FetchOrdersActiveFilter, pub owners: Vec
, pub order_hash: Option, @@ -43,7 +43,7 @@ pub struct LocalDbOrder { pub owner: Address, pub block_timestamp: u64, pub block_number: u64, - pub orderbook_address: Address, + pub raindex_address: Address, pub order_bytes: Bytes, pub transaction_hash: B256, pub inputs: Option, @@ -56,18 +56,18 @@ pub struct LocalDbOrder { const FIRST_ADD_CHAIN_IDS_CLAUSE: &str = "/*FIRST_ADD_CHAIN_IDS_CLAUSE*/"; const FIRST_ADD_CHAIN_IDS_CLAUSE_BODY: &str = "AND oe.chain_id IN ({list})"; -const FIRST_ADD_ORDERBOOKS_CLAUSE: &str = "/*FIRST_ADD_ORDERBOOKS_CLAUSE*/"; -const FIRST_ADD_ORDERBOOKS_CLAUSE_BODY: &str = "AND oe.orderbook_address IN ({list})"; +const FIRST_ADD_RAINDEXES_CLAUSE: &str = "/*FIRST_ADD_RAINDEXES_CLAUSE*/"; +const FIRST_ADD_RAINDEXES_CLAUSE_BODY: &str = "AND oe.raindex_address IN ({list})"; const TAKE_ORDERS_CHAIN_IDS_CLAUSE: &str = "/*TAKE_ORDERS_CHAIN_IDS_CLAUSE*/"; const TAKE_ORDERS_CHAIN_IDS_CLAUSE_BODY: &str = "AND t.chain_id IN ({list})"; -const TAKE_ORDERS_ORDERBOOKS_CLAUSE: &str = "/*TAKE_ORDERS_ORDERBOOKS_CLAUSE*/"; -const TAKE_ORDERS_ORDERBOOKS_CLAUSE_BODY: &str = "AND t.orderbook_address IN ({list})"; +const TAKE_ORDERS_RAINDEXES_CLAUSE: &str = "/*TAKE_ORDERS_RAINDEXES_CLAUSE*/"; +const TAKE_ORDERS_RAINDEXES_CLAUSE_BODY: &str = "AND t.raindex_address IN ({list})"; const CLEAR_EVENTS_CHAIN_IDS_CLAUSE: &str = "/*CLEAR_EVENTS_CHAIN_IDS_CLAUSE*/"; const CLEAR_EVENTS_CHAIN_IDS_CLAUSE_BODY: &str = "AND entries.chain_id IN ({list})"; -const CLEAR_EVENTS_ORDERBOOKS_CLAUSE: &str = "/*CLEAR_EVENTS_ORDERBOOKS_CLAUSE*/"; -const CLEAR_EVENTS_ORDERBOOKS_CLAUSE_BODY: &str = "AND entries.orderbook_address IN ({list})"; +const CLEAR_EVENTS_RAINDEXES_CLAUSE: &str = "/*CLEAR_EVENTS_RAINDEXES_CLAUSE*/"; +const CLEAR_EVENTS_RAINDEXES_CLAUSE_BODY: &str = "AND entries.raindex_address IN ({list})"; const TX_HASH_CLAUSE: &str = "/*TX_HASH_CLAUSE*/"; const TX_HASH_CLAUSE_BODY: &str = "AND oe.transaction_hash = {param}"; const PAGINATION_CLAUSE: &str = "/*PAGINATION_CLAUSE*/"; @@ -78,7 +78,7 @@ pub fn build_fetch_orders_stmt(args: &FetchOrdersArgs) -> Result Result Result= 3); assert_eq!(stmt.params[0], SqlValue::Text("active".to_string())); } @@ -354,10 +354,10 @@ mod tests { } #[test] - fn orderbook_filters_lowercase_and_optional() { + fn raindex_filters_lowercase_and_optional() { let args = FetchOrdersArgs { chain_ids: vec![1], - orderbook_addresses: vec![ + raindex_addresses: vec![ Address::from_str("0xAbCDeF0000000000000000000000000000000000").unwrap(), Address::from_str("0xabcdef0000000000000000000000000000000000").unwrap(), Address::from_str("0x0000000000000000000000000000000000000000").unwrap(), @@ -368,11 +368,11 @@ mod tests { let stmt = build_fetch_orders_stmt(&args).unwrap(); for marker in [ - MAIN_ORDERBOOKS_CLAUSE, - LATEST_ADD_ORDERBOOKS_CLAUSE, - FIRST_ADD_ORDERBOOKS_CLAUSE, - TAKE_ORDERS_ORDERBOOKS_CLAUSE, - CLEAR_EVENTS_ORDERBOOKS_CLAUSE, + MAIN_RAINDEXES_CLAUSE, + LATEST_ADD_RAINDEXES_CLAUSE, + FIRST_ADD_RAINDEXES_CLAUSE, + TAKE_ORDERS_RAINDEXES_CLAUSE, + CLEAR_EVENTS_RAINDEXES_CLAUSE, ] { assert!( !stmt.sql.contains(marker), @@ -381,12 +381,12 @@ mod tests { } assert!( - stmt.sql.contains("AND oe.orderbook_address IN (?"), - "main orderbook filter missing" + stmt.sql.contains("AND oe.raindex_address IN (?"), + "main raindex filter missing" ); assert!( - stmt.sql.contains("AND t.orderbook_address IN (?"), - "take_orders orderbook filter missing" + stmt.sql.contains("AND t.raindex_address IN (?"), + "take_orders raindex filter missing" ); // Only the trimmed, lowercased address should appear in bound params. @@ -401,26 +401,26 @@ mod tests { .collect(); assert!( text_params.iter().any(|text| text.as_str() == lower_addr), - "expected lowercase orderbook address in params" + "expected lowercase raindex address in params" ); for text in text_params { let lowered = text.to_ascii_lowercase(); assert_eq!( text.as_str(), lowered.as_str(), - "orderbook param should be lowercase" + "raindex param should be lowercase" ); } - // When orderbooks are omitted entirely, no orderbook clause should remain. - let args_no_orderbooks = FetchOrdersArgs { + // When raindexes are omitted entirely, no raindex clause should remain. + let args_no_raindexes = FetchOrdersArgs { chain_ids: vec![1], ..FetchOrdersArgs::default() }; - let stmt_no_orderbooks = build_fetch_orders_stmt(&args_no_orderbooks).unwrap(); + let stmt_no_raindexes = build_fetch_orders_stmt(&args_no_raindexes).unwrap(); assert!( - !stmt_no_orderbooks.sql.contains("oe.orderbook_address IN ("), - "orderbook clause should not appear when list is empty" + !stmt_no_raindexes.sql.contains("oe.raindex_address IN ("), + "raindex clause should not appear when list is empty" ); } diff --git a/crates/common/src/local_db/query/fetch_orders/query.sql b/crates/common/src/local_db/query/fetch_orders/query.sql index fbf8ff3f72..b1ec0c864d 100644 --- a/crates/common/src/local_db/query/fetch_orders/query.sql +++ b/crates/common/src/local_db/query/fetch_orders/query.sql @@ -4,7 +4,7 @@ SELECT l.order_owner AS owner, fa.block_timestamp AS blockTimestamp, fa.block_number AS blockNumber, - l.orderbook_address AS orderbookAddress, + l.raindex_address AS raindexAddress, la.order_bytes AS orderBytes, json_group_array( CASE @@ -16,7 +16,7 @@ SELECT 'vaultId', ios.vault_id, 'token', ios.token, 'owner', l.order_owner, - 'orderbookAddress', l.orderbook_address, + 'raindexAddress', l.raindex_address, 'tokenName', COALESCE(tok.name, ''), 'tokenSymbol', COALESCE(tok.symbol, ''), 'tokenDecimals', COALESCE(tok.decimals, 0), @@ -37,7 +37,7 @@ SELECT 'vaultId', ios.vault_id, 'token', ios.token, 'owner', l.order_owner, - 'orderbookAddress', l.orderbook_address, + 'raindexAddress', l.raindex_address, 'tokenName', COALESCE(tok.name, ''), 'tokenSymbol', COALESCE(tok.symbol, ''), 'tokenDecimals', COALESCE(tok.decimals, 0), @@ -55,7 +55,7 @@ SELECT SELECT m.meta FROM meta_events m WHERE m.chain_id = l.chain_id - AND m.orderbook_address = l.orderbook_address + AND m.raindex_address = l.raindex_address AND m.subject = COALESCE(la.order_hash, l.order_hash) ORDER BY m.block_number DESC, m.log_index DESC LIMIT 1 @@ -63,7 +63,7 @@ SELECT FROM ( SELECT latest.chain_id, - latest.orderbook_address, + latest.raindex_address, latest.order_owner, latest.order_nonce, latest.order_hash, @@ -75,7 +75,7 @@ FROM ( FROM ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce, oe.order_hash, @@ -87,7 +87,7 @@ FROM ( ROW_NUMBER() OVER ( PARTITION BY oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce ORDER BY oe.block_number DESC, oe.log_index DESC @@ -95,7 +95,7 @@ FROM ( FROM order_events oe WHERE 1 = 1 /*MAIN_CHAIN_IDS_CLAUSE*/ - /*MAIN_ORDERBOOKS_CLAUSE*/ + /*MAIN_RAINDEXES_CLAUSE*/ /*TX_HASH_CLAUSE*/ ) latest WHERE latest.row_rank_latest = 1 @@ -103,7 +103,7 @@ FROM ( LEFT JOIN ( SELECT ranked.chain_id, - ranked.orderbook_address, + ranked.raindex_address, ranked.order_owner, ranked.order_nonce, ranked.transaction_hash, @@ -113,7 +113,7 @@ LEFT JOIN ( FROM ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce, oe.transaction_hash, @@ -123,7 +123,7 @@ LEFT JOIN ( ROW_NUMBER() OVER ( PARTITION BY oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce ORDER BY oe.block_number DESC, oe.log_index DESC @@ -131,27 +131,27 @@ LEFT JOIN ( FROM order_events oe WHERE oe.event_type = 'AddOrderV3' /*LATEST_ADD_CHAIN_IDS_CLAUSE*/ - /*LATEST_ADD_ORDERBOOKS_CLAUSE*/ + /*LATEST_ADD_RAINDEXES_CLAUSE*/ ) ranked WHERE ranked.row_rank_add = 1 ) la ON la.chain_id = l.chain_id - AND la.orderbook_address = l.orderbook_address + AND la.raindex_address = l.raindex_address AND la.order_owner = l.order_owner AND la.order_nonce = l.order_nonce LEFT JOIN order_ios ios ON ios.chain_id = l.chain_id - AND ios.orderbook_address = l.orderbook_address + AND ios.raindex_address = l.raindex_address AND ios.transaction_hash = la.transaction_hash AND ios.log_index = la.log_index LEFT JOIN erc20_tokens tok ON tok.chain_id = ios.chain_id - AND tok.orderbook_address = ios.orderbook_address + AND tok.raindex_address = ios.raindex_address AND tok.token_address = ios.token LEFT JOIN ( SELECT rvb.chain_id, - rvb.orderbook_address, + rvb.raindex_address, rvb.owner, rvb.token, rvb.vault_id, @@ -159,60 +159,60 @@ LEFT JOIN ( FROM running_vault_balances rvb ) vb ON vb.chain_id = ios.chain_id - AND vb.orderbook_address = ios.orderbook_address + AND vb.raindex_address = ios.raindex_address AND vb.token = ios.token AND vb.vault_id = ios.vault_id AND vb.owner = l.order_owner LEFT JOIN ( SELECT t.chain_id, - t.orderbook_address, + t.raindex_address, t.order_owner, t.order_nonce, COUNT(*) AS trade_count FROM take_orders t WHERE 1 = 1 /*TAKE_ORDERS_CHAIN_IDS_CLAUSE*/ - /*TAKE_ORDERS_ORDERBOOKS_CLAUSE*/ - GROUP BY t.chain_id, t.orderbook_address, t.order_owner, t.order_nonce + /*TAKE_ORDERS_RAINDEXES_CLAUSE*/ + GROUP BY t.chain_id, t.raindex_address, t.order_owner, t.order_nonce ) tc ON tc.chain_id = l.chain_id - AND tc.orderbook_address = l.orderbook_address + AND tc.raindex_address = l.raindex_address AND tc.order_owner = l.order_owner AND tc.order_nonce = l.order_nonce LEFT JOIN ( SELECT entries.chain_id, - entries.orderbook_address, + entries.raindex_address, entries.order_hash, COUNT(*) AS trade_count FROM ( SELECT c.chain_id, - c.orderbook_address, + c.raindex_address, c.alice_order_hash AS order_hash FROM clear_v3_events c WHERE c.alice_order_hash IS NOT NULL UNION ALL SELECT c.chain_id, - c.orderbook_address, + c.raindex_address, c.bob_order_hash AS order_hash FROM clear_v3_events c WHERE c.bob_order_hash IS NOT NULL ) entries WHERE entries.order_hash IS NOT NULL /*CLEAR_EVENTS_CHAIN_IDS_CLAUSE*/ - /*CLEAR_EVENTS_ORDERBOOKS_CLAUSE*/ - GROUP BY entries.chain_id, entries.orderbook_address, entries.order_hash + /*CLEAR_EVENTS_RAINDEXES_CLAUSE*/ + GROUP BY entries.chain_id, entries.raindex_address, entries.order_hash ) cc ON cc.chain_id = l.chain_id - AND cc.orderbook_address = l.orderbook_address + AND cc.raindex_address = l.raindex_address AND cc.order_hash = COALESCE(la.order_hash, l.order_hash) LEFT JOIN ( SELECT ranked.chain_id, - ranked.orderbook_address, + ranked.raindex_address, ranked.order_owner, ranked.order_nonce, ranked.block_timestamp, @@ -220,7 +220,7 @@ LEFT JOIN ( FROM ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce, oe.block_timestamp, @@ -228,7 +228,7 @@ LEFT JOIN ( ROW_NUMBER() OVER ( PARTITION BY oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce ORDER BY oe.block_number ASC, oe.log_index ASC @@ -236,12 +236,12 @@ LEFT JOIN ( FROM order_events oe WHERE oe.event_type = 'AddOrderV3' /*FIRST_ADD_CHAIN_IDS_CLAUSE*/ - /*FIRST_ADD_ORDERBOOKS_CLAUSE*/ + /*FIRST_ADD_RAINDEXES_CLAUSE*/ ) ranked WHERE ranked.row_rank_first_add = 1 ) fa ON fa.chain_id = l.chain_id - AND fa.orderbook_address = l.orderbook_address + AND fa.raindex_address = l.raindex_address AND fa.order_owner = l.order_owner AND fa.order_nonce = l.order_nonce WHERE @@ -260,7 +260,7 @@ GROUP BY l.order_owner, fa.block_timestamp, fa.block_number, - l.orderbook_address, + l.raindex_address, l.order_nonce, l.event_type, la.transaction_hash diff --git a/crates/common/src/local_db/query/fetch_orders_common.rs b/crates/common/src/local_db/query/fetch_orders_common.rs index e5bda799f8..209fc99e70 100644 --- a/crates/common/src/local_db/query/fetch_orders_common.rs +++ b/crates/common/src/local_db/query/fetch_orders_common.rs @@ -15,7 +15,7 @@ pub(crate) const INPUT_TOKENS_CLAUSE: &str = "/*INPUT_TOKENS_CLAUSE*/"; pub(crate) const INPUT_TOKENS_CLAUSE_BODY: &str = "AND EXISTS ( SELECT 1 FROM order_ios io2 WHERE io2.chain_id = l.chain_id - AND io2.orderbook_address = l.orderbook_address + AND io2.raindex_address = l.raindex_address AND io2.transaction_hash = la.transaction_hash AND io2.log_index = la.log_index AND lower(io2.io_type) = 'input' @@ -26,7 +26,7 @@ pub(crate) const OUTPUT_TOKENS_CLAUSE: &str = "/*OUTPUT_TOKENS_CLAUSE*/"; pub(crate) const OUTPUT_TOKENS_CLAUSE_BODY: &str = "AND EXISTS ( SELECT 1 FROM order_ios io2 WHERE io2.chain_id = l.chain_id - AND io2.orderbook_address = l.orderbook_address + AND io2.raindex_address = l.raindex_address AND io2.transaction_hash = la.transaction_hash AND io2.log_index = la.log_index AND lower(io2.io_type) = 'output' @@ -36,7 +36,7 @@ pub(crate) const OUTPUT_TOKENS_CLAUSE_BODY: &str = "AND EXISTS ( pub(crate) const COMBINED_TOKENS_CLAUSE_BODY: &str = "AND EXISTS ( SELECT 1 FROM order_ios io2 WHERE io2.chain_id = l.chain_id - AND io2.orderbook_address = l.orderbook_address + AND io2.raindex_address = l.raindex_address AND io2.transaction_hash = la.transaction_hash AND io2.log_index = la.log_index AND ( @@ -48,17 +48,17 @@ pub(crate) const COMBINED_TOKENS_CLAUSE_BODY: &str = "AND EXISTS ( pub(crate) const MAIN_CHAIN_IDS_CLAUSE: &str = "/*MAIN_CHAIN_IDS_CLAUSE*/"; pub(crate) const MAIN_CHAIN_IDS_CLAUSE_BODY: &str = "AND oe.chain_id IN ({list})"; -pub(crate) const MAIN_ORDERBOOKS_CLAUSE: &str = "/*MAIN_ORDERBOOKS_CLAUSE*/"; -pub(crate) const MAIN_ORDERBOOKS_CLAUSE_BODY: &str = "AND oe.orderbook_address IN ({list})"; +pub(crate) const MAIN_RAINDEXES_CLAUSE: &str = "/*MAIN_RAINDEXES_CLAUSE*/"; +pub(crate) const MAIN_RAINDEXES_CLAUSE_BODY: &str = "AND oe.raindex_address IN ({list})"; pub(crate) const LATEST_ADD_CHAIN_IDS_CLAUSE: &str = "/*LATEST_ADD_CHAIN_IDS_CLAUSE*/"; pub(crate) const LATEST_ADD_CHAIN_IDS_CLAUSE_BODY: &str = "AND oe.chain_id IN ({list})"; -pub(crate) const LATEST_ADD_ORDERBOOKS_CLAUSE: &str = "/*LATEST_ADD_ORDERBOOKS_CLAUSE*/"; -pub(crate) const LATEST_ADD_ORDERBOOKS_CLAUSE_BODY: &str = "AND oe.orderbook_address IN ({list})"; +pub(crate) const LATEST_ADD_RAINDEXES_CLAUSE: &str = "/*LATEST_ADD_RAINDEXES_CLAUSE*/"; +pub(crate) const LATEST_ADD_RAINDEXES_CLAUSE_BODY: &str = "AND oe.raindex_address IN ({list})"; pub(crate) struct PreparedFilters { pub chain_ids: Vec, - pub orderbooks: Vec
, + pub raindexes: Vec
, } pub(crate) fn bind_common_order_filters( @@ -76,12 +76,12 @@ pub(crate) fn bind_common_order_filters( chain_ids.sort_unstable(); chain_ids.dedup(); - let mut orderbooks = args.orderbook_addresses.clone(); - orderbooks.sort(); - orderbooks.dedup(); + let mut raindexes = args.raindex_addresses.clone(); + raindexes.sort(); + raindexes.dedup(); let chain_ids_iter = || chain_ids.iter().cloned().map(SqlValue::from); - let orderbooks_iter = || orderbooks.iter().cloned().map(SqlValue::from); + let raindexes_iter = || raindexes.iter().cloned().map(SqlValue::from); stmt.bind_list_clause( MAIN_CHAIN_IDS_CLAUSE, @@ -95,14 +95,14 @@ pub(crate) fn bind_common_order_filters( )?; stmt.bind_list_clause( - MAIN_ORDERBOOKS_CLAUSE, - MAIN_ORDERBOOKS_CLAUSE_BODY, - orderbooks_iter(), + MAIN_RAINDEXES_CLAUSE, + MAIN_RAINDEXES_CLAUSE_BODY, + raindexes_iter(), )?; stmt.bind_list_clause( - LATEST_ADD_ORDERBOOKS_CLAUSE, - LATEST_ADD_ORDERBOOKS_CLAUSE_BODY, - orderbooks_iter(), + LATEST_ADD_RAINDEXES_CLAUSE, + LATEST_ADD_RAINDEXES_CLAUSE_BODY, + raindexes_iter(), )?; let mut owners = args.owners.clone(); @@ -172,6 +172,6 @@ pub(crate) fn bind_common_order_filters( Ok(PreparedFilters { chain_ids, - orderbooks, + raindexes, }) } diff --git a/crates/common/src/local_db/query/fetch_orders_count/mod.rs b/crates/common/src/local_db/query/fetch_orders_count/mod.rs index f06198db3a..67adddb9a5 100644 --- a/crates/common/src/local_db/query/fetch_orders_count/mod.rs +++ b/crates/common/src/local_db/query/fetch_orders_count/mod.rs @@ -91,14 +91,14 @@ mod tests { } #[test] - fn builds_count_with_orderbooks() { + fn builds_count_with_raindexes() { let args = FetchOrdersArgs { chain_ids: vec![1], - orderbook_addresses: vec![Address::ZERO], + raindex_addresses: vec![Address::ZERO], ..FetchOrdersArgs::default() }; let stmt = build_fetch_orders_count_stmt(&args).unwrap(); - assert!(stmt.sql.contains("AND oe.orderbook_address IN (?")); + assert!(stmt.sql.contains("AND oe.raindex_address IN (?")); } #[test] diff --git a/crates/common/src/local_db/query/fetch_orders_count/query.sql b/crates/common/src/local_db/query/fetch_orders_count/query.sql index ae0b948ec8..b0bbcd8867 100644 --- a/crates/common/src/local_db/query/fetch_orders_count/query.sql +++ b/crates/common/src/local_db/query/fetch_orders_count/query.sql @@ -4,7 +4,7 @@ SELECT COUNT(*) AS orders_count FROM ( FROM ( SELECT latest.chain_id, - latest.orderbook_address, + latest.raindex_address, latest.order_owner, latest.order_nonce, latest.order_hash, @@ -12,7 +12,7 @@ SELECT COUNT(*) AS orders_count FROM ( FROM ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce, oe.order_hash, @@ -20,7 +20,7 @@ SELECT COUNT(*) AS orders_count FROM ( ROW_NUMBER() OVER ( PARTITION BY oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce ORDER BY oe.block_number DESC, oe.log_index DESC @@ -28,14 +28,14 @@ SELECT COUNT(*) AS orders_count FROM ( FROM order_events oe WHERE 1 = 1 /*MAIN_CHAIN_IDS_CLAUSE*/ - /*MAIN_ORDERBOOKS_CLAUSE*/ + /*MAIN_RAINDEXES_CLAUSE*/ ) latest WHERE latest.row_rank_latest = 1 ) l LEFT JOIN ( SELECT ranked.chain_id, - ranked.orderbook_address, + ranked.raindex_address, ranked.order_owner, ranked.order_nonce, ranked.order_hash, @@ -44,7 +44,7 @@ SELECT COUNT(*) AS orders_count FROM ( FROM ( SELECT oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce, oe.order_hash, @@ -53,7 +53,7 @@ SELECT COUNT(*) AS orders_count FROM ( ROW_NUMBER() OVER ( PARTITION BY oe.chain_id, - oe.orderbook_address, + oe.raindex_address, oe.order_owner, oe.order_nonce ORDER BY oe.block_number DESC, oe.log_index DESC @@ -61,12 +61,12 @@ SELECT COUNT(*) AS orders_count FROM ( FROM order_events oe WHERE oe.event_type = 'AddOrderV3' /*LATEST_ADD_CHAIN_IDS_CLAUSE*/ - /*LATEST_ADD_ORDERBOOKS_CLAUSE*/ + /*LATEST_ADD_RAINDEXES_CLAUSE*/ ) ranked WHERE ranked.row_rank_add = 1 ) la ON la.chain_id = l.chain_id - AND la.orderbook_address = l.orderbook_address + AND la.raindex_address = l.raindex_address AND la.order_owner = l.order_owner AND la.order_nonce = l.order_nonce WHERE diff --git a/crates/common/src/local_db/query/fetch_store_addresses/mod.rs b/crates/common/src/local_db/query/fetch_store_addresses/mod.rs index 3cb5a5a950..c046464d09 100644 --- a/crates/common/src/local_db/query/fetch_store_addresses/mod.rs +++ b/crates/common/src/local_db/query/fetch_store_addresses/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::Address; use serde::{Deserialize, Serialize}; @@ -12,12 +12,12 @@ pub struct StoreAddressRow { pub store_address: Address, } -pub fn fetch_store_addresses_stmt(ob_id: &OrderbookIdentifier) -> SqlStatement { +pub fn fetch_store_addresses_stmt(raindex_id: &RaindexIdentifier) -> SqlStatement { SqlStatement::new_with_params( FETCH_STORE_ADDRESSES_SQL, [ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), ], ) } @@ -27,8 +27,8 @@ mod tests { use super::*; #[test] - fn stmt_binds_chain_and_orderbook() { - let stmt = fetch_store_addresses_stmt(&OrderbookIdentifier::new(1, Address::ZERO)); + fn stmt_binds_chain_and_raindex() { + let stmt = fetch_store_addresses_stmt(&RaindexIdentifier::new(1, Address::ZERO)); assert_eq!(stmt.sql, FETCH_STORE_ADDRESSES_SQL); assert_eq!(stmt.params.len(), 2); assert!(stmt diff --git a/crates/common/src/local_db/query/fetch_store_addresses/query.sql b/crates/common/src/local_db/query/fetch_store_addresses/query.sql index 786bc183e9..b3d8a5f389 100644 --- a/crates/common/src/local_db/query/fetch_store_addresses/query.sql +++ b/crates/common/src/local_db/query/fetch_store_addresses/query.sql @@ -1,13 +1,13 @@ SELECT DISTINCT store_address AS store_address FROM order_events WHERE chain_id = ?1 - AND orderbook_address = ?2 + AND raindex_address = ?2 AND store_address IS NOT NULL AND store_address != '' UNION SELECT DISTINCT store_address AS store_address FROM interpreter_store_sets WHERE chain_id = ?1 - AND orderbook_address = ?2 + AND raindex_address = ?2 AND store_address IS NOT NULL AND store_address != ''; diff --git a/crates/common/src/local_db/query/fetch_target_watermark/mod.rs b/crates/common/src/local_db/query/fetch_target_watermark/mod.rs index 5602152ae9..2ed1c3dff5 100644 --- a/crates/common/src/local_db/query/fetch_target_watermark/mod.rs +++ b/crates/common/src/local_db/query/fetch_target_watermark/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::{Address, Bytes}; use serde::{Deserialize, Serialize}; @@ -10,18 +10,18 @@ pub const FETCH_TARGET_WATERMARK_SQL: &str = include_str!("query.sql"); #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct TargetWatermarkRow { pub chain_id: u32, - pub orderbook_address: Address, + pub raindex_address: Address, pub last_block: u64, pub last_hash: Bytes, pub updated_at: u64, } -pub fn fetch_target_watermark_stmt(ob_id: &OrderbookIdentifier) -> SqlStatement { +pub fn fetch_target_watermark_stmt(raindex_id: &RaindexIdentifier) -> SqlStatement { SqlStatement::new_with_params( FETCH_TARGET_WATERMARK_SQL, [ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), ], ) } @@ -32,26 +32,26 @@ mod tests { #[test] fn fetch_stmt_binds_params() { - let stmt = fetch_target_watermark_stmt(&OrderbookIdentifier::new(10, Address::ZERO)); + let stmt = fetch_target_watermark_stmt(&RaindexIdentifier::new(10, Address::ZERO)); assert!(stmt.sql().to_lowercase().contains("from target_watermarks")); assert_eq!(stmt.params().len(), 2); } #[test] fn fetch_stmt_sql_matches_template_and_where_clause() { - let stmt = fetch_target_watermark_stmt(&OrderbookIdentifier::new(1, Address::ZERO)); + let stmt = fetch_target_watermark_stmt(&RaindexIdentifier::new(1, Address::ZERO)); // Exact template equality (comes from include_str!) assert_eq!(stmt.sql(), FETCH_TARGET_WATERMARK_SQL); // Defensive: check placeholders and where clause shape let lower = stmt.sql().to_lowercase(); - assert!(lower.contains("where chain_id = ?1 and orderbook_address = ?2")); + assert!(lower.contains("where chain_id = ?1 and raindex_address = ?2")); } #[test] fn fetch_stmt_param_order_and_values() { let chain_id = 111u32; let addr = Address::repeat_byte(0xab); - let stmt = fetch_target_watermark_stmt(&OrderbookIdentifier::new(chain_id, addr)); + let stmt = fetch_target_watermark_stmt(&RaindexIdentifier::new(chain_id, addr)); let params = stmt.params(); assert_eq!(params.len(), 2); @@ -63,7 +63,7 @@ mod tests { assert_eq!( params[1], SqlValue::Text("0xabababababababababababababababababababab".to_string()), - "second param must be orderbook_address as hex string" + "second param must be raindex_address as hex string" ); // Ensure address string formatting is 0x-prefixed lowercase hex let SqlValue::Text(s) = ¶ms[1] else { diff --git a/crates/common/src/local_db/query/fetch_target_watermark/query.sql b/crates/common/src/local_db/query/fetch_target_watermark/query.sql index 27d588548e..76c4e1a364 100644 --- a/crates/common/src/local_db/query/fetch_target_watermark/query.sql +++ b/crates/common/src/local_db/query/fetch_target_watermark/query.sql @@ -1,3 +1,3 @@ -SELECT chain_id, orderbook_address, last_block, last_hash, updated_at +SELECT chain_id, raindex_address, last_block, last_hash, updated_at FROM target_watermarks -WHERE chain_id = ?1 AND orderbook_address = ?2; +WHERE chain_id = ?1 AND raindex_address = ?2; diff --git a/crates/common/src/local_db/query/fetch_transaction_by_hash/mod.rs b/crates/common/src/local_db/query/fetch_transaction_by_hash/mod.rs index f163cf6f9b..2ea26ea8b0 100644 --- a/crates/common/src/local_db/query/fetch_transaction_by_hash/mod.rs +++ b/crates/common/src/local_db/query/fetch_transaction_by_hash/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::{Address, B256}; use serde::{Deserialize, Serialize}; @@ -20,14 +20,14 @@ pub struct LocalDbTransaction { /// Builds a SQL statement to fetch transaction info by transaction hash /// from the deposits and withdrawals tables. pub fn build_fetch_transaction_by_hash_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, tx_hash: B256, ) -> SqlStatement { SqlStatement::new_with_params( QUERY_TEMPLATE, vec![ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), SqlValue::from(tx_hash), ], ) @@ -40,11 +40,11 @@ mod tests { #[test] fn builds_correct_sql_with_params() { - let orderbook = address!("0x1234567890123456789012345678901234567890"); + let raindex = address!("0x1234567890123456789012345678901234567890"); let tx_hash = b256!("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"); - let ob_id = OrderbookIdentifier::new(1, orderbook); + let raindex_id = RaindexIdentifier::new(1, raindex); - let stmt = build_fetch_transaction_by_hash_stmt(&ob_id, tx_hash); + let stmt = build_fetch_transaction_by_hash_stmt(&raindex_id, tx_hash); assert!(stmt.sql.contains("SELECT")); assert!(stmt.sql.contains("FROM deposits")); diff --git a/crates/common/src/local_db/query/fetch_transaction_by_hash/query.sql b/crates/common/src/local_db/query/fetch_transaction_by_hash/query.sql index e50635ae74..33b5328195 100644 --- a/crates/common/src/local_db/query/fetch_transaction_by_hash/query.sql +++ b/crates/common/src/local_db/query/fetch_transaction_by_hash/query.sql @@ -1,7 +1,7 @@ WITH params AS ( SELECT ?1 AS chain_id, - ?2 AS orderbook_address, + ?2 AS raindex_address, ?3 AS transaction_hash ), combined AS ( @@ -14,7 +14,7 @@ combined AS ( FROM deposits d JOIN params p ON p.chain_id = d.chain_id - AND p.orderbook_address = d.orderbook_address + AND p.raindex_address = d.raindex_address AND p.transaction_hash = d.transaction_hash UNION ALL SELECT @@ -26,7 +26,7 @@ combined AS ( FROM withdrawals w JOIN params p ON p.chain_id = w.chain_id - AND p.orderbook_address = w.orderbook_address + AND p.raindex_address = w.raindex_address AND p.transaction_hash = w.transaction_hash ) SELECT diff --git a/crates/common/src/local_db/query/fetch_vault_balance_changes/mod.rs b/crates/common/src/local_db/query/fetch_vault_balance_changes/mod.rs index 3af0f919c4..5b2d44e412 100644 --- a/crates/common/src/local_db/query/fetch_vault_balance_changes/mod.rs +++ b/crates/common/src/local_db/query/fetch_vault_balance_changes/mod.rs @@ -1,6 +1,6 @@ use crate::local_db::{ query::{SqlBuildError, SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use crate::types::VaultBalanceChangeKind; use alloy::primitives::{Address, B256, U256}; @@ -26,7 +26,7 @@ pub struct LocalDbVaultBalanceChange { } pub fn build_fetch_balance_changes_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, vault_id: U256, token: Address, owner: Address, @@ -34,8 +34,8 @@ pub fn build_fetch_balance_changes_stmt( ) -> Result { let mut stmt = SqlStatement::new(QUERY_TEMPLATE); - stmt.push(SqlValue::from(ob_id.chain_id)); - stmt.push(SqlValue::from(ob_id.orderbook_address)); + stmt.push(SqlValue::from(raindex_id.chain_id)); + stmt.push(SqlValue::from(raindex_id.raindex_address)); stmt.push(SqlValue::from(vault_id)); stmt.push(SqlValue::from(token)); stmt.push(SqlValue::from(owner)); @@ -67,7 +67,7 @@ mod tests { #[test] fn builds_with_params_no_filter() { let stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), U256::from(1), Address::ZERO, Address::ZERO, @@ -83,7 +83,7 @@ mod tests { #[test] fn builds_with_single_filter_type() { let stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), U256::from(1), Address::ZERO, Address::ZERO, @@ -99,7 +99,7 @@ mod tests { #[test] fn builds_with_take_order_filter_expands_to_two_types() { let stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), U256::from(1), Address::ZERO, Address::ZERO, @@ -114,7 +114,7 @@ mod tests { #[test] fn builds_with_clear_filter_expands_to_four_types() { let stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), U256::from(1), Address::ZERO, Address::ZERO, @@ -129,7 +129,7 @@ mod tests { #[test] fn builds_with_multiple_filter_types() { let stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), U256::from(1), Address::ZERO, Address::ZERO, @@ -147,7 +147,7 @@ mod tests { #[test] fn builds_with_empty_filter_array() { let stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), U256::from(1), Address::ZERO, Address::ZERO, diff --git a/crates/common/src/local_db/query/fetch_vault_balance_changes/query.sql b/crates/common/src/local_db/query/fetch_vault_balance_changes/query.sql index ca1fb5ba59..99e1cd3d9e 100644 --- a/crates/common/src/local_db/query/fetch_vault_balance_changes/query.sql +++ b/crates/common/src/local_db/query/fetch_vault_balance_changes/query.sql @@ -1,7 +1,7 @@ WITH params AS ( SELECT ?1 AS chain_id, - ?2 AS orderbook_address, + ?2 AS raindex_address, ?3 AS vault_id, ?4 AS token, ?5 AS owner @@ -20,7 +20,7 @@ SELECT FROM vault_balance_changes vbc JOIN params p ON p.chain_id = vbc.chain_id - AND p.orderbook_address = vbc.orderbook_address + AND p.raindex_address = vbc.raindex_address AND p.vault_id = vbc.vault_id AND p.token = vbc.token AND p.owner = vbc.owner diff --git a/crates/common/src/local_db/query/fetch_vaults/mod.rs b/crates/common/src/local_db/query/fetch_vaults/mod.rs index 0a5b6492c8..d13efb9c13 100644 --- a/crates/common/src/local_db/query/fetch_vaults/mod.rs +++ b/crates/common/src/local_db/query/fetch_vaults/mod.rs @@ -11,7 +11,7 @@ pub struct LocalDbVault { pub vault_id: U256, pub token: Address, pub owner: Address, - pub orderbook_address: Address, + pub raindex_address: Address, pub token_name: String, pub token_symbol: String, pub token_decimals: u8, @@ -23,7 +23,7 @@ pub struct LocalDbVault { #[derive(Debug, Clone, Default)] pub struct FetchVaultsArgs { pub chain_ids: Vec, - pub orderbook_addresses: Vec
, + pub raindex_addresses: Vec
, pub owners: Vec
, pub tokens: Vec
, pub hide_zero_balance: bool, @@ -39,8 +39,8 @@ const TOKENS_CLAUSE_BODY: &str = "\nAND o.token IN ({list})\n"; const CHAIN_IDS_CLAUSE: &str = "/*CHAIN_IDS_CLAUSE*/"; const CHAIN_IDS_BODY: &str = "AND rvb.chain_id IN ({list})"; -const ORDERBOOKS_CLAUSE: &str = "/*ORDERBOOKS_CLAUSE*/"; -const ORDERBOOKS_BODY: &str = "AND rvb.orderbook_address IN ({list})"; +const RAINDEXES_CLAUSE: &str = "/*RAINDEXES_CLAUSE*/"; +const RAINDEXES_BODY: &str = "AND rvb.raindex_address IN ({list})"; const HIDE_ZERO_BALANCE_CLAUSE: &str = "/*HIDE_ZERO_BALANCE*/"; const HIDE_ZERO_BALANCE_BODY: &str = "\nAND NOT FLOAT_IS_ZERO(o.balance)\n"; @@ -49,7 +49,7 @@ const ONLY_ACTIVE_ORDERS_CLAUSE: &str = "/*ONLY_ACTIVE_ORDERS_CLAUSE*/"; const ONLY_ACTIVE_ORDERS_BODY: &str = "\nAND EXISTS ( SELECT 1 FROM order_io_items oii WHERE oii.chain_id = o.chain_id - AND oii.orderbook_address = o.orderbook_address + AND oii.raindex_address = o.raindex_address AND oii.owner = o.owner AND oii.token = o.token AND oii.vault_id = o.vault_id @@ -58,13 +58,13 @@ const ONLY_ACTIVE_ORDERS_BODY: &str = "\nAND EXISTS ( const INNER_CHAIN_IDS_CLAUSE: &str = "/*INNER_CHAIN_IDS_CLAUSE*/"; const INNER_CHAIN_IDS_BODY: &str = "AND chain_id IN ({list})"; -const INNER_ORDERBOOKS_CLAUSE: &str = "/*INNER_ORDERBOOKS_CLAUSE*/"; -const INNER_ORDERBOOKS_BODY: &str = "AND orderbook_address IN ({list})"; +const INNER_RAINDEXES_CLAUSE: &str = "/*INNER_RAINDEXES_CLAUSE*/"; +const INNER_RAINDEXES_BODY: &str = "AND raindex_address IN ({list})"; const OIO_CHAIN_IDS_CLAUSE: &str = "/*OIO_CHAIN_IDS_CLAUSE*/"; const OIO_CHAIN_IDS_BODY: &str = "AND io.chain_id IN ({list})"; -const OIO_ORDERBOOKS_CLAUSE: &str = "/*OIO_ORDERBOOKS_CLAUSE*/"; -const OIO_ORDERBOOKS_BODY: &str = "AND io.orderbook_address IN ({list})"; +const OIO_RAINDEXES_CLAUSE: &str = "/*OIO_RAINDEXES_CLAUSE*/"; +const OIO_RAINDEXES_BODY: &str = "AND io.raindex_address IN ({list})"; pub fn build_fetch_vaults_stmt(args: &FetchVaultsArgs) -> Result { let mut stmt = SqlStatement::new(QUERY_TEMPLATE); @@ -81,21 +81,17 @@ pub fn build_fetch_vaults_stmt(args: &FetchVaultsArgs) -> Result SqlStatement { let mut stmt = SqlStatement::new(QUERY_TEMPLATE); // ?1 -> chain id - stmt.push(SqlValue::I64(ob_id.chain_id as i64)); - // ?2 -> orderbook address - stmt.push(SqlValue::Text(ob_id.orderbook_address.to_string())); + stmt.push(SqlValue::I64(raindex_id.chain_id as i64)); + // ?2 -> raindex address + stmt.push(SqlValue::Text(raindex_id.raindex_address.to_string())); // ?3 -> block number stmt.push(SqlValue::I64(block_number as i64)); stmt @@ -28,7 +28,7 @@ mod tests { #[test] fn builds_update_query() { let stmt = build_update_last_synced_block_stmt( - &OrderbookIdentifier::new(42161, Address::from([0x11u8; 20])), + &RaindexIdentifier::new(42161, Address::from([0x11u8; 20])), 999, ); assert!(stmt.sql.contains("ON CONFLICT")); diff --git a/crates/common/src/local_db/query/update_last_synced_block/query.sql b/crates/common/src/local_db/query/update_last_synced_block/query.sql index b71b46a115..1c3ed217cf 100644 --- a/crates/common/src/local_db/query/update_last_synced_block/query.sql +++ b/crates/common/src/local_db/query/update_last_synced_block/query.sql @@ -1,13 +1,13 @@ INSERT INTO sync_status ( chain_id, - orderbook_address, + raindex_address, last_synced_block ) VALUES ( ?1, ?2, ?3 ) -ON CONFLICT(chain_id, orderbook_address) +ON CONFLICT(chain_id, raindex_address) DO UPDATE SET last_synced_block = excluded.last_synced_block, updated_at = CURRENT_TIMESTAMP; diff --git a/crates/common/src/local_db/query/upsert_target_watermark/mod.rs b/crates/common/src/local_db/query/upsert_target_watermark/mod.rs index 5bb28fa756..ada22e9e1e 100644 --- a/crates/common/src/local_db/query/upsert_target_watermark/mod.rs +++ b/crates/common/src/local_db/query/upsert_target_watermark/mod.rs @@ -1,21 +1,21 @@ use crate::local_db::{ query::{SqlStatement, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; use alloy::primitives::Bytes; const QUERY_TEMPLATE: &str = include_str!("query.sql"); pub fn upsert_target_watermark_stmt( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, last_block: u64, last_hash: Bytes, ) -> SqlStatement { SqlStatement::new_with_params( QUERY_TEMPLATE, [ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), SqlValue::from(last_block), SqlValue::from(last_hash), ], @@ -31,7 +31,7 @@ mod tests { #[test] fn upsert_stmt_binds_all_params() { let stmt = upsert_target_watermark_stmt( - &OrderbookIdentifier::new(10, Address::from([0xabu8; 20])), + &RaindexIdentifier::new(10, Address::from([0xabu8; 20])), 123, Bytes::from_str("0xbeef").unwrap(), ); @@ -42,27 +42,27 @@ mod tests { #[test] fn upsert_stmt_sql_matches_template_and_columns() { let stmt = upsert_target_watermark_stmt( - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), 0, Bytes::from_str("0xbeef").unwrap(), ); assert_eq!(stmt.sql(), QUERY_TEMPLATE); let lower = stmt.sql().to_lowercase(); assert!(lower.contains("insert into target_watermarks")); - assert!(lower.contains("(chain_id, orderbook_address, last_block, last_hash)")); + assert!(lower.contains("(chain_id, raindex_address, last_block, last_hash)")); assert!(lower.contains("values (?1, ?2, ?3, ?4)")); - assert!(lower.contains("on conflict(chain_id, orderbook_address)")); + assert!(lower.contains("on conflict(chain_id, raindex_address)")); assert!(lower.contains("updated_at = (cast(strftime('%s', 'now') as integer) * 1000)")); } #[test] fn upsert_stmt_param_order_and_values() { let chain_id = 100u32; - let orderbook = Address::from([0x11u8; 20]); + let raindex = Address::from([0x11u8; 20]); let last_block = 42u64; let last_hash = Bytes::from_str("0xdeadbeef").unwrap(); let stmt = upsert_target_watermark_stmt( - &OrderbookIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), last_block, last_hash.clone(), ); @@ -70,7 +70,7 @@ mod tests { let params = stmt.params(); assert_eq!(params.len(), 4); assert_eq!(params[0], SqlValue::U64(chain_id as u64)); - assert_eq!(params[1], SqlValue::Text(orderbook.to_string())); + assert_eq!(params[1], SqlValue::Text(raindex.to_string())); assert_eq!(params[2], SqlValue::U64(last_block)); assert_eq!(params[3], SqlValue::Text(last_hash.to_string())); } diff --git a/crates/common/src/local_db/query/upsert_target_watermark/query.sql b/crates/common/src/local_db/query/upsert_target_watermark/query.sql index 76b746b8b2..6519512035 100644 --- a/crates/common/src/local_db/query/upsert_target_watermark/query.sql +++ b/crates/common/src/local_db/query/upsert_target_watermark/query.sql @@ -1,6 +1,6 @@ -INSERT INTO target_watermarks (chain_id, orderbook_address, last_block, last_hash) +INSERT INTO target_watermarks (chain_id, raindex_address, last_block, last_hash) VALUES (?1, ?2, ?3, ?4) -ON CONFLICT(chain_id, orderbook_address) DO UPDATE SET +ON CONFLICT(chain_id, raindex_address) DO UPDATE SET last_block = excluded.last_block, last_hash = excluded.last_hash, updated_at = (CAST(strftime('%s', 'now') AS INTEGER) * 1000); diff --git a/crates/common/src/local_db/query/upsert_vault_balances/insert_balance_changes.sql b/crates/common/src/local_db/query/upsert_vault_balances/insert_balance_changes.sql index 56b16be0f9..6f33926a97 100644 --- a/crates/common/src/local_db/query/upsert_vault_balances/insert_balance_changes.sql +++ b/crates/common/src/local_db/query/upsert_vault_balances/insert_balance_changes.sql @@ -1,14 +1,14 @@ WITH RECURSIVE params AS ( SELECT ?1 AS chain_id, - ?2 AS orderbook_address, + ?2 AS raindex_address, ?3 AS start_block, ?4 AS end_block ), filtered AS ( SELECT vd.chain_id, - vd.orderbook_address, + vd.raindex_address, vd.transaction_hash, vd.owner, vd.token, @@ -19,17 +19,17 @@ filtered AS ( vd.kind AS change_type, vd.delta, ROW_NUMBER() OVER ( - PARTITION BY vd.chain_id, vd.orderbook_address, vd.owner, vd.token, vd.vault_id + PARTITION BY vd.chain_id, vd.raindex_address, vd.owner, vd.token, vd.vault_id ORDER BY vd.block_number, vd.log_index ) AS rn, COALESCE(rvb.balance, FLOAT_ZERO_HEX()) AS prefix_balance FROM vault_deltas vd JOIN params p ON p.chain_id = vd.chain_id - AND p.orderbook_address = vd.orderbook_address + AND p.raindex_address = vd.raindex_address LEFT JOIN running_vault_balances rvb ON rvb.chain_id = vd.chain_id - AND rvb.orderbook_address = vd.orderbook_address + AND rvb.raindex_address = vd.raindex_address AND rvb.owner = vd.owner AND rvb.token = vd.token AND rvb.vault_id = vd.vault_id @@ -38,7 +38,7 @@ filtered AS ( ordered AS ( SELECT f.chain_id, - f.orderbook_address, + f.raindex_address, f.transaction_hash, f.owner, f.token, @@ -67,7 +67,7 @@ ordered AS ( SELECT next.chain_id, - next.orderbook_address, + next.raindex_address, next.transaction_hash, next.owner, next.token, @@ -92,7 +92,7 @@ ordered AS ( FROM ordered JOIN filtered next ON next.chain_id = ordered.chain_id - AND next.orderbook_address = ordered.orderbook_address + AND next.raindex_address = ordered.raindex_address AND next.owner = ordered.owner AND next.token = ordered.token AND next.vault_id = ordered.vault_id @@ -100,7 +100,7 @@ ordered AS ( ) INSERT OR IGNORE INTO vault_balance_changes ( chain_id, - orderbook_address, + raindex_address, transaction_hash, owner, token, @@ -114,7 +114,7 @@ INSERT OR IGNORE INTO vault_balance_changes ( ) SELECT chain_id, - orderbook_address, + raindex_address, transaction_hash, owner, token, diff --git a/crates/common/src/local_db/query/upsert_vault_balances/insert_running_balances.sql b/crates/common/src/local_db/query/upsert_vault_balances/insert_running_balances.sql index c69a56edba..4ed8a8a66c 100644 --- a/crates/common/src/local_db/query/upsert_vault_balances/insert_running_balances.sql +++ b/crates/common/src/local_db/query/upsert_vault_balances/insert_running_balances.sql @@ -1,21 +1,21 @@ WITH latest_blocks AS ( SELECT chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, MAX(block_number) AS last_block FROM vault_deltas vd WHERE vd.chain_id = ?1 - AND vd.orderbook_address = ?2 + AND vd.raindex_address = ?2 AND vd.block_number BETWEEN ?3 AND ?4 - GROUP BY chain_id, orderbook_address, owner, token, vault_id + GROUP BY chain_id, raindex_address, owner, token, vault_id ), delta_batches AS ( SELECT vd.chain_id, - vd.orderbook_address, + vd.raindex_address, vd.owner, vd.token, vd.vault_id, @@ -28,7 +28,7 @@ delta_batches AS ( SELECT MAX(vd2.log_index) FROM vault_deltas vd2 WHERE vd2.chain_id = vd.chain_id - AND vd2.orderbook_address = vd.orderbook_address + AND vd2.raindex_address = vd.raindex_address AND vd2.owner = vd.owner AND vd2.token = vd.token AND vd2.vault_id = vd.vault_id @@ -37,19 +37,19 @@ delta_batches AS ( FROM vault_deltas vd JOIN latest_blocks lb ON lb.chain_id = vd.chain_id - AND lb.orderbook_address = vd.orderbook_address + AND lb.raindex_address = vd.raindex_address AND lb.owner = vd.owner AND lb.token = vd.token AND lb.vault_id = vd.vault_id WHERE vd.chain_id = ?1 - AND vd.orderbook_address = ?2 + AND vd.raindex_address = ?2 AND vd.block_number BETWEEN ?3 AND ?4 - GROUP BY vd.chain_id, vd.orderbook_address, vd.owner, vd.token, vd.vault_id, lb.last_block + GROUP BY vd.chain_id, vd.raindex_address, vd.owner, vd.token, vd.vault_id, lb.last_block ), existing_matching AS ( SELECT mvb.chain_id, - mvb.orderbook_address, + mvb.raindex_address, mvb.owner, mvb.token, mvb.vault_id, @@ -59,7 +59,7 @@ existing_matching AS ( FROM running_vault_balances mvb JOIN delta_batches db ON db.chain_id = mvb.chain_id - AND db.orderbook_address = mvb.orderbook_address + AND db.raindex_address = mvb.raindex_address AND db.owner = mvb.owner AND db.token = mvb.token AND db.vault_id = mvb.vault_id @@ -67,7 +67,7 @@ existing_matching AS ( combined AS ( SELECT chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, @@ -78,7 +78,7 @@ combined AS ( UNION ALL SELECT chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, @@ -90,18 +90,18 @@ combined AS ( aggregated AS ( SELECT chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, COALESCE(FLOAT_SUM(contribution), FLOAT_ZERO_HEX()) AS balance, MAX(last_block) AS last_block FROM combined - GROUP BY chain_id, orderbook_address, owner, token, vault_id + GROUP BY chain_id, raindex_address, owner, token, vault_id ) INSERT OR REPLACE INTO running_vault_balances ( chain_id, - orderbook_address, + raindex_address, owner, token, vault_id, @@ -112,7 +112,7 @@ INSERT OR REPLACE INTO running_vault_balances ( ) SELECT a.chain_id, - a.orderbook_address, + a.raindex_address, a.owner, a.token, a.vault_id, @@ -122,7 +122,7 @@ SELECT SELECT c.last_log_index FROM combined c WHERE c.chain_id = a.chain_id - AND c.orderbook_address = a.orderbook_address + AND c.raindex_address = a.raindex_address AND c.owner = a.owner AND c.token = a.token AND c.vault_id = a.vault_id diff --git a/crates/common/src/local_db/query/upsert_vault_balances/mod.rs b/crates/common/src/local_db/query/upsert_vault_balances/mod.rs index 434b232fb8..02debc726a 100644 --- a/crates/common/src/local_db/query/upsert_vault_balances/mod.rs +++ b/crates/common/src/local_db/query/upsert_vault_balances/mod.rs @@ -1,32 +1,37 @@ use crate::local_db::{ query::{SqlStatement, SqlStatementBatch, SqlValue}, - OrderbookIdentifier, + RaindexIdentifier, }; const UPSERT_RUNNING_SQL: &str = include_str!("insert_running_balances.sql"); const INSERT_BALANCE_CHANGES_SQL: &str = include_str!("insert_balance_changes.sql"); pub fn upsert_vault_balances_batch( - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, start_block: u64, end_block: u64, ) -> SqlStatementBatch { - let change_stmt = build_stmt(INSERT_BALANCE_CHANGES_SQL, ob_id, start_block, end_block); - let running_stmt = build_stmt(UPSERT_RUNNING_SQL, ob_id, start_block, end_block); + let change_stmt = build_stmt( + INSERT_BALANCE_CHANGES_SQL, + raindex_id, + start_block, + end_block, + ); + let running_stmt = build_stmt(UPSERT_RUNNING_SQL, raindex_id, start_block, end_block); SqlStatementBatch::from(vec![change_stmt, running_stmt]) } fn build_stmt( template: &str, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, start_block: u64, end_block: u64, ) -> SqlStatement { SqlStatement::new_with_params( template, [ - SqlValue::from(ob_id.chain_id), - SqlValue::from(ob_id.orderbook_address), + SqlValue::from(raindex_id.chain_id), + SqlValue::from(raindex_id.raindex_address), SqlValue::from(start_block), SqlValue::from(end_block), ], @@ -40,15 +45,15 @@ mod tests { #[test] fn batch_binds_all_params() { - let ob_id = OrderbookIdentifier::new(111, Address::from([0x11u8; 20])); - let batch = upsert_vault_balances_batch(&ob_id, 100, 200); + let raindex_id = RaindexIdentifier::new(111, Address::from([0x11u8; 20])); + let batch = upsert_vault_balances_batch(&raindex_id, 100, 200); assert_eq!(batch.len(), 2); for stmt in batch.statements() { assert_eq!(stmt.params().len(), 4); assert_eq!(stmt.params()[0], SqlValue::U64(111)); assert_eq!( stmt.params()[1], - SqlValue::Text(ob_id.orderbook_address.to_string()) + SqlValue::Text(raindex_id.raindex_address.to_string()) ); assert_eq!(stmt.params()[2], SqlValue::U64(100)); assert_eq!(stmt.params()[3], SqlValue::U64(200)); @@ -57,7 +62,7 @@ mod tests { #[test] fn batch_targets_change_log_and_running_tables() { - let batch = upsert_vault_balances_batch(&OrderbookIdentifier::new(1, Address::ZERO), 0, 10); + let batch = upsert_vault_balances_batch(&RaindexIdentifier::new(1, Address::ZERO), 0, 10); let sql: Vec<_> = batch .statements() .iter() @@ -70,7 +75,7 @@ mod tests { #[test] fn batch_filters_block_range() { let batch = upsert_vault_balances_batch( - &OrderbookIdentifier::new(3, Address::from([0x55; 20])), + &RaindexIdentifier::new(3, Address::from([0x55; 20])), 123, 456, ); @@ -87,7 +92,7 @@ mod tests { #[test] fn running_stmt_includes_zero_balance_batches() { - let batch = upsert_vault_balances_batch(&OrderbookIdentifier::new(4, Address::ZERO), 0, 0); + let batch = upsert_vault_balances_batch(&RaindexIdentifier::new(4, Address::ZERO), 0, 0); let sql = batch.statements()[1].sql().to_lowercase(); assert!( !sql.contains("having not float_is_zero"), @@ -97,7 +102,7 @@ mod tests { #[test] fn running_stmt_uses_float_sum_for_updates() { - let batch = upsert_vault_balances_batch(&OrderbookIdentifier::new(5, Address::ZERO), 0, 1); + let batch = upsert_vault_balances_batch(&RaindexIdentifier::new(5, Address::ZERO), 0, 1); let sql = batch.statements()[1].sql().to_lowercase(); assert!( sql.contains("insert or replace into running_vault_balances"), diff --git a/crates/common/src/local_db/token_fetch.rs b/crates/common/src/local_db/token_fetch.rs index 258c95da5f..e0191dde18 100644 --- a/crates/common/src/local_db/token_fetch.rs +++ b/crates/common/src/local_db/token_fetch.rs @@ -66,7 +66,7 @@ mod tests { use crate::local_db::{FetchConfig, LocalDbError}; use crate::rpc_client::RpcClient; use alloy::primitives::Address; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use url::Url; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] diff --git a/crates/common/src/meta.rs b/crates/common/src/meta.rs index fc20d5cdeb..1fcedbafd8 100644 --- a/crates/common/src/meta.rs +++ b/crates/common/src/meta.rs @@ -46,8 +46,8 @@ impl TryDecodeRainlangSource for String { #[cfg(test)] mod tests { - use rain_orderbook_subgraph_client::types::common::SgBytes; - use rain_orderbook_subgraph_client::types::common::SgRainMetaV1; + use raindex_subgraph_client::types::common::SgBytes; + use raindex_subgraph_client::types::common::SgRainMetaV1; use super::*; diff --git a/crates/common/src/oracle.rs b/crates/common/src/oracle.rs index 7dfbcf95a6..976796feec 100644 --- a/crates/common/src/oracle.rs +++ b/crates/common/src/oracle.rs @@ -1,3 +1,3 @@ // Re-export oracle types and functions from the quote crate. // This maintains backward compatibility for code in common that uses oracle functionality. -pub use rain_orderbook_quote::oracle::*; +pub use raindex_quote::oracle::*; diff --git a/crates/common/src/parsed_meta.rs b/crates/common/src/parsed_meta.rs index 16d6949fc4..54dbd7bbda 100644 --- a/crates/common/src/parsed_meta.rs +++ b/crates/common/src/parsed_meta.rs @@ -48,7 +48,7 @@ impl ParsedMeta { } /// Parse multiple metadata items from a vector of RainMetaDocumentV1Item - /// Returns only the items relevant to the orderbook frontend + /// Returns only the items relevant to the raindex frontend pub fn parse_multiple( items: &[RainMetaDocumentV1Item], ) -> Result, rain_metadata::Error> { @@ -60,7 +60,7 @@ impl ParsedMeta { } /// Parse metadata from raw bytes - /// This method parses the complete metadata document and extracts only orderbook-relevant items + /// This method parses the complete metadata document and extracts only raindex-relevant items pub fn parse_from_bytes(bytes: &[u8]) -> Result, rain_metadata::Error> { let items = RainMetaDocumentV1Item::cbor_decode(bytes)?; Self::parse_multiple(&items) diff --git a/crates/common/src/raindex_client/add_orders.rs b/crates/common/src/raindex_client/add_orders.rs index 11cecfe674..486f5abcbf 100644 --- a/crates/common/src/raindex_client/add_orders.rs +++ b/crates/common/src/raindex_client/add_orders.rs @@ -45,11 +45,11 @@ impl RaindexClient { #[wasm_export(js_name = "chainId", param_description = "Chain ID for the network")] chain_id: u32, #[wasm_export( - js_name = "orderbookAddress", - param_description = "Orderbook contract address", + js_name = "raindexAddress", + param_description = "Raindex contract address", unchecked_param_type = "Hex" )] - orderbook_address: String, + raindex_address: String, #[wasm_export( js_name = "txHash", param_description = "Transaction hash", @@ -67,11 +67,11 @@ impl RaindexClient { )] interval_ms: Option, ) -> Result, RaindexError> { - let orderbook_address = Address::from_str(&orderbook_address)?; + let raindex_address = Address::from_str(&raindex_address)?; let tx_hash = B256::from_str(&tx_hash)?; self.get_add_orders_for_transaction( chain_id, - orderbook_address, + raindex_address, tx_hash, max_attempts.map(|v| v as usize), interval_ms.map(|v| v as u64), @@ -83,7 +83,7 @@ impl RaindexClient { async fn get_add_orders_for_transaction( &self, chain_id: u32, - orderbook_address: Address, + raindex_address: Address, tx_hash: B256, max_attempts: Option, interval_ms: Option, @@ -101,7 +101,7 @@ impl RaindexClient { let local_result = retry_with_constant_interval( || async { let orders = local_source - .get_added_by_tx_hash(chain_id, orderbook_address, tx_hash) + .get_added_by_tx_hash(chain_id, raindex_address, tx_hash) .await .map_err(PollError::Inner)?; if orders.is_empty() { @@ -133,12 +133,12 @@ impl RaindexClient { let subgraph_result = retry_with_constant_interval( || async { let orders = match subgraph_source - .get_added_by_tx_hash(chain_id, orderbook_address, tx_hash) + .get_added_by_tx_hash(chain_id, raindex_address, tx_hash) .await { Ok(orders) => orders, - Err(RaindexError::OrderbookSubgraphClientError( - rain_orderbook_subgraph_client::OrderbookSubgraphClientError::Empty, + Err(RaindexError::RaindexSubgraphClientError( + raindex_subgraph_client::RaindexSubgraphClientError::Empty, )) => return Err(PollError::Empty), Err(e) => return Err(PollError::Inner(e)), }; @@ -179,7 +179,7 @@ mod tests { mod non_wasm { use super::*; use crate::raindex_client::tests::{ - get_test_yaml, new_with_local_db, CHAIN_ID_1_ORDERBOOK_ADDRESS, + get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS, }; use crate::{ local_db::query::{ @@ -191,7 +191,7 @@ mod tests { use alloy::primitives::{b256, Address, Bytes, U256}; use async_trait::async_trait; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; use std::{ str::FromStr, @@ -274,7 +274,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -301,7 +301,7 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -315,7 +315,7 @@ mod tests { "balanceChanges": [] } ], - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "active": true, @@ -364,7 +364,7 @@ mod tests { let res = raindex_client .get_add_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), None, None, @@ -408,7 +408,7 @@ mod tests { assert_eq!(order.meta(), Some(Bytes::from_str("0xff0a89c674ee7874a3005902252f2a20302e2063616c63756c6174652d696f202a2f200a7573696e672d776f7264732d66726f6d203078466532343131434461313933443945346538334135633233344337466433323031303138383361430a616d743a203130302c0a696f3a2063616c6c3c323e28293b0a0a2f2a20312e2068616e646c652d696f202a2f200a3a63616c6c3c333e28292c0a3a656e7375726528657175616c2d746f286f75747075742d7661756c742d64656372656173652829203130302920226d7573742074616b652066756c6c20616d6f756e7422293b0a0a2f2a20322e206765742d696f2d726174696f2d6e6f77202a2f200a656c61707365643a2063616c6c3c343e28292c0a696f3a2073617475726174696e672d73756228302e3031373733353620646976286d756c28656c61707365642073756228302e3031373733353620302e30313733383434292920363029293b0a0a2f2a20332e206f6e652d73686f74202a2f200a3a656e737572652869732d7a65726f286765742868617368286f726465722d68617368282920226861732d657865637574656422292929202268617320657865637574656422292c0a3a7365742868617368286f726465722d68617368282920226861732d657865637574656422292031293b0a0a2f2a20342e206765742d656c6170736564202a2f200a5f3a20737562286e6f772829206765742868617368286f726465722d68617368282920226465706c6f792d74696d65222929293b011bff13109e41336ff20278186170706c69636174696f6e2f6f637465742d73747265616d").unwrap())); assert!(order.active()); assert_eq!( - order.orderbook(), + order.raindex(), Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); @@ -445,7 +445,7 @@ mod tests { assert_eq!(output.token().symbol(), Some("sFLR".to_string())); assert_eq!(output.token().decimals(), 18); assert_eq!( - output.orderbook(), + output.raindex(), Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); assert_eq!(output.orders_as_outputs().len(), 1); @@ -493,7 +493,7 @@ mod tests { assert_eq!(input.token().symbol(), Some("WFLR".to_string())); assert_eq!(input.token().decimals(), 18); assert_eq!( - input.orderbook(), + input.raindex(), Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); assert!(input.orders_as_outputs().is_empty()); @@ -549,7 +549,7 @@ mod tests { let res = raindex_client .get_add_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_ADD_ORDER_POLL_ATTEMPTS), Some(10), @@ -583,7 +583,7 @@ mod tests { let err = raindex_client .get_add_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_ADD_ORDER_POLL_ATTEMPTS), Some(10), @@ -603,7 +603,7 @@ mod tests { async fn test_get_transaction_add_orders_prefers_local_db() { let tx_hash = b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"); - let orderbook_address = + let raindex_address = Address::from_str("0x0987654321098765432109876543210987654321").unwrap(); let owner = Address::from_str("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(); @@ -615,7 +615,7 @@ mod tests { owner, block_timestamp: 1_000, block_number: 50, - orderbook_address, + raindex_address, order_bytes: Bytes::from_str("0x01").unwrap(), transaction_hash: tx_hash, inputs: None, @@ -651,7 +651,7 @@ mod tests { .await; let res = client - .get_add_orders_for_transaction(137, orderbook_address, tx_hash, Some(3), Some(1)) + .get_add_orders_for_transaction(137, raindex_address, tx_hash, Some(3), Some(1)) .await .unwrap(); @@ -671,7 +671,7 @@ mod tests { async fn test_get_transaction_add_orders_exhausts_local_without_fallback() { let tx_hash = b256!("0x00000000000000000000000000000000000000000000000000000000cafebabe"); - let orderbook_address = + let raindex_address = Address::from_str("0x0987654321098765432109876543210987654321").unwrap(); let local_exec = CountingJsonExec { @@ -701,7 +701,7 @@ mod tests { .await; let err = client - .get_add_orders_for_transaction(137, orderbook_address, tx_hash, Some(2), Some(1)) + .get_add_orders_for_transaction(137, raindex_address, tx_hash, Some(2), Some(1)) .await .unwrap_err(); diff --git a/crates/common/src/raindex_client/local_db/mod.rs b/crates/common/src/raindex_client/local_db/mod.rs index 4c9ec13c11..5dd82b4b81 100644 --- a/crates/common/src/raindex_client/local_db/mod.rs +++ b/crates/common/src/raindex_client/local_db/mod.rs @@ -2,7 +2,7 @@ pub use crate::local_db::pipeline::SyncPhase; use crate::local_db::query::{ FromDbJson, LocalDbQueryError, LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; #[cfg(target_family = "wasm")] use executor::JsCallbackExecutor; @@ -27,7 +27,7 @@ pub mod vaults; pub use state::SyncReadiness; pub(crate) use state::{ClassifiedChains, LocalDbState, QuerySource}; pub use status::{ - LocalDbStatus, LocalDbStatusSnapshot, NetworkSyncStatus, OrderbookSyncStatus, SchedulerState, + LocalDbStatus, LocalDbStatusSnapshot, NetworkSyncStatus, RaindexSyncStatus, SchedulerState, }; #[cfg(target_family = "wasm")] @@ -337,9 +337,9 @@ mod wasm_tests { use super::*; use crate::raindex_client::RaindexClient; use gloo_timers::future::TimeoutFuture; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::{ - orderbook::{OrderbookYaml, OrderbookYamlValidation}, + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::{ + raindex::{RaindexYaml, RaindexYamlValidation}, YamlParsable, }; use std::cell::RefCell; @@ -354,7 +354,7 @@ mod wasm_tests { wasm_bindgen_test_configure!(run_in_browser); - fn single_orderbook_settings_yaml() -> String { + fn single_raindex_settings_yaml() -> String { format!( r#" version: {version} @@ -377,8 +377,8 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 1000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil @@ -391,9 +391,9 @@ orderbooks: #[cfg(not(target_family = "wasm"))] async fn build_client() -> RaindexClient { - RaindexClient::new(vec![single_orderbook_settings_yaml()], None, None) + RaindexClient::new(vec![single_raindex_settings_yaml()], None, None) .await - .expect("valid orderbook yaml") + .expect("valid raindex yaml") } fn success_callback() -> js_sys::Function { diff --git a/crates/common/src/raindex_client/local_db/orders.rs b/crates/common/src/raindex_client/local_db/orders.rs index 5708713d13..809c110f8b 100644 --- a/crates/common/src/raindex_client/local_db/orders.rs +++ b/crates/common/src/raindex_client/local_db/orders.rs @@ -10,7 +10,7 @@ use super::LocalDb; use crate::local_db::query::fetch_orders::LocalDbOrder; use crate::local_db::query::fetch_vaults::LocalDbVault; use crate::local_db::query::LocalDbQueryError; -use crate::local_db::{query::fetch_orders::FetchOrdersArgs, OrderbookIdentifier}; +use crate::local_db::{query::fetch_orders::FetchOrdersArgs, RaindexIdentifier}; use crate::raindex_client::local_db::query::fetch_orders::fetch_orders; use crate::raindex_client::ClientRef; use alloy::primitives::{Address, B256}; @@ -40,12 +40,12 @@ impl<'a> LocalDbOrders<'a> { async fn fetch_orders_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError> { let fetch_args = FetchOrdersArgs { chain_ids: vec![chain_id], - orderbook_addresses: vec![orderbook], + raindex_addresses: vec![raindex], tx_hash: Some(tx_hash), ..FetchOrdersArgs::default() }; @@ -139,12 +139,12 @@ impl OrdersDataSource for LocalDbOrders<'_> { async fn get_by_hash( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, ) -> Result, RaindexError> { let fetch_args = FetchOrdersArgs { - chain_ids: vec![ob_id.chain_id], - orderbook_addresses: vec![ob_id.orderbook_address], + chain_ids: vec![raindex_id.chain_id], + raindex_addresses: vec![raindex_id.raindex_address], order_hash: Some(*order_hash), ..FetchOrdersArgs::default() }; @@ -162,51 +162,61 @@ impl OrdersDataSource for LocalDbOrders<'_> { async fn get_added_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError> { - self.fetch_orders_by_tx_hash(chain_id, orderbook, tx_hash) + self.fetch_orders_by_tx_hash(chain_id, raindex, tx_hash) .await } async fn get_removed_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError> { - self.fetch_orders_by_tx_hash(chain_id, orderbook, tx_hash) + self.fetch_orders_by_tx_hash(chain_id, raindex, tx_hash) .await } async fn trades_list( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, _page: Option, ) -> Result, RaindexError> { - let local_trades = - fetch_order_trades(self.db, ob_id, *order_hash, start_timestamp, end_timestamp).await?; + let local_trades = fetch_order_trades( + self.db, + raindex_id, + *order_hash, + start_timestamp, + end_timestamp, + ) + .await?; local_trades .into_iter() - .map(|trade| RaindexTrade::try_from_local_db_trade(ob_id.chain_id, trade)) + .map(|trade| RaindexTrade::try_from_local_db_trade(raindex_id.chain_id, trade)) .collect() } async fn trades_count( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { - Ok( - fetch_order_trades_count(self.db, ob_id, *order_hash, start_timestamp, end_timestamp) - .await?, + Ok(fetch_order_trades_count( + self.db, + raindex_id, + *order_hash, + start_timestamp, + end_timestamp, ) + .await?) } } @@ -297,14 +307,14 @@ mod tests { let output_vault_id = U256::from_str("0x0b").unwrap(); let input_token = address!("0x00000000000000000000000000000000000000aa"); let output_token = address!("0x00000000000000000000000000000000000000bb"); - let orderbook_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); + let raindex_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); let input_vault = LocalDbVault { chain_id: 1, vault_id: input_vault_id, token: input_token, owner, - orderbook_address, + raindex_address, token_name: "Token A".to_string(), token_symbol: "TKNA".to_string(), token_decimals: 18, @@ -319,7 +329,7 @@ mod tests { vault_id: output_vault_id, token: output_token, owner, - orderbook_address, + raindex_address, token_name: "Token B".to_string(), token_symbol: "TKNB".to_string(), token_decimals: 6, @@ -336,7 +346,7 @@ mod tests { "vaultId": input_vault.vault_id, "token": input_vault.token, "owner": input_vault.owner, - "orderbookAddress": input_vault.orderbook_address, + "raindexAddress": input_vault.raindex_address, "tokenName": input_vault.token_name, "tokenSymbol": input_vault.token_symbol, "tokenDecimals": input_vault.token_decimals, @@ -353,7 +363,7 @@ mod tests { "vaultId": output_vault.vault_id, "token": output_vault.token, "owner": output_vault.owner, - "orderbookAddress": output_vault.orderbook_address, + "raindexAddress": output_vault.raindex_address, "tokenName": output_vault.token_name, "tokenSymbol": output_vault.token_symbol, "tokenDecimals": output_vault.token_decimals, @@ -369,7 +379,7 @@ mod tests { owner, block_timestamp: 123456, block_number: 654321, - orderbook_address, + raindex_address, order_bytes: order_bytes, transaction_hash: transaction_hash.clone(), inputs: Some(inputs_json.to_string()), @@ -406,7 +416,7 @@ mod tests { assert!(order.active()); assert_eq!(order.trades_count(), local_order.trade_count as u16); assert_eq!(order.meta(), Some(meta_str)); - assert_eq!(order.orderbook(), orderbook_address.to_string()); + assert_eq!(order.raindex(), raindex_address.to_string()); let tx = order .transaction() .expect("transaction should be populated"); @@ -449,8 +459,8 @@ mod tests { Some(input_vault.token_symbol.clone()) ); assert_eq!( - input_vaults[0].orderbook(), - input_vault.orderbook_address.to_string() + input_vaults[0].raindex(), + input_vault.raindex_address.to_string() ); let output_vaults = order.outputs_list().items(); @@ -460,8 +470,8 @@ mod tests { Some(output_vault.token_symbol.clone()) ); assert_eq!( - output_vaults[0].orderbook(), - output_vault.orderbook_address.to_string() + output_vaults[0].raindex(), + output_vault.raindex_address.to_string() ); } @@ -479,14 +489,14 @@ mod tests { let output_vault_id = U256::from_str("0x0b").unwrap(); let input_token = address!("0x00000000000000000000000000000000000000aa"); let output_token = address!("0x00000000000000000000000000000000000000bb"); - let orderbook_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); + let raindex_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); let input_vault = LocalDbVault { chain_id: 1, vault_id: input_vault_id, token: input_token, owner, - orderbook_address, + raindex_address, token_name: "Token A".to_string(), token_symbol: "TKNA".to_string(), token_decimals: 18, @@ -501,7 +511,7 @@ mod tests { vault_id: output_vault_id, token: output_token, owner, - orderbook_address, + raindex_address, token_name: "Token B".to_string(), token_symbol: "TKNB".to_string(), token_decimals: 6, @@ -518,7 +528,7 @@ mod tests { "vaultId": input_vault.vault_id, "token": input_vault.token, "owner": input_vault.owner, - "orderbookAddress": input_vault.orderbook_address, + "raindexAddress": input_vault.raindex_address, "tokenName": input_vault.token_name, "tokenSymbol": input_vault.token_symbol, "tokenDecimals": input_vault.token_decimals, @@ -535,7 +545,7 @@ mod tests { "vaultId": output_vault.vault_id, "token": output_vault.token, "owner": output_vault.owner, - "orderbookAddress": output_vault.orderbook_address, + "raindexAddress": output_vault.raindex_address, "tokenName": output_vault.token_name, "tokenSymbol": output_vault.token_symbol, "tokenDecimals": output_vault.token_decimals, @@ -551,7 +561,7 @@ mod tests { owner, block_timestamp: 123456, block_number: 654321, - orderbook_address, + raindex_address, order_bytes: order_bytes.clone(), transaction_hash: transaction_hash.clone(), inputs: Some(inputs_json.to_string()), @@ -571,7 +581,7 @@ mod tests { let order = client .get_order_by_hash( - &OrderbookIdentifier::new(42161, orderbook_address), + &RaindexIdentifier::new(42161, raindex_address), order_hash.clone(), ) .await @@ -587,7 +597,7 @@ mod tests { assert!(order.active()); assert_eq!(order.trades_count(), local_order.trade_count as u16); assert_eq!(order.meta(), Some(meta.to_string())); - assert_eq!(order.orderbook(), orderbook_address.to_string()); + assert_eq!(order.raindex(), raindex_address.to_string()); } #[wasm_bindgen_test] @@ -599,7 +609,7 @@ mod tests { b256!("0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); let order_bytes = bytes!("0x00000000000000000000000000000000000000000000000000000000000000ff"); - let orderbook_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); + let raindex_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); let local_order = LocalDbOrder { chain_id: 137, @@ -607,7 +617,7 @@ mod tests { owner, block_timestamp: 123456, block_number: 654321, - orderbook_address, + raindex_address, order_bytes: order_bytes.clone(), transaction_hash, inputs: None, @@ -627,7 +637,7 @@ mod tests { let orders = client .get_add_orders_for_transaction_wasm_binding( 137, - orderbook_address.to_string(), + raindex_address.to_string(), transaction_hash.to_string(), Some(1), Some(1), @@ -656,7 +666,7 @@ mod tests { b256!("0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"); let order_bytes = bytes!("0x00000000000000000000000000000000000000000000000000000000000000ee"); - let orderbook_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); + let raindex_address = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); let local_order = LocalDbOrder { chain_id: 137, @@ -664,7 +674,7 @@ mod tests { owner, block_timestamp: 789012, block_number: 210987, - orderbook_address, + raindex_address, order_bytes: order_bytes.clone(), transaction_hash, inputs: None, @@ -684,7 +694,7 @@ mod tests { let orders = client .get_remove_orders_for_transaction_wasm_binding( 137, - orderbook_address.to_string(), + raindex_address.to_string(), transaction_hash.to_string(), Some(1), Some(1), diff --git a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs index 60b8766117..c667705d94 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/bootstrap.rs @@ -4,7 +4,7 @@ use crate::local_db::{ fetch_target_watermark::{fetch_target_watermark_stmt, TargetWatermarkRow}, LocalDbQueryExecutor, }, - LocalDbError, OrderbookIdentifier, + LocalDbError, RaindexIdentifier, }; use alloy::primitives::Address; @@ -39,10 +39,11 @@ impl ClientBootstrapAdapter { async fn is_fresh_db( self, db: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result { - let rows: Vec = - db.query_json(&fetch_target_watermark_stmt(ob_id)).await?; + let rows: Vec = db + .query_json(&fetch_target_watermark_stmt(raindex_id)) + .await?; Ok(rows.is_empty()) } } @@ -55,10 +56,10 @@ impl BootstrapPipeline for ClientBootstrapAdapter { { let BootstrapState { last_synced_block, .. - } = self.inspect_state(db, &config.ob_id).await?; + } = self.inspect_state(db, &config.raindex_id).await?; if let Some(dump_stmt) = config.dump_stmt.as_ref() { - if self.is_fresh_db(db, &config.ob_id).await? { + if self.is_fresh_db(db, &config.raindex_id).await? { db.execute_batch(dump_stmt).await?; return Ok(()); } @@ -70,7 +71,7 @@ impl BootstrapPipeline for ClientBootstrapAdapter { ) { Ok(_) => {} Err(_) => { - self.clear_orderbook_data(db, &config.ob_id).await?; + self.clear_raindex_data(db, &config.raindex_id).await?; db.execute_batch(dump_stmt).await?; } } @@ -98,7 +99,7 @@ impl BootstrapPipeline for ClientBootstrapAdapter { has_required_tables, .. } = self - .inspect_state(db, &OrderbookIdentifier::new(0, Address::ZERO)) + .inspect_state(db, &RaindexIdentifier::new(0, Address::ZERO)) .await?; if !has_required_tables { @@ -124,7 +125,7 @@ mod tests { use std::sync::Mutex; use super::*; - use crate::local_db::query::clear_orderbook_data::clear_orderbook_data_batch; + use crate::local_db::query::clear_raindex_data::clear_raindex_data_batch; use crate::local_db::query::clear_tables::clear_tables_stmt; use crate::local_db::query::create_tables::create_tables_stmt; use crate::local_db::query::create_tables::REQUIRED_TABLES; @@ -141,7 +142,7 @@ mod tests { }; use alloy::primitives::{Address, Bytes}; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; + use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; use serde_json::json; use std::str::FromStr; @@ -223,20 +224,20 @@ mod tests { } } - fn sample_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier { + fn sample_ob_id() -> RaindexIdentifier { + RaindexIdentifier { chain_id: 1, - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, } } - fn runner_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(0, Address::ZERO) + fn runner_ob_id() -> RaindexIdentifier { + RaindexIdentifier::new(0, Address::ZERO) } fn cfg_with_dump(latest_block: u64) -> BootstrapConfig { BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![SqlStatement::new( "--dump-sql", )])), @@ -261,7 +262,7 @@ mod tests { fn watermark_row(last_block: u64) -> TargetWatermarkRow { TargetWatermarkRow { chain_id: sample_ob_id().chain_id, - orderbook_address: sample_ob_id().orderbook_address, + raindex_address: sample_ob_id().raindex_address, last_block, last_hash: Bytes::from_str("0xbeef").unwrap(), updated_at: 1, @@ -463,7 +464,7 @@ mod tests { let tables_json = required_tables_json(); let dump_stmt = SqlStatement::new("--dump-sql"); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: 100, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -472,7 +473,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) - .with_json(&fetch_target_watermark_stmt(&cfg.ob_id), json!([])) + .with_json(&fetch_target_watermark_stmt(&cfg.raindex_id), json!([])) .with_text(&dump_stmt, "ok"); adapter.engine_run(&db, &cfg).await.unwrap(); @@ -488,18 +489,18 @@ mod tests { let latest = last_synced + u64::from(TEST_BLOCK_NUMBER_THRESHOLD) + 1; let dump_stmt = SqlStatement::new("--dump-sql"); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: latest, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, deployment_block: 1, }; - let clear_batch = clear_orderbook_data_batch(&sample_ob_id()); + let clear_batch = clear_raindex_data_batch(&sample_ob_id()); let mut db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ) .with_text(&dump_stmt, "dumped"); @@ -531,7 +532,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); @@ -551,7 +552,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); @@ -567,7 +568,7 @@ mod tests { let last_synced = 200_000u64; let latest = last_synced + u64::from(TEST_BLOCK_NUMBER_THRESHOLD) + 5; let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: None, latest_block: latest, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -577,7 +578,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); @@ -594,7 +595,7 @@ mod tests { let latest = last_synced + u64::from(TEST_BLOCK_NUMBER_THRESHOLD) + 42; let dump_stmt = SqlStatement::new("--dump-sql"); let cfg = BootstrapConfig { - ob_id: sample_ob_id(), + raindex_id: sample_ob_id(), dump_stmt: Some(SqlStatementBatch::from(vec![dump_stmt.clone()])), latest_block: latest, block_number_threshold: TEST_BLOCK_NUMBER_THRESHOLD, @@ -604,7 +605,7 @@ mod tests { let db = MockDb::default() .with_json(&fetch_tables_stmt(), tables_json) .with_json( - &fetch_target_watermark_stmt(&cfg.ob_id), + &fetch_target_watermark_stmt(&cfg.raindex_id), json!([watermark_row(last_synced)]), ); diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs index 10893f7320..c752c5dcfa 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/config.rs @@ -2,8 +2,8 @@ use crate::local_db::pipeline::runner::utils::{ build_runner_targets, ParsedRunnerSettings, RunnerTarget, }; use crate::local_db::LocalDbError; -use rain_orderbook_app_settings::local_db_sync::LocalDbSyncCfg; -use rain_orderbook_app_settings::orderbook::OrderbookCfg; +use raindex_app_settings::local_db_sync::LocalDbSyncCfg; +use raindex_app_settings::raindex::RaindexCfg; use std::collections::HashMap; #[derive(Debug, Clone)] @@ -18,24 +18,24 @@ impl NetworkRunnerConfig { global: &ParsedRunnerSettings, network_key: &str, ) -> Result { - let filtered_orderbooks: HashMap = global - .orderbooks + let filtered_raindexes: HashMap = global + .raindexes .iter() - .filter(|(_, ob)| ob.network.key == network_key) + .filter(|(_, raindex_cfg)| raindex_cfg.network.key == network_key) .map(|(k, v)| (k.clone(), v.clone())) .collect(); - if filtered_orderbooks.is_empty() { + if filtered_raindexes.is_empty() { return Err(LocalDbError::CustomError(format!( - "no orderbooks found for network: {}", + "no raindexes found for network: {}", network_key ))); } - let chain_id = filtered_orderbooks + let chain_id = filtered_raindexes .values() .next() - .map(|ob| ob.network.chain_id) + .map(|raindex_cfg| raindex_cfg.network.chain_id) .ok_or_else(|| { LocalDbError::CustomError(format!( "could not determine chain_id for network: {}", @@ -54,14 +54,14 @@ impl NetworkRunnerConfig { network_key: network_key.to_string(), chain_id, settings: ParsedRunnerSettings { - orderbooks: filtered_orderbooks, + raindexes: filtered_raindexes, syncs: filtered_syncs, }, }) } pub fn build_targets(&self) -> Result, LocalDbError> { - build_runner_targets(&self.settings.orderbooks, &self.settings.syncs) + build_runner_targets(&self.settings.raindexes, &self.settings.syncs) } } @@ -69,7 +69,7 @@ impl NetworkRunnerConfig { mod tests { use super::*; use crate::local_db::pipeline::runner::utils::parse_runner_settings; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; fn sample_settings_yaml() -> String { format!( @@ -109,20 +109,20 @@ local-db-sync: finality-depth: 24 bootstrap-block-threshold: 5000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: network-a subgraph: network-a local-db-remote: remote-a deployment-block: 111 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: network-b subgraph: network-b local-db-remote: remote-b deployment-block: 222 - ob-c: + raindex-c: address: 0x00000000000000000000000000000000000000c3 network: network-a subgraph: network-a @@ -134,17 +134,17 @@ orderbooks: } #[test] - fn from_global_settings_filters_orderbooks_for_network() { + fn from_global_settings_filters_raindexes_for_network() { let global = parse_runner_settings(&sample_settings_yaml()).expect("valid yaml"); let config = NetworkRunnerConfig::from_global_settings(&global, "network-a").expect("config ok"); assert_eq!(config.network_key, "network-a"); assert_eq!(config.chain_id, 1); - assert_eq!(config.settings.orderbooks.len(), 2); - assert!(config.settings.orderbooks.contains_key("ob-a")); - assert!(config.settings.orderbooks.contains_key("ob-c")); - assert!(!config.settings.orderbooks.contains_key("ob-b")); + assert_eq!(config.settings.raindexes.len(), 2); + assert!(config.settings.raindexes.contains_key("raindex-a")); + assert!(config.settings.raindexes.contains_key("raindex-c")); + assert!(!config.settings.raindexes.contains_key("raindex-b")); } #[test] @@ -179,13 +179,13 @@ orderbooks: } #[test] - fn build_targets_single_orderbook_network() { + fn build_targets_single_raindex_network() { let global = parse_runner_settings(&sample_settings_yaml()).expect("valid yaml"); let config = NetworkRunnerConfig::from_global_settings(&global, "network-b").expect("config ok"); let targets = config.build_targets().expect("targets ok"); assert_eq!(targets.len(), 1); - assert_eq!(targets[0].orderbook_key, "ob-b"); + assert_eq!(targets[0].raindex_key, "raindex-b"); } } diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs index 0aac71a994..b90bb7c074 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/environment.rs @@ -32,7 +32,7 @@ pub fn default_environment() -> RunnerEnvironment< DefaultEventsPipeline::with_regular_rpcs(target.inputs.metadata_rpcs.clone())?; let tokens = DefaultTokensPipeline::new(target.inputs.metadata_rpcs.clone())?; - let status_bus = ClientStatusBus::with_ob_id(target.inputs.ob_id.clone()); + let status_bus = ClientStatusBus::with_ob_id(target.inputs.raindex_id.clone()); Ok(EnginePipelines::new( ClientBootstrapAdapter::new(), @@ -63,7 +63,7 @@ pub fn default_environment() -> RunnerEnvironment< DefaultEventsPipeline::with_regular_rpcs(target.inputs.metadata_rpcs.clone())?; let tokens = DefaultTokensPipeline::new(target.inputs.metadata_rpcs.clone())?; - let status_bus = TracingStatusBus::with_ob_id(target.inputs.ob_id.clone()); + let status_bus = TracingStatusBus::with_ob_id(target.inputs.raindex_id.clone()); Ok(EnginePipelines::new( ClientBootstrapAdapter::new(), @@ -83,7 +83,7 @@ mod tests { use crate::local_db::fetch::FetchConfig; use crate::local_db::pipeline::engine::SyncInputs; use crate::local_db::pipeline::{FinalityConfig, SyncConfig, WindowOverrides}; - use crate::local_db::{LocalDbError, OrderbookIdentifier}; + use crate::local_db::{LocalDbError, RaindexIdentifier}; use crate::rpc_client::RpcClientError; use alloy::primitives::address; use url::Url; @@ -91,13 +91,13 @@ mod tests { fn sample_target(metadata_rpcs: Vec) -> RunnerTarget { let fetch = FetchConfig::new(1, 1, 1, 1, 0, 0).expect("fetch config"); RunnerTarget { - orderbook_key: "test-ob".to_string(), + raindex_key: "test-raindex".to_string(), network_key: "test-network".to_string(), manifest_url: Url::parse("https://manifests.example/client.yaml").unwrap(), inputs: SyncInputs { - ob_id: OrderbookIdentifier { + raindex_id: RaindexIdentifier { chain_id: 1, - orderbook_address: address!("00000000000000000000000000000000000000c1"), + raindex_address: address!("00000000000000000000000000000000000000c1"), }, metadata_rpcs, cfg: SyncConfig { diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs index e64c3020dc..0a573d6908 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/mod.rs @@ -22,7 +22,7 @@ use crate::local_db::{ EventsPipeline, StatusBus, TokensPipeline, WindowPipeline, }, query::LocalDbQueryExecutor, - LocalDbError, OrderbookIdentifier, + LocalDbError, RaindexIdentifier, }; use crate::raindex_client::local_db::pipeline::bootstrap::ClientBootstrapAdapter; #[cfg(target_family = "wasm")] @@ -34,7 +34,7 @@ use config::NetworkRunnerConfig; use environment::default_environment; use futures::future::join_all; use leadership::{DefaultLeadership, Leadership, LeadershipGuard}; -use rain_orderbook_app_settings::remote::manifest::ManifestMap; +use raindex_app_settings::remote::manifest::ManifestMap; pub struct ClientRunner { network_key: Option, @@ -65,7 +65,7 @@ where leadership: L, ) -> Result { let settings = parse_runner_settings(&settings_yaml)?; - let base_targets = build_runner_targets(&settings.orderbooks, &settings.syncs)?; + let base_targets = build_runner_targets(&settings.raindexes, &settings.syncs)?; Ok(Self { network_key: None, @@ -124,7 +124,7 @@ where if !self.manifests_loaded { self.manifest_map = match self .environment - .fetch_manifests(&self.settings.orderbooks) + .fetch_manifests(&self.settings.raindexes) .await { Ok(map) => map, @@ -132,8 +132,8 @@ where return Ok(RunOutcome::Report(RunReport { successes: Vec::new(), failures: vec![TargetFailure { - ob_id: OrderbookIdentifier::new(0, Address::ZERO), - orderbook_key: None, + raindex_id: RaindexIdentifier::new(0, Address::ZERO), + raindex_key: None, stage: TargetStage::ManifestFetch, error, }], @@ -190,8 +190,8 @@ where Ok(target) } Err(error) => Err(TargetFailure { - ob_id: target.inputs.ob_id.clone(), - orderbook_key: Some(target.orderbook_key.clone()), + raindex_id: target.inputs.raindex_id.clone(), + raindex_key: Some(target.raindex_key.clone()), stage: TargetStage::DumpDownload, error, }), @@ -230,13 +230,13 @@ where let futures = targets.into_iter().map(move |target| { let environment = environment.clone(); async move { - let ob_id = target.inputs.ob_id.clone(); + let raindex_id = target.inputs.raindex_id.clone(); let engine = match environment.build_engine(&target) { Ok(engine) => engine.into_engine(), Err(error) => { return Err(TargetFailure { - ob_id, - orderbook_key: Some(target.orderbook_key.clone()), + raindex_id, + raindex_key: Some(target.raindex_key.clone()), stage: TargetStage::EngineBuild, error, }) @@ -246,8 +246,8 @@ where match engine.run(db, &target.inputs).await { Ok(outcome) => Ok(TargetSuccess { outcome }), Err(error) => Err(TargetFailure { - ob_id, - orderbook_key: Some(target.orderbook_key.clone()), + raindex_id, + raindex_key: Some(target.raindex_key.clone()), stage: TargetStage::EngineRun, error, }), @@ -331,16 +331,16 @@ mod tests { use crate::local_db::query::fetch_tables::{fetch_tables_stmt, TableResponse}; use crate::local_db::query::fetch_target_watermark::fetch_target_watermark_stmt; use crate::local_db::query::{FromDbJson, LocalDbQueryError, SqlStatement, SqlStatementBatch}; - use crate::local_db::{LocalDbError, OrderbookIdentifier}; + use crate::local_db::{LocalDbError, RaindexIdentifier}; use crate::rpc_client::LogEntryResponse; use alloy::primitives::{address, b256, Address, Bytes, B256}; use async_trait::async_trait; - use rain_orderbook_app_settings::local_db_manifest::{ - LocalDbManifest, ManifestNetwork, ManifestOrderbook, DB_SCHEMA_VERSION, MANIFEST_VERSION, + use raindex_app_settings::local_db_manifest::{ + LocalDbManifest, ManifestNetwork, ManifestRaindex, DB_SCHEMA_VERSION, MANIFEST_VERSION, }; - use rain_orderbook_app_settings::orderbook::OrderbookCfg; - use rain_orderbook_app_settings::remote::manifest::ManifestMap; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::raindex::RaindexCfg; + use raindex_app_settings::remote::manifest::ManifestMap; + use raindex_app_settings::spec_version::SpecVersion; use serde::Serialize; use serde_json::{json, Value}; use std::collections::{HashMap, VecDeque}; @@ -351,11 +351,11 @@ mod tests { const CHAIN_ID: u32 = 42161; const NETWORK_KEY: &str = "anvil"; - const ORDERBOOK_KEY_A: &str = "ob-a"; - const ORDERBOOK_KEY_B: &str = "ob-b"; + const RAINDEX_KEY_A: &str = "raindex-a"; + const RAINDEX_KEY_B: &str = "raindex-b"; - const ORDERBOOK_A: Address = address!("00000000000000000000000000000000000000a1"); - const ORDERBOOK_B: Address = address!("00000000000000000000000000000000000000b2"); + const RAINDEX_A: Address = address!("00000000000000000000000000000000000000a1"); + const RAINDEX_B: Address = address!("00000000000000000000000000000000000000b2"); #[derive(Clone, Default)] struct AlwaysLeadership; @@ -440,7 +440,7 @@ mod tests { #[derive(Clone, Debug)] struct BootstrapRecord { - orderbook_key: String, + raindex_key: String, dump_sql: Option, latest_block: u64, } @@ -473,11 +473,11 @@ mod tests { self.dump_requests.lock().unwrap().clone() } - fn record_engine_run(&self, orderbook_key: &str) { + fn record_engine_run(&self, raindex_key: &str) { self.engine_runs .lock() .unwrap() - .push(orderbook_key.to_string()); + .push(raindex_key.to_string()); } fn engine_runs(&self) -> Vec { @@ -486,7 +486,7 @@ mod tests { fn record_bootstrap( &self, - orderbook_key: String, + raindex_key: String, dump_sql: Option, latest_block: u64, ) { @@ -494,7 +494,7 @@ mod tests { .lock() .unwrap() .push(BootstrapRecord { - orderbook_key, + raindex_key, dump_sql, latest_block, }); @@ -504,11 +504,11 @@ mod tests { self.bootstrap_records.lock().unwrap().clone() } - fn record_status(&self, orderbook_key: &str, message: &str) { + fn record_status(&self, raindex_key: &str, message: &str) { self.status_messages .lock() .unwrap() - .push((orderbook_key.to_string(), message.to_string())); + .push((raindex_key.to_string(), message.to_string())); } fn record_persist(&self) { @@ -635,14 +635,14 @@ mod tests { #[derive(Clone)] struct StubBootstrap { telemetry: Telemetry, - orderbook_key: String, + raindex_key: String, } impl StubBootstrap { - fn new(telemetry: Telemetry, orderbook_key: String) -> Self { + fn new(telemetry: Telemetry, raindex_key: String) -> Self { Self { telemetry, - orderbook_key, + raindex_key, } } } @@ -663,7 +663,7 @@ mod tests { async fn inspect_state( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _ob_id: &RaindexIdentifier, ) -> Result where DB: LocalDbQueryExecutor + ?Sized, @@ -685,10 +685,10 @@ mod tests { Ok(()) } - async fn clear_orderbook_data( + async fn clear_raindex_data( &self, _db: &DB, - _target: &OrderbookIdentifier, + _target: &RaindexIdentifier, ) -> Result<(), LocalDbError> where DB: LocalDbQueryExecutor + ?Sized, @@ -706,7 +706,7 @@ mod tests { { let dump_sql = config.dump_stmt.as_ref().map(dump_sql); self.telemetry.record_bootstrap( - self.orderbook_key.clone(), + self.raindex_key.clone(), dump_sql, config.latest_block, ); @@ -745,7 +745,7 @@ mod tests { async fn compute( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _ob_id: &RaindexIdentifier, _cfg: &SyncConfig, _latest_block: u64, ) -> Result<(u64, u64), LocalDbError> @@ -779,9 +779,9 @@ mod tests { )) } - async fn fetch_orderbook( + async fn fetch_raindex( &self, - _orderbook_address: Address, + _raindex_address: Address, _from_block: u64, _to_block: u64, _cfg: &FetchConfig, @@ -815,7 +815,7 @@ mod tests { async fn load_existing( &self, _db: &DB, - _ob_id: &OrderbookIdentifier, + _ob_id: &RaindexIdentifier, _token_addrs_lower: &[Address], ) -> Result< Vec, @@ -839,15 +839,15 @@ mod tests { #[derive(Clone)] struct StubApply { telemetry: Telemetry, - orderbook_key: String, + raindex_key: String, fail: bool, } impl StubApply { - fn new(telemetry: Telemetry, orderbook_key: String, fail: bool) -> Self { + fn new(telemetry: Telemetry, raindex_key: String, fail: bool) -> Self { Self { telemetry, - orderbook_key, + raindex_key, fail, } } @@ -865,10 +865,7 @@ mod tests { ) -> Result { let mut batch = SqlStatementBatch::new(); batch.add(SqlStatement::new("BEGIN TRANSACTION")); - batch.add(SqlStatement::new(format!( - "-- apply {}", - self.orderbook_key - ))); + batch.add(SqlStatement::new(format!("-- apply {}", self.raindex_key))); batch.add(SqlStatement::new("COMMIT")); Ok(batch) } @@ -877,11 +874,11 @@ mod tests { where DB: LocalDbQueryExecutor + ?Sized, { - self.telemetry.record_engine_run(&self.orderbook_key); + self.telemetry.record_engine_run(&self.raindex_key); if self.fail { return Err(LocalDbError::CustomError(format!( "apply failed {}", - self.orderbook_key + self.raindex_key ))); } db.execute_batch(batch).await?; @@ -893,14 +890,14 @@ mod tests { #[derive(Clone)] struct StubStatusBus { telemetry: Telemetry, - orderbook_key: String, + raindex_key: String, } impl StubStatusBus { - fn new(telemetry: Telemetry, orderbook_key: String) -> Self { + fn new(telemetry: Telemetry, raindex_key: String) -> Self { Self { telemetry, - orderbook_key, + raindex_key, } } } @@ -909,7 +906,7 @@ mod tests { impl StatusBus for StubStatusBus { async fn send(&self, phase: SyncPhase) -> Result<(), LocalDbError> { self.telemetry - .record_status(&self.orderbook_key, phase.to_message()); + .record_status(&self.raindex_key, phase.to_message()); Ok(()) } } @@ -952,19 +949,19 @@ mod tests { const END_HASH_B: &str = "0x000000000000000000000000000000000000000000000000000000000000beef"; fn dump_url_a() -> Url { - Url::parse("https://dumps.example/ob-a.sql").unwrap() + Url::parse("https://dumps.example/raindex-a.sql").unwrap() } fn dump_url_b() -> Url { - Url::parse("https://dumps.example/ob-b.sql").unwrap() + Url::parse("https://dumps.example/raindex-b.sql").unwrap() } fn manifest_for_a() -> ManifestMap { - make_manifest(remote_url_a(), ORDERBOOK_A, dump_url_a(), 111, END_HASH_A) + make_manifest(remote_url_a(), RAINDEX_A, dump_url_a(), 111, END_HASH_A) } fn manifest_for_b() -> ManifestMap { - make_manifest(remote_url_b(), ORDERBOOK_B, dump_url_b(), 222, END_HASH_B) + make_manifest(remote_url_b(), RAINDEX_B, dump_url_b(), 222, END_HASH_B) } fn manifest_for_both() -> ManifestMap { @@ -975,7 +972,7 @@ mod tests { fn make_manifest( remote: Url, - orderbook_address: Address, + raindex_address: Address, dump_url: Url, end_block: u64, end_hash: &str, @@ -988,8 +985,8 @@ mod tests { NETWORK_KEY.to_string(), ManifestNetwork { chain_id: CHAIN_ID, - orderbooks: vec![ManifestOrderbook { - address: orderbook_address, + raindexes: vec![ManifestRaindex { + address: raindex_address, dump_url, end_block, end_block_hash: Bytes::copy_from_slice(end_block_hash.as_slice()), @@ -1001,7 +998,7 @@ mod tests { HashMap::from([(remote, manifest)]) } - fn two_orderbooks_settings_yaml() -> String { + fn two_raindexes_settings_yaml() -> String { format!( r#" version: {version} @@ -1025,14 +1022,14 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil local-db-remote: remote-a deployment-block: 123 - ob-b: + raindex-b: address: 0x00000000000000000000000000000000000000b2 network: anvil subgraph: anvil @@ -1043,7 +1040,7 @@ orderbooks: ) } - fn single_orderbook_settings_yaml() -> String { + fn single_raindex_settings_yaml() -> String { format!( r#" version: {version} @@ -1066,8 +1063,8 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 10000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil @@ -1095,7 +1092,7 @@ orderbooks: }; db.set_json_value(&fetch_db_metadata_stmt(), &[metadata_row]); db.set_json_raw( - &fetch_target_watermark_stmt(&OrderbookIdentifier::new(0, Address::ZERO)), + &fetch_target_watermark_stmt(&RaindexIdentifier::new(0, Address::ZERO)), json!([]), ); } @@ -1104,10 +1101,13 @@ orderbooks: prepare_db_baseline(db); for target in targets { db.set_json_raw( - &fetch_target_watermark_stmt(&target.inputs.ob_id), + &fetch_target_watermark_stmt(&target.inputs.raindex_id), + json!([]), + ); + db.set_json_raw( + &fetch_store_addresses_stmt(&target.inputs.raindex_id), json!([]), ); - db.set_json_raw(&fetch_store_addresses_stmt(&target.inputs.ob_id), json!([])); } } @@ -1118,17 +1118,17 @@ orderbooks: let behaviors = Arc::new(behaviors); Arc::new(move |target: &RunnerTarget| { let behavior = behaviors - .get(&target.orderbook_key) + .get(&target.raindex_key) .copied() .unwrap_or(EngineBehavior::Success); let telemetry = telemetry.clone(); telemetry.record_builder_init(); let fail_apply = behavior == EngineBehavior::ApplyFail; - let bootstrap = StubBootstrap::new(telemetry.clone(), target.orderbook_key.clone()); + let bootstrap = StubBootstrap::new(telemetry.clone(), target.raindex_key.clone()); let window = StubWindow::new(0, target.inputs.cfg.deployment_block); let events = StubEvents::new(target.inputs.cfg.deployment_block); - let apply = StubApply::new(telemetry.clone(), target.orderbook_key.clone(), fail_apply); - let status = StubStatusBus::new(telemetry.clone(), target.orderbook_key.clone()); + let apply = StubApply::new(telemetry.clone(), target.raindex_key.clone(), fail_apply); + let status = StubStatusBus::new(telemetry.clone(), target.raindex_key.clone()); Ok(EnginePipelines::new( bootstrap, window, events, StubTokens, apply, status, )) @@ -1147,7 +1147,7 @@ orderbooks: let manifest_fetcher = { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); Box::pin(async move { @@ -1198,9 +1198,12 @@ orderbooks: .collect() } - fn expect_orderbooks(report: &RunReport, expected: &[Address]) { + fn expect_raindexes(report: &RunReport, expected: &[Address]) { let outcomes = extract_outcomes(report); - let mut addrs: Vec
= outcomes.iter().map(|o| o.ob_id.orderbook_address).collect(); + let mut addrs: Vec
= outcomes + .iter() + .map(|o| o.raindex_id.raindex_address) + .collect(); addrs.sort(); let mut expected_sorted = expected.to_vec(); expected_sorted.sort(); @@ -1229,7 +1232,7 @@ orderbooks: #[test] fn default_environment_builds_engine_for_target() { - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let runner = ClientRunner::new(settings).expect("runner builds with default env"); assert_eq!(runner.base_targets.len(), 1); @@ -1247,7 +1250,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1257,7 +1260,7 @@ orderbooks: let report = unwrap_report(outcome); let outcomes = extract_outcomes(&report); assert_eq!(outcomes.len(), 2); - expect_orderbooks(&report, &[ORDERBOOK_A, ORDERBOOK_B]); + expect_raindexes(&report, &[RAINDEX_A, RAINDEX_B]); assert!(runner.manifests_loaded); assert!(runner.has_provisioned_dumps); assert_eq!(telemetry.manifest_fetch_count(), 1); @@ -1273,10 +1276,10 @@ orderbooks: .is_some_and(|sql| sql.starts_with("-- dump for ")))); let latest_blocks: HashMap = records .iter() - .map(|record| (record.orderbook_key.clone(), record.latest_block)) + .map(|record| (record.raindex_key.clone(), record.latest_block)) .collect(); - assert_eq!(latest_blocks.get(ORDERBOOK_KEY_A), Some(&111)); - assert_eq!(latest_blocks.get(ORDERBOOK_KEY_B), Some(&222)); + assert_eq!(latest_blocks.get(RAINDEX_KEY_A), Some(&111)); + assert_eq!(latest_blocks.get(RAINDEX_KEY_B), Some(&222)); assert_eq!(db.batch_calls().len(), 2); } @@ -1285,7 +1288,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1310,7 +1313,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = CountingLeadership::new(); let mut runner = ClientRunner::with_environment(settings, environment, leadership.clone()).unwrap(); @@ -1335,7 +1338,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = SequenceLeadership::new(vec![LeadershipAction::Skip]); let mut runner = ClientRunner::with_environment(settings, environment, leadership).unwrap(); @@ -1356,7 +1359,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = SequenceLeadership::new(vec![LeadershipAction::Skip, LeadershipAction::Grant]); let mut runner = ClientRunner::with_environment(settings, environment, leadership).unwrap(); @@ -1385,7 +1388,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(manifest_for_both(), HashMap::new(), 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let leadership = SequenceLeadership::new(vec![LeadershipAction::Fail("no leadership".into())]); let mut runner = ClientRunner::with_environment(settings, environment, leadership).unwrap(); @@ -1406,12 +1409,12 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment( manifest_for_a(), - HashMap::from([(ORDERBOOK_KEY_B.to_string(), EngineBehavior::Success)]), + HashMap::from([(RAINDEX_KEY_B.to_string(), EngineBehavior::Success)]), 1, 1, telemetry.clone(), ); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1427,8 +1430,8 @@ orderbooks: let records = telemetry.bootstrap_records(); let record_a = records .iter() - .find(|r| r.orderbook_key == ORDERBOOK_KEY_A) - .expect("record for ob-a"); + .find(|r| r.raindex_key == RAINDEX_KEY_A) + .expect("record for raindex-a"); assert!(record_a .dump_sql .as_ref() @@ -1437,8 +1440,8 @@ orderbooks: let record_b = records .iter() - .find(|r| r.orderbook_key == ORDERBOOK_KEY_B) - .expect("record for ob-b"); + .find(|r| r.raindex_key == RAINDEX_KEY_B) + .expect("record for raindex-b"); assert!(record_b.dump_sql.is_none()); assert_eq!(record_b.latest_block, 0); } @@ -1448,7 +1451,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(ManifestMap::new(), HashMap::new(), 1, 0, telemetry.clone()); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); runner.base_targets.clear(); @@ -1473,7 +1476,7 @@ orderbooks: let manifest_fetcher = { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); Box::pin(async move { @@ -1497,7 +1500,7 @@ orderbooks: }; let engine_builder = engine_builder_for_behaviors(telemetry.clone(), HashMap::new()); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1523,7 +1526,7 @@ orderbooks: let telemetry = Telemetry::default(); let manifest_fetcher = { let telemetry = telemetry.clone(); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); Box::pin(async move { telemetry.record_manifest_fetch(); @@ -1542,7 +1545,7 @@ orderbooks: let engine_builder = engine_builder_for_behaviors(telemetry.clone(), HashMap::new()); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1575,7 +1578,7 @@ orderbooks: let manifest_fetcher = { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); Box::pin(async move { @@ -1602,7 +1605,7 @@ orderbooks: let engine_builder = engine_builder_for_behaviors(telemetry.clone(), behaviors); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1627,7 +1630,7 @@ orderbooks: let manifest_fetcher = { let telemetry = telemetry.clone(); let manifest_arc = Arc::new(manifest); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); Box::pin(async move { @@ -1651,7 +1654,7 @@ orderbooks: let engine_builder = engine_builder_for_behaviors(telemetry.clone(), HashMap::new()); let environment = RunnerEnvironment::new(manifest_fetcher, dump_downloader, engine_builder); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1667,11 +1670,11 @@ orderbooks: .failures .iter() .any(|failure| failure.stage == TargetStage::DumpDownload - && failure.ob_id.orderbook_address == ORDERBOOK_A)); + && failure.raindex_id.raindex_address == RAINDEX_A)); assert!(report .successes .iter() - .any(|success| success.outcome.ob_id.orderbook_address == ORDERBOOK_B)); + .any(|success| success.outcome.raindex_id.raindex_address == RAINDEX_B)); assert!(!runner.has_provisioned_dumps); } @@ -1679,14 +1682,14 @@ orderbooks: async fn engine_builder_error_is_propagated() { let telemetry = Telemetry::default(); let manifest = manifest_for_both(); - let settings = two_orderbooks_settings_yaml(); - let behaviors = HashMap::from([(ORDERBOOK_KEY_B.to_string(), EngineBehavior::Success)]); + let settings = two_raindexes_settings_yaml(); + let behaviors = HashMap::from([(RAINDEX_KEY_B.to_string(), EngineBehavior::Success)]); let manifest_arc = Arc::new(manifest); let manifest_fetcher = { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); Box::pin(async move { @@ -1717,25 +1720,25 @@ orderbooks: let telemetry = telemetry.clone(); let behaviors = Arc::new(behaviors); Arc::new(move |target: &RunnerTarget| { - if target.orderbook_key == ORDERBOOK_KEY_A { + if target.raindex_key == RAINDEX_KEY_A { return Err(LocalDbError::CustomError("builder failed".into())); } let behaviors = Arc::clone(&behaviors); let telemetry = telemetry.clone(); let behavior = behaviors - .get(&target.orderbook_key) + .get(&target.raindex_key) .copied() .unwrap_or(EngineBehavior::Success); telemetry.record_builder_init(); - let bootstrap = StubBootstrap::new(telemetry.clone(), target.orderbook_key.clone()); + let bootstrap = StubBootstrap::new(telemetry.clone(), target.raindex_key.clone()); let window = StubWindow::new(0, target.inputs.cfg.deployment_block); let events = StubEvents::new(target.inputs.cfg.deployment_block); let apply = StubApply::new( telemetry.clone(), - target.orderbook_key.clone(), + target.raindex_key.clone(), behavior == EngineBehavior::ApplyFail, ); - let status = StubStatusBus::new(telemetry.clone(), target.orderbook_key.clone()); + let status = StubStatusBus::new(telemetry.clone(), target.raindex_key.clone()); Ok(EnginePipelines::new( bootstrap, window, events, StubTokens, apply, status, )) @@ -1760,7 +1763,7 @@ orderbooks: assert_eq!(telemetry.dump_requests().len(), 2); let engine_runs = telemetry.engine_runs(); assert!( - engine_runs.iter().all(|key| key != ORDERBOOK_KEY_A), + engine_runs.iter().all(|key| key != RAINDEX_KEY_A), "engine should not run for target with builder failure" ); } @@ -1769,11 +1772,11 @@ orderbooks: async fn engine_run_failure_is_propagated() { let telemetry = Telemetry::default(); let mut behaviors = HashMap::new(); - behaviors.insert(ORDERBOOK_KEY_A.to_string(), EngineBehavior::ApplyFail); - behaviors.insert(ORDERBOOK_KEY_B.to_string(), EngineBehavior::Success); + behaviors.insert(RAINDEX_KEY_A.to_string(), EngineBehavior::ApplyFail); + behaviors.insert(RAINDEX_KEY_B.to_string(), EngineBehavior::Success); let environment = build_environment(manifest_for_both(), behaviors, 1, 2, telemetry.clone()); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); let db = RecordingDb::default(); @@ -1793,20 +1796,20 @@ orderbooks: assert!(telemetry .engine_runs() .iter() - .any(|key| key == ORDERBOOK_KEY_A)); + .any(|key| key == RAINDEX_KEY_A)); } #[tokio::test] async fn engine_build_and_run_failures_are_both_reported() { let telemetry = Telemetry::default(); let manifest = manifest_for_both(); - let settings = two_orderbooks_settings_yaml(); + let settings = two_raindexes_settings_yaml(); let manifest_arc = Arc::new(manifest); let manifest_fetcher = { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); - Arc::new(move |_orderbooks: &HashMap| { + Arc::new(move |_raindexes: &HashMap| { let telemetry = telemetry.clone(); let manifest_arc = Arc::clone(&manifest_arc); Box::pin(async move { @@ -1820,15 +1823,15 @@ orderbooks: let engine_builder: TestEngineBuilder = { let telemetry = telemetry.clone(); Arc::new(move |target: &RunnerTarget| { - if target.orderbook_key == ORDERBOOK_KEY_A { + if target.raindex_key == RAINDEX_KEY_A { return Err(LocalDbError::CustomError("build boom".into())); } telemetry.record_builder_init(); - let bootstrap = StubBootstrap::new(telemetry.clone(), target.orderbook_key.clone()); + let bootstrap = StubBootstrap::new(telemetry.clone(), target.raindex_key.clone()); let window = StubWindow::new(0, target.inputs.cfg.deployment_block); let events = StubEvents::new(target.inputs.cfg.deployment_block); - let apply = StubApply::new(telemetry.clone(), target.orderbook_key.clone(), true); // force engine run failure - let status = StubStatusBus::new(telemetry.clone(), target.orderbook_key.clone()); + let apply = StubApply::new(telemetry.clone(), target.raindex_key.clone(), true); // force engine run failure + let status = StubStatusBus::new(telemetry.clone(), target.raindex_key.clone()); Ok(EnginePipelines::new( bootstrap, window, events, StubTokens, apply, status, )) @@ -1849,11 +1852,11 @@ orderbooks: assert!(report .failures .iter() - .any(|f| f.ob_id.orderbook_address == ORDERBOOK_A)); + .any(|f| f.raindex_id.raindex_address == RAINDEX_A)); assert!(report .failures .iter() - .any(|f| f.ob_id.orderbook_address == ORDERBOOK_B)); + .any(|f| f.raindex_id.raindex_address == RAINDEX_B)); } #[tokio::test] @@ -1861,7 +1864,7 @@ orderbooks: let telemetry = Telemetry::default(); let environment = build_environment(ManifestMap::new(), HashMap::new(), 1, 0, telemetry.clone()); - let settings = single_orderbook_settings_yaml(); + let settings = single_raindex_settings_yaml(); let mut runner = ClientRunner::with_environment(settings, environment, AlwaysLeadership).unwrap(); @@ -1878,7 +1881,7 @@ orderbooks: let records = telemetry.bootstrap_records(); assert_eq!(records.len(), 1); let record = &records[0]; - assert_eq!(record.orderbook_key, ORDERBOOK_KEY_A); + assert_eq!(record.raindex_key, RAINDEX_KEY_A); assert_eq!(record.dump_sql.as_deref(), Some("-- preloaded dump")); assert_eq!(record.latest_block, 0); } diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs index f21541036b..b51c3f38a1 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/native.rs @@ -14,8 +14,8 @@ use crate::local_db::LocalDbError; use crate::raindex_client::local_db::pipeline::bootstrap::ClientBootstrapAdapter; use crate::raindex_client::local_db::pipeline::status::TracingStatusBus; use crate::raindex_client::local_db::{LocalDb, SyncReadiness}; -use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; -use rain_orderbook_app_settings::network::NetworkCfg; +use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; +use raindex_app_settings::network::NetworkCfg; use std::collections::HashMap; use std::future::Future; use std::path::PathBuf; @@ -82,10 +82,10 @@ pub fn start( sync_readiness: SyncReadiness, ) -> Result { let mut networks_map: HashMap = HashMap::new(); - for ob in settings.orderbooks.values() { + for raindex_cfg in settings.raindexes.values() { networks_map - .entry(ob.network.key.clone()) - .or_insert_with(|| (*ob.network).clone()); + .entry(raindex_cfg.network.key.clone()) + .or_insert_with(|| (*raindex_cfg.network).clone()); } let mut networks: Vec = networks_map.into_values().collect(); networks.sort_by(|a, b| a.key.cmp(&b.key)); @@ -234,7 +234,7 @@ async fn run_network_loop( tracing::warn!( network = %network_key, chain_id, - ob = %format!("{:#x}", failure.ob_id.orderbook_address), + raindex = %format!("{:#x}", failure.raindex_id.raindex_address), stage = ?failure.stage, error = %failure.error, "sync target failed" @@ -275,7 +275,7 @@ mod tests { use super::*; use crate::local_db::pipeline::runner::{RunReport, TargetFailure, TargetStage}; use crate::local_db::query::{FromDbJson, LocalDbQueryError, SqlStatement, SqlStatementBatch}; - use crate::local_db::OrderbookIdentifier; + use crate::local_db::RaindexIdentifier; use alloy::primitives::Address; use std::collections::VecDeque; use std::sync::atomic::AtomicUsize; @@ -344,8 +344,8 @@ mod tests { if should_fail { failures.fetch_add(1, Ordering::SeqCst); let failure = TargetFailure { - ob_id: OrderbookIdentifier::new(1, Address::ZERO), - orderbook_key: None, + raindex_id: RaindexIdentifier::new(1, Address::ZERO), + raindex_key: None, stage: TargetStage::EngineRun, error: LocalDbError::CustomError("runner failure".to_string()), }; @@ -386,7 +386,7 @@ mod tests { #[test] fn start_returns_error_for_empty_settings() { let settings = ParsedRunnerSettings { - orderbooks: HashMap::new(), + raindexes: HashMap::new(), syncs: HashMap::new(), }; let result = start( diff --git a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs index a1f3f35535..ce791c3ce4 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/runner/scheduler/wasm.rs @@ -17,8 +17,8 @@ use crate::raindex_client::local_db::pipeline::status::{ use crate::raindex_client::local_db::{LocalDb, NetworkSyncStatus, SchedulerState, SyncReadiness}; use gloo_timers::future::TimeoutFuture; use js_sys::Function; -use rain_orderbook_app_settings::local_db_manifest::DB_SCHEMA_VERSION; -use rain_orderbook_app_settings::network::NetworkCfg; +use raindex_app_settings::local_db_manifest::DB_SCHEMA_VERSION; +use raindex_app_settings::network::NetworkCfg; use std::cell::Cell; use std::collections::HashMap; use std::future::Future; @@ -86,10 +86,10 @@ pub(crate) fn start( sync_readiness: SyncReadiness, ) -> Result { let mut networks_map: HashMap = HashMap::new(); - for ob in settings.orderbooks.values() { + for raindex_cfg in settings.raindexes.values() { networks_map - .entry(ob.network.key.clone()) - .or_insert_with(|| (*ob.network).clone()); + .entry(raindex_cfg.network.key.clone()) + .or_insert_with(|| (*raindex_cfg.network).clone()); } let mut networks: Vec = networks_map.into_values().collect(); networks.sort_by(|a, b| a.key.cmp(&b.key)); @@ -244,8 +244,8 @@ async fn run_network_loop( } else { let first = &report.failures[0]; let msg = format!( - "ob {:#x} failed at {:?}: {}", - first.ob_id.orderbook_address, + "raindex {:#x} failed at {:?}: {}", + first.raindex_id.raindex_address, first.stage, first.error.to_readable_msg() ); @@ -294,7 +294,7 @@ mod wasm_tests { use super::*; use crate::local_db::pipeline::runner::utils::parse_runner_settings; use crate::local_db::pipeline::runner::{RunReport, TargetFailure, TargetStage}; - use crate::local_db::OrderbookIdentifier; + use crate::local_db::RaindexIdentifier; use crate::raindex_client::local_db::pipeline::status::get_scheduler_state; use crate::raindex_client::local_db::LocalDbStatus; use alloy::primitives::Address; @@ -360,8 +360,8 @@ mod wasm_tests { if should_fail { failures.set(failures.get() + 1); let failure = TargetFailure { - ob_id: OrderbookIdentifier::new(1, Address::ZERO), - orderbook_key: None, + raindex_id: RaindexIdentifier::new(1, Address::ZERO), + raindex_key: None, stage: TargetStage::EngineRun, error: LocalDbError::CustomError("runner failure".to_string()), }; diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs b/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs index 6935b367af..51f36e0768 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/mod.rs @@ -11,12 +11,12 @@ pub use wasm::*; #[cfg(test)] mod tests { use crate::local_db::pipeline::SyncPhase; - use crate::local_db::OrderbookIdentifier; - use crate::raindex_client::local_db::{LocalDbStatus, OrderbookSyncStatus, SchedulerState}; + use crate::local_db::RaindexIdentifier; + use crate::raindex_client::local_db::{LocalDbStatus, RaindexSyncStatus, SchedulerState}; use alloy::primitives::address; - fn test_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(1, address!("0000000000000000000000000000000000001234")) + fn test_raindex_id() -> RaindexIdentifier { + RaindexIdentifier::new(1, address!("0000000000000000000000000000000000001234")) } #[test] @@ -34,12 +34,12 @@ mod tests { "Computing sync window" ); assert_eq!( - SyncPhase::FetchingOrderbookLogs.to_message(), - "Fetching orderbook logs" + SyncPhase::FetchingRaindexLogs.to_message(), + "Fetching raindex logs" ); assert_eq!( - SyncPhase::DecodingOrderbookLogs.to_message(), - "Decoding orderbook logs" + SyncPhase::DecodingRaindexLogs.to_message(), + "Decoding raindex logs" ); assert_eq!( SyncPhase::FetchingStoreLogs.to_message(), @@ -69,11 +69,11 @@ mod tests { } #[test] - fn orderbook_sync_status_syncing_sets_correct_fields() { - let ob_id = test_ob_id(); - let status = OrderbookSyncStatus::syncing(ob_id.clone(), SyncPhase::FetchingLatestBlock); + fn raindex_sync_status_syncing_sets_correct_fields() { + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::syncing(raindex_id.clone(), SyncPhase::FetchingLatestBlock); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Syncing); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert_eq!( @@ -84,11 +84,11 @@ mod tests { } #[test] - fn orderbook_sync_status_active_with_leader_sets_correct_fields() { - let ob_id = test_ob_id(); - let status = OrderbookSyncStatus::active(ob_id.clone(), SchedulerState::Leader); + fn raindex_sync_status_active_with_leader_sets_correct_fields() { + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::active(raindex_id.clone(), SchedulerState::Leader); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Active); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert!(status.phase_message.is_none()); @@ -96,11 +96,11 @@ mod tests { } #[test] - fn orderbook_sync_status_active_with_not_leader_sets_correct_fields() { - let ob_id = test_ob_id(); - let status = OrderbookSyncStatus::active(ob_id.clone(), SchedulerState::NotLeader); + fn raindex_sync_status_active_with_not_leader_sets_correct_fields() { + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::active(raindex_id.clone(), SchedulerState::NotLeader); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Active); assert_eq!(status.scheduler_state, SchedulerState::NotLeader); assert!(status.phase_message.is_none()); @@ -108,12 +108,12 @@ mod tests { } #[test] - fn orderbook_sync_status_failure_sets_correct_fields() { - let ob_id = test_ob_id(); + fn raindex_sync_status_failure_sets_correct_fields() { + let raindex_id = test_raindex_id(); let error_msg = "RPC connection failed".to_string(); - let status = OrderbookSyncStatus::failure(ob_id.clone(), error_msg.clone()); + let status = RaindexSyncStatus::failure(raindex_id.clone(), error_msg.clone()); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Failure); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert!(status.phase_message.is_none()); @@ -121,17 +121,17 @@ mod tests { } #[test] - fn orderbook_sync_status_new_with_all_fields() { - let ob_id = test_ob_id(); - let status = OrderbookSyncStatus::new( - ob_id.clone(), + fn raindex_sync_status_new_with_all_fields() { + let raindex_id = test_raindex_id(); + let status = RaindexSyncStatus::new( + raindex_id.clone(), LocalDbStatus::Syncing, SchedulerState::Leader, Some("Custom phase".to_string()), Some("Custom error".to_string()), ); - assert_eq!(status.ob_id, ob_id); + assert_eq!(status.raindex_id, raindex_id); assert_eq!(status.status, LocalDbStatus::Syncing); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert_eq!(status.phase_message, Some("Custom phase".to_string())); diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/native.rs b/crates/common/src/raindex_client/local_db/pipeline/status/native.rs index 78d4a8a4a6..5ffbcd8cc4 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/native.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/native.rs @@ -1,31 +1,31 @@ use crate::local_db::pipeline::{StatusBus, SyncPhase}; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; #[derive(Debug, Clone, Default)] pub struct TracingStatusBus { - ob_id: Option, - orderbook_key: Option, + raindex_id: Option, + raindex_key: Option, } impl TracingStatusBus { pub fn new() -> Self { Self { - ob_id: None, - orderbook_key: None, + raindex_id: None, + raindex_key: None, } } - pub fn with_ob_id(ob_id: OrderbookIdentifier) -> Self { + pub fn with_ob_id(raindex_id: RaindexIdentifier) -> Self { Self { - ob_id: Some(ob_id), - orderbook_key: None, + raindex_id: Some(raindex_id), + raindex_key: None, } } - pub fn with_ob_id_and_key(ob_id: OrderbookIdentifier, key: String) -> Self { + pub fn with_ob_id_and_key(raindex_id: RaindexIdentifier, key: String) -> Self { Self { - ob_id: Some(ob_id), - orderbook_key: Some(key), + raindex_id: Some(raindex_id), + raindex_key: Some(key), } } } @@ -33,17 +33,17 @@ impl TracingStatusBus { #[async_trait::async_trait(?Send)] impl StatusBus for TracingStatusBus { async fn send(&self, phase: SyncPhase) -> Result<(), LocalDbError> { - let chain_id = self.ob_id.as_ref().map(|id| id.chain_id).unwrap_or(0); + let chain_id = self.raindex_id.as_ref().map(|id| id.chain_id).unwrap_or(0); let ob_addr = self - .ob_id + .raindex_id .as_ref() - .map(|id| format!("{:#x}", id.orderbook_address)) + .map(|id| format!("{:#x}", id.raindex_address)) .unwrap_or_default(); - let key = self.orderbook_key.as_deref().unwrap_or("unknown"); + let key = self.raindex_key.as_deref().unwrap_or("unknown"); tracing::debug!( chain_id = chain_id, - orderbook = %ob_addr, + raindex = %ob_addr, key = key, phase = %phase.to_message(), "sync phase" @@ -57,17 +57,17 @@ impl StatusBus for TracingStatusBus { mod tests { use super::*; use crate::local_db::pipeline::SyncPhase; - use crate::local_db::OrderbookIdentifier; + use crate::local_db::RaindexIdentifier; use alloy::primitives::address; - fn test_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(1, address!("0000000000000000000000000000000000001234")) + fn test_ob_id() -> RaindexIdentifier { + RaindexIdentifier::new(1, address!("0000000000000000000000000000000000001234")) } #[tokio::test] async fn tracing_status_bus_send_returns_ok() { - let ob_id = test_ob_id(); - let bus = TracingStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = TracingStatusBus::with_ob_id(raindex_id); let result = bus.send(SyncPhase::FetchingLatestBlock).await; assert!(result.is_ok()); } diff --git a/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs b/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs index f9f5868e02..9cbeb246b1 100644 --- a/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs +++ b/crates/common/src/raindex_client/local_db/pipeline/status/wasm.rs @@ -1,6 +1,6 @@ use crate::local_db::pipeline::{StatusBus, SyncPhase}; -use crate::local_db::{LocalDbError, OrderbookIdentifier}; -use crate::raindex_client::local_db::{OrderbookSyncStatus, SchedulerState}; +use crate::local_db::{LocalDbError, RaindexIdentifier}; +use crate::raindex_client::local_db::{RaindexSyncStatus, SchedulerState}; use js_sys::Function; use std::cell::RefCell; use std::rc::Rc; @@ -27,7 +27,7 @@ pub fn get_scheduler_state() -> SchedulerState { SCHEDULER_STATE.with(|s| *s.borrow()) } -fn emit_to_callback(status: OrderbookSyncStatus) { +fn emit_to_callback(status: RaindexSyncStatus) { STATUS_CALLBACK.with(|c| { if let Some(callback) = c.borrow().as_ref() { if let Ok(value) = serde_wasm_bindgen::to_value(&status) { @@ -39,37 +39,42 @@ fn emit_to_callback(status: OrderbookSyncStatus) { #[derive(Debug, Clone, Default)] pub struct ClientStatusBus { - ob_id: Option, + raindex_id: Option, } impl ClientStatusBus { pub fn new() -> Self { - Self { ob_id: None } + Self { raindex_id: None } } - pub fn with_ob_id(ob_id: OrderbookIdentifier) -> Self { - Self { ob_id: Some(ob_id) } + pub fn with_ob_id(raindex_id: RaindexIdentifier) -> Self { + Self { + raindex_id: Some(raindex_id), + } } - fn emit(&self, status: OrderbookSyncStatus) { + fn emit(&self, status: RaindexSyncStatus) { emit_to_callback(status); } pub fn emit_active(&self) { - let Some(ob_id) = &self.ob_id else { + let Some(raindex_id) = &self.raindex_id else { return; }; let scheduler_state = get_scheduler_state(); - self.emit(OrderbookSyncStatus::active(ob_id.clone(), scheduler_state)); + self.emit(RaindexSyncStatus::active( + raindex_id.clone(), + scheduler_state, + )); } pub fn emit_failure(&self, error: String) { - let Some(ob_id) = &self.ob_id else { + let Some(raindex_id) = &self.raindex_id else { return; }; - self.emit(OrderbookSyncStatus::failure(ob_id.clone(), error)); + self.emit(RaindexSyncStatus::failure(raindex_id.clone(), error)); } } @@ -81,11 +86,11 @@ impl StatusBus for ClientStatusBus { return Ok(()); } - let Some(ob_id) = &self.ob_id else { + let Some(raindex_id) = &self.raindex_id else { return Ok(()); }; - let status = OrderbookSyncStatus::syncing(ob_id.clone(), phase); + let status = RaindexSyncStatus::syncing(raindex_id.clone(), phase); self.emit(status); Ok(()) @@ -96,25 +101,25 @@ impl StatusBus for ClientStatusBus { mod tests { use super::*; use crate::local_db::pipeline::SyncPhase; - use crate::local_db::OrderbookIdentifier; + use crate::local_db::RaindexIdentifier; use crate::raindex_client::local_db::SchedulerState; use alloy::primitives::address; - fn test_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(1, address!("0000000000000000000000000000000000001234")) + fn test_ob_id() -> RaindexIdentifier { + RaindexIdentifier::new(1, address!("0000000000000000000000000000000000001234")) } #[test] fn client_status_bus_default_has_no_ob_id() { let bus = ClientStatusBus::new(); - assert!(bus.ob_id.is_none()); + assert!(bus.raindex_id.is_none()); } #[test] fn client_status_bus_with_ob_id_stores_identifier() { - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id.clone()); - assert_eq!(bus.ob_id, Some(ob_id)); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id.clone()); + assert_eq!(bus.raindex_id, Some(raindex_id)); } #[tokio::test] @@ -126,9 +131,9 @@ mod tests { #[tokio::test] async fn send_skips_when_not_leader() { - let ob_id = test_ob_id(); + let raindex_id = test_ob_id(); set_scheduler_state(SchedulerState::NotLeader); - let bus = ClientStatusBus::with_ob_id(ob_id); + let bus = ClientStatusBus::with_ob_id(raindex_id); let result = bus.send(SyncPhase::FetchingLatestBlock).await; assert!(result.is_ok()); set_scheduler_state(SchedulerState::Leader); @@ -137,8 +142,8 @@ mod tests { #[tokio::test] async fn send_returns_ok_when_leader_with_ob_id() { set_scheduler_state(SchedulerState::Leader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); let result = bus.send(SyncPhase::FetchingLatestBlock).await; assert!(result.is_ok()); } @@ -158,15 +163,15 @@ mod tests { #[test] fn emit_active_with_ob_id_does_not_panic() { set_scheduler_state(SchedulerState::Leader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); bus.emit_active(); } #[test] fn emit_failure_with_ob_id_does_not_panic() { - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); bus.emit_failure("test error".to_string()); } @@ -187,9 +192,9 @@ mod tests { mod wasm_tests { use super::*; use crate::local_db::pipeline::{StatusBus, SyncPhase}; - use crate::local_db::OrderbookIdentifier; + use crate::local_db::RaindexIdentifier; use crate::raindex_client::local_db::LocalDbStatus; - use crate::raindex_client::local_db::{OrderbookSyncStatus, SchedulerState}; + use crate::raindex_client::local_db::{RaindexSyncStatus, SchedulerState}; use alloy::primitives::address; use std::cell::RefCell; use std::rc::Rc; @@ -200,15 +205,15 @@ mod wasm_tests { wasm_bindgen_test_configure!(run_in_browser); - fn test_ob_id() -> OrderbookIdentifier { - OrderbookIdentifier::new(1, address!("0000000000000000000000000000000000001234")) + fn test_ob_id() -> RaindexIdentifier { + RaindexIdentifier::new(1, address!("0000000000000000000000000000000000001234")) } fn create_recording_callback( - recorded: Rc>>, + recorded: Rc>>, ) -> Rc { let closure = Closure::wrap(Box::new(move |value: JsValue| { - if let Ok(status) = serde_wasm_bindgen::from_value::(value) { + if let Ok(status) = serde_wasm_bindgen::from_value::(value) { recorded.borrow_mut().push(status); } }) as Box); @@ -225,8 +230,8 @@ mod wasm_tests { set_status_callback(Some(callback)); set_scheduler_state(SchedulerState::Leader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id.clone()); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id.clone()); bus.send(SyncPhase::FetchingLatestBlock).await.unwrap(); set_status_callback(None); @@ -235,7 +240,7 @@ mod wasm_tests { assert_eq!(emissions.len(), 1, "expected exactly one emission"); let emitted = &emissions[0]; - assert_eq!(emitted.ob_id, ob_id); + assert_eq!(emitted.raindex_id, raindex_id); assert_eq!(emitted.status, LocalDbStatus::Syncing); assert_eq!(emitted.scheduler_state, SchedulerState::Leader); assert_eq!( @@ -252,8 +257,8 @@ mod wasm_tests { set_status_callback(Some(callback)); set_scheduler_state(SchedulerState::NotLeader); - let ob_id = test_ob_id(); - let bus = ClientStatusBus::with_ob_id(ob_id); + let raindex_id = test_ob_id(); + let bus = ClientStatusBus::with_ob_id(raindex_id); bus.send(SyncPhase::FetchingLatestBlock).await.unwrap(); set_status_callback(None); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_all_tokens.rs b/crates/common/src/raindex_client/local_db/query/fetch_all_tokens.rs index cb85cb8b5f..9a0835674e 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_all_tokens.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_all_tokens.rs @@ -26,7 +26,7 @@ mod wasm_tests { async fn wrapper_uses_builder_sql_exactly() { let args = FetchAllTokensArgs { chain_ids: vec![1, 137], - orderbook_addresses: vec![Address::from([0x11; 20])], + raindex_addresses: vec![Address::from([0x11; 20])], }; let expected_stmt = build_fetch_all_tokens_stmt(&args).unwrap(); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs b/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs index df5d5dbb10..4ecc96a5e7 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_erc20_tokens_by_addresses.rs @@ -1,14 +1,14 @@ use crate::local_db::query::fetch_erc20_tokens_by_addresses::{build_fetch_stmt, Erc20TokenRow}; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use alloy::primitives::Address; pub async fn fetch_erc20_tokens_by_addresses( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, addresses: &[Address], ) -> Result, LocalDbQueryError> { - if let Some(stmt) = build_fetch_stmt(ob_id, addresses)? { + if let Some(stmt) = build_fetch_stmt(raindex_id, addresses)? { exec.query_json(&stmt).await } else { Ok(vec![]) @@ -36,7 +36,7 @@ mod wasm_tests { let exec = JsCallbackExecutor::from_ref(&callback); let res = super::fetch_erc20_tokens_by_addresses( &exec, - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), &[], ) .await; @@ -51,7 +51,7 @@ mod wasm_tests { Address::from_str("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(), Address::from_str("0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").unwrap(), ]; - let expected_stmt = build_fetch_stmt(&OrderbookIdentifier::new(10, Address::ZERO), &addrs) + let expected_stmt = build_fetch_stmt(&RaindexIdentifier::new(10, Address::ZERO), &addrs) .unwrap() .unwrap(); @@ -64,7 +64,7 @@ mod wasm_tests { let res = super::fetch_erc20_tokens_by_addresses( &exec, - &OrderbookIdentifier::new(10, Address::ZERO), + &RaindexIdentifier::new(10, Address::ZERO), &addrs, ) .await; diff --git a/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs b/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs index 6167823478..98b3264b54 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_last_synced_block.rs @@ -2,13 +2,14 @@ use crate::local_db::query::fetch_last_synced_block::{ fetch_last_synced_block_stmt, SyncStatusResponse, }; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; pub async fn fetch_last_synced_block( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result, LocalDbQueryError> { - exec.query_json(&fetch_last_synced_block_stmt(ob_id)).await + exec.query_json(&fetch_last_synced_block_stmt(raindex_id)) + .await } #[cfg(target_family = "wasm")] @@ -28,13 +29,13 @@ mod wasm { #[wasm_export(param_description = "JavaScript function to execute database queries")] db_callback: js_sys::Function, #[wasm_export(js_name = "chainId")] chain_id: u32, - #[wasm_export(js_name = "orderbookAddress", unchecked_param_type = "Address")] - orderbook_address: String, + #[wasm_export(js_name = "raindexAddress", unchecked_param_type = "Address")] + raindex_address: String, ) -> Result, LocalDbError> { let exec = JsCallbackExecutor::from_ref(&db_callback); fetch_last_synced_block( &exec, - &OrderbookIdentifier::new(chain_id, Address::from_str(&orderbook_address)?), + &RaindexIdentifier::new(chain_id, Address::from_str(&raindex_address)?), ) .await .map_err(LocalDbError::from) @@ -54,14 +55,12 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_raw_sql_exactly() { - let expected_stmt = - fetch_last_synced_block_stmt(&OrderbookIdentifier::new(0, Address::ZERO)); + let expected_stmt = fetch_last_synced_block_stmt(&RaindexIdentifier::new(0, Address::ZERO)); let store = Rc::new(RefCell::new((String::new(), JsValue::UNDEFINED))); let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); let res = - super::fetch_last_synced_block(&exec, &OrderbookIdentifier::new(0, Address::ZERO)) - .await; + super::fetch_last_synced_block(&exec, &RaindexIdentifier::new(0, Address::ZERO)).await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs index f65057f9a5..74ecf2866b 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades.rs @@ -2,17 +2,18 @@ use crate::local_db::query::fetch_order_trades::{ build_fetch_order_trades_stmt, LocalDbOrderTrade, }; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use alloy::primitives::B256; pub async fn fetch_order_trades( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result, LocalDbQueryError> { - let stmt = build_fetch_order_trades_stmt(ob_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = + build_fetch_order_trades_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; exec.query_json(&stmt).await } @@ -30,14 +31,14 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_builder_sql_exactly() { let chain_id = 111; - let orderbook = Address::from([0x77; 20]); + let raindex = Address::from([0x77; 20]); let order_hash = b256!("0x000000000000000000000000000000000000000000000000000000000000abcd"); let start = Some(100); let end = Some(200); let expected_stmt = build_fetch_order_trades_stmt( - &OrderbookIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash.clone(), start, end, @@ -53,7 +54,7 @@ mod wasm_tests { let res = super::fetch_order_trades( &exec, - &OrderbookIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash, start, end, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs index 4c100aa50e..10a66d6413 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_trades_count.rs @@ -4,16 +4,17 @@ use crate::local_db::query::fetch_order_trades_count::{ build_fetch_trade_count_stmt, extract_trade_count, LocalDbTradeCountRow, }; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; pub async fn fetch_order_trades_count( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { - let stmt = build_fetch_trade_count_stmt(ob_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = + build_fetch_trade_count_stmt(raindex_id, order_hash, start_timestamp, end_timestamp)?; let rows: Vec = exec.query_json(&stmt).await?; Ok(extract_trade_count(&rows)) } @@ -36,9 +37,9 @@ mod wasm_tests { let start = Some(10); let end = Some(20); - let orderbook = Address::from([0x88; 20]); + let raindex = Address::from([0x88; 20]); let expected_stmt = build_fetch_trade_count_stmt( - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), order_hash.clone(), start, end, @@ -56,7 +57,7 @@ mod wasm_tests { let res = super::fetch_order_trades_count( &exec, - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), order_hash, start, end, @@ -79,7 +80,7 @@ mod wasm_tests { let exec = JsCallbackExecutor::from_ref(&callback); let res = super::fetch_order_trades_count( &exec, - &OrderbookIdentifier::new(1, Address::ZERO), + &RaindexIdentifier::new(1, Address::ZERO), b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"), None, None, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs index d73db58800..caac4ef0ee 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_order_vaults_volume.rs @@ -2,18 +2,22 @@ use crate::local_db::query::fetch_order_vaults_volume::{ build_fetch_order_vaults_volume_stmt, LocalDbVaultVolume, }; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use alloy::primitives::B256; pub async fn fetch_order_vaults_volume( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, start_timestamp: Option, end_timestamp: Option, ) -> Result, LocalDbQueryError> { - let stmt = - build_fetch_order_vaults_volume_stmt(ob_id, order_hash, start_timestamp, end_timestamp)?; + let stmt = build_fetch_order_vaults_volume_stmt( + raindex_id, + order_hash, + start_timestamp, + end_timestamp, + )?; exec.query_json(&stmt).await } @@ -31,14 +35,14 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_builder_sql_exactly() { let chain_id = 111; - let orderbook = Address::from([0x77; 20]); + let raindex = Address::from([0x77; 20]); let order_hash = b256!("0x000000000000000000000000000000000000000000000000000000000000abcd"); let start = Some(100); let end = Some(200); let expected_stmt = build_fetch_order_vaults_volume_stmt( - &OrderbookIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash, start, end, @@ -54,7 +58,7 @@ mod wasm_tests { let res = super::fetch_order_vaults_volume( &exec, - &OrderbookIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex), order_hash, start, end, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_orders.rs b/crates/common/src/raindex_client/local_db/query/fetch_orders.rs index 7e606c18e0..5169a01634 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_orders.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_orders.rs @@ -25,7 +25,7 @@ impl From for FetchOrdersArgs { owners: filters.owners, order_hash: filters.order_hash, tokens, - orderbook_addresses: filters.orderbook_addresses.unwrap_or_default(), + raindex_addresses: filters.raindex_addresses.unwrap_or_default(), ..FetchOrdersArgs::default() } } @@ -50,8 +50,8 @@ mod tests { fn from_get_orders_filters_builds_args() { let owner = Address::from_str("0x0123456789ABCDEF0123456789ABCDEF01234567").unwrap(); let token = Address::from_str("0x89ABCDEF0123456789ABCDEF0123456789ABCDEF").unwrap(); - let orderbook1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - let orderbook2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); + let raindex1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + let raindex2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); let filters = GetOrdersFilters { owners: vec![owner], active: Some(true), @@ -62,7 +62,7 @@ mod tests { inputs: Some(vec![token]), outputs: None, }), - orderbook_addresses: Some(vec![orderbook1, orderbook2]), + raindex_addresses: Some(vec![raindex1, raindex2]), }; let args: FetchOrdersArgs = filters.into(); assert!(matches!(args.filter, FetchOrdersActiveFilter::Active)); @@ -81,37 +81,37 @@ mod tests { "0x00000000000000000000000000000000000000000000000000000000deadbeef" )) ); - assert_eq!(args.orderbook_addresses.len(), 2); - assert_eq!(args.orderbook_addresses[0], orderbook1); - assert_eq!(args.orderbook_addresses[1], orderbook2); + assert_eq!(args.raindex_addresses.len(), 2); + assert_eq!(args.raindex_addresses[0], raindex1); + assert_eq!(args.raindex_addresses[1], raindex2); } #[test] - fn from_get_orders_filters_none_orderbook_addresses_becomes_empty_vec() { + fn from_get_orders_filters_none_raindex_addresses_becomes_empty_vec() { let filters = GetOrdersFilters { owners: vec![], active: None, order_hash: None, tokens: None, - orderbook_addresses: None, + raindex_addresses: None, }; let args: FetchOrdersArgs = filters.into(); - assert!(args.orderbook_addresses.is_empty()); + assert!(args.raindex_addresses.is_empty()); } #[test] - fn from_get_orders_filters_single_orderbook_address() { - let orderbook = address!("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); + fn from_get_orders_filters_single_raindex_address() { + let raindex = address!("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); let filters = GetOrdersFilters { owners: vec![], active: None, order_hash: None, tokens: None, - orderbook_addresses: Some(vec![orderbook]), + raindex_addresses: Some(vec![raindex]), }; let args: FetchOrdersArgs = filters.into(); - assert_eq!(args.orderbook_addresses.len(), 1); - assert_eq!(args.orderbook_addresses[0], orderbook); + assert_eq!(args.raindex_addresses.len(), 1); + assert_eq!(args.raindex_addresses[0], raindex); } #[cfg(target_family = "wasm")] @@ -127,7 +127,7 @@ mod tests { use wasm_bindgen_test::*; use wasm_bindgen_utils::prelude::*; - fn orderbook() -> Address { + fn raindex() -> Address { Address::from([0x11; 20]) } @@ -145,7 +145,7 @@ mod tests { "0x0000000000000000000000000000000000000000000000000000000000000001" )); args.chain_ids = vec![137]; - args.orderbook_addresses = vec![orderbook()]; + args.raindex_addresses = vec![raindex()]; let expected_stmt = build_fetch_orders_stmt(&args).unwrap(); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs index 76952ea332..d9bcd6dd9a 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_store_addresses.rs @@ -1,12 +1,13 @@ use crate::local_db::query::fetch_store_addresses::{fetch_store_addresses_stmt, StoreAddressRow}; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; pub async fn fetch_store_addresses( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, ) -> Result, LocalDbQueryError> { - exec.query_json(&fetch_store_addresses_stmt(ob_id)).await + exec.query_json(&fetch_store_addresses_stmt(raindex_id)) + .await } #[cfg(all(test, target_family = "wasm"))] @@ -22,16 +23,15 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_raw_sql_exactly() { - let orderbook = Address::from([0x55; 20]); - let expected_stmt = fetch_store_addresses_stmt(&OrderbookIdentifier::new(1, orderbook)); + let raindex = Address::from([0x55; 20]); + let expected_stmt = fetch_store_addresses_stmt(&RaindexIdentifier::new(1, raindex)); let store = Rc::new(RefCell::new(( String::new(), wasm_bindgen::JsValue::UNDEFINED, ))); let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); - let res = - super::fetch_store_addresses(&exec, &OrderbookIdentifier::new(1, orderbook)).await; + let res = super::fetch_store_addresses(&exec, &RaindexIdentifier::new(1, raindex)).await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } diff --git a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs index 959ebaa06f..dbcee73897 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_transaction_by_hash.rs @@ -2,15 +2,15 @@ use crate::local_db::query::fetch_transaction_by_hash::{ build_fetch_transaction_by_hash_stmt, LocalDbTransaction, }; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use alloy::primitives::B256; pub async fn fetch_transaction_by_hash( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, tx_hash: B256, ) -> Result, LocalDbQueryError> { - let stmt = build_fetch_transaction_by_hash_stmt(ob_id, tx_hash); + let stmt = build_fetch_transaction_by_hash_stmt(raindex_id, tx_hash); exec.query_json(&stmt).await } @@ -28,20 +28,17 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_uses_builder_sql_exactly() { let tx_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc"); - let orderbook = Address::from([0x51; 20]); + let raindex = Address::from([0x51; 20]); let expected_stmt = - build_fetch_transaction_by_hash_stmt(&OrderbookIdentifier::new(1, orderbook), tx_hash); + build_fetch_transaction_by_hash_stmt(&RaindexIdentifier::new(1, raindex), tx_hash); let store = Rc::new(RefCell::new((String::new(), JsValue::UNDEFINED))); let callback = create_sql_capturing_callback("[]", store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); - let res = super::fetch_transaction_by_hash( - &exec, - &OrderbookIdentifier::new(1, orderbook), - tx_hash, - ) - .await; + let res = + super::fetch_transaction_by_hash(&exec, &RaindexIdentifier::new(1, raindex), tx_hash) + .await; assert!(res.is_ok()); assert_eq!(store.borrow().clone().0, expected_stmt.sql); } @@ -49,10 +46,10 @@ mod wasm_tests { #[wasm_bindgen_test] async fn wrapper_returns_rows_when_present() { let tx_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc"); - let orderbook = address!("0x5151515151515151515151515151515151515151"); + let raindex = address!("0x5151515151515151515151515151515151515151"); let sender = address!("0x1111111111111111111111111111111111111111"); let expected_stmt = - build_fetch_transaction_by_hash_stmt(&OrderbookIdentifier::new(1, orderbook), tx_hash); + build_fetch_transaction_by_hash_stmt(&RaindexIdentifier::new(1, raindex), tx_hash); let row_json = format!( r#"[{{ @@ -71,12 +68,9 @@ mod wasm_tests { let callback = create_sql_capturing_callback(&row_json, store.clone()); let exec = JsCallbackExecutor::from_ref(&callback); - let res = super::fetch_transaction_by_hash( - &exec, - &OrderbookIdentifier::new(1, orderbook), - tx_hash, - ) - .await; + let res = + super::fetch_transaction_by_hash(&exec, &RaindexIdentifier::new(1, raindex), tx_hash) + .await; assert!(res.is_ok()); let rows = res.unwrap(); assert_eq!(rows.len(), 1); diff --git a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs index 36a6a3fbb0..0ce3f8049f 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_vault_balance_changes.rs @@ -2,14 +2,14 @@ use crate::local_db::query::fetch_vault_balance_changes::{ build_fetch_balance_changes_stmt, LocalDbVaultBalanceChange, }; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use crate::raindex_client::vaults::VaultBalanceChangeFilter; use crate::types::VaultBalanceChangeKind; use alloy::primitives::{Address, U256}; pub async fn fetch_vault_balance_changes( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, vault_id: U256, token: Address, owner: Address, @@ -17,8 +17,13 @@ pub async fn fetch_vault_balance_changes( ) -> Result, LocalDbQueryError> { let filter_kinds: Option> = filter_types.map(|filters| filters.iter().map(|f| f.to_kind()).collect()); - let stmt = - build_fetch_balance_changes_stmt(ob_id, vault_id, token, owner, filter_kinds.as_deref())?; + let stmt = build_fetch_balance_changes_stmt( + raindex_id, + vault_id, + token, + owner, + filter_kinds.as_deref(), + )?; exec.query_json(&stmt).await } @@ -37,10 +42,10 @@ mod wasm_tests { async fn wrapper_uses_builder_sql_exactly() { let vault_id = U256::from(1); let token = address!("0x00000000000000000000000000000000000000aa"); - let orderbook = Address::from([0x51; 20]); + let raindex = Address::from([0x51; 20]); let owner = address!("0x00000000000000000000000000000000000000f1"); let expected_stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -57,7 +62,7 @@ mod wasm_tests { let res = super::fetch_vault_balance_changes( &exec, - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -72,10 +77,10 @@ mod wasm_tests { async fn wrapper_returns_rows_when_present() { let vault_id = U256::from(1); let token = address!("0x00000000000000000000000000000000000000bb"); - let orderbook = Address::from([0x61; 20]); + let raindex = Address::from([0x61; 20]); let owner = address!("0x0000000000000000000000000000000000000011"); let expected_stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -105,7 +110,7 @@ mod wasm_tests { let res = super::fetch_vault_balance_changes( &exec, - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -122,7 +127,7 @@ mod wasm_tests { async fn wrapper_uses_builder_sql_with_filter_types() { let vault_id = U256::from(1); let token = address!("0x00000000000000000000000000000000000000aa"); - let orderbook = Address::from([0x51; 20]); + let raindex = Address::from([0x51; 20]); let owner = address!("0x00000000000000000000000000000000000000f1"); let filter_types = vec![ VaultBalanceChangeFilter::Deposit, @@ -130,7 +135,7 @@ mod wasm_tests { ]; let filter_kinds: Vec<_> = filter_types.iter().map(|f| f.to_kind()).collect(); let expected_stmt = build_fetch_balance_changes_stmt( - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, @@ -147,7 +152,7 @@ mod wasm_tests { let res = super::fetch_vault_balance_changes( &exec, - &OrderbookIdentifier::new(1, orderbook), + &RaindexIdentifier::new(1, raindex), vault_id, token, owner, diff --git a/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs b/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs index 0513ddb464..8724d54a88 100644 --- a/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs +++ b/crates/common/src/raindex_client/local_db/query/fetch_vaults.rs @@ -7,7 +7,7 @@ impl FetchVaultsArgs { pub fn from_filters(filters: GetVaultsFilters) -> Self { FetchVaultsArgs { chain_ids: Vec::new(), - orderbook_addresses: filters.orderbook_addresses.unwrap_or_default(), + raindex_addresses: filters.raindex_addresses.unwrap_or_default(), owners: filters.owners, tokens: filters.tokens.unwrap_or_default(), hide_zero_balance: filters.hide_zero_balance, @@ -39,13 +39,13 @@ mod tests { fn from_filters_builds_args() { let owner = address!("0x0123456789ABCDEF0123456789ABCDEF01234567"); let token = address!("0x89ABCDEF0123456789ABCDEF0123456789ABCDEF"); - let orderbook1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); - let orderbook2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); + let raindex1 = address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); + let raindex2 = address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); let filters = GetVaultsFilters { owners: vec![owner], hide_zero_balance: true, tokens: Some(vec![token]), - orderbook_addresses: Some(vec![orderbook1, orderbook2]), + raindex_addresses: Some(vec![raindex1, raindex2]), only_active_orders: false, }; let args = FetchVaultsArgs::from_filters(filters); @@ -58,38 +58,38 @@ mod tests { vec![address!("0x89abcdef0123456789abcdef0123456789abcdef")] ); assert!(args.hide_zero_balance); - assert_eq!(args.orderbook_addresses.len(), 2); - assert_eq!(args.orderbook_addresses[0], orderbook1); - assert_eq!(args.orderbook_addresses[1], orderbook2); + assert_eq!(args.raindex_addresses.len(), 2); + assert_eq!(args.raindex_addresses[0], raindex1); + assert_eq!(args.raindex_addresses[1], raindex2); assert!(!args.only_active_orders); } #[test] - fn from_filters_none_orderbook_addresses_becomes_empty_vec() { + fn from_filters_none_raindex_addresses_becomes_empty_vec() { let filters = GetVaultsFilters { owners: vec![], hide_zero_balance: false, tokens: None, - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: false, }; let args = FetchVaultsArgs::from_filters(filters); - assert!(args.orderbook_addresses.is_empty()); + assert!(args.raindex_addresses.is_empty()); } #[test] - fn from_filters_single_orderbook_address() { - let orderbook = address!("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); + fn from_filters_single_raindex_address() { + let raindex = address!("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF"); let filters = GetVaultsFilters { owners: vec![], hide_zero_balance: false, tokens: None, - orderbook_addresses: Some(vec![orderbook]), + raindex_addresses: Some(vec![raindex]), only_active_orders: false, }; let args = FetchVaultsArgs::from_filters(filters); - assert_eq!(args.orderbook_addresses.len(), 1); - assert_eq!(args.orderbook_addresses[0], orderbook); + assert_eq!(args.raindex_addresses.len(), 1); + assert_eq!(args.raindex_addresses[0], raindex); } #[test] @@ -98,7 +98,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: None, - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: true, }; let args = FetchVaultsArgs::from_filters(filters); @@ -126,7 +126,7 @@ mod tests { args.tokens = vec![address!("0x00000000000000000000000000000000000000aa")]; args.hide_zero_balance = true; args.chain_ids = vec![1, 137]; - args.orderbook_addresses = vec![ + args.raindex_addresses = vec![ Address::from([0x11; 20]), Address::from([0x22; 20]), Address::from([0x22; 20]), diff --git a/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs b/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs index 1d9fc3db31..a2b0a6a119 100644 --- a/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs +++ b/crates/common/src/raindex_client/local_db/query/update_last_synced_block.rs @@ -1,13 +1,13 @@ use crate::local_db::query::update_last_synced_block::build_update_last_synced_block_stmt; use crate::local_db::query::{LocalDbQueryError, LocalDbQueryExecutor}; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; pub async fn update_last_synced_block( exec: &E, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, block_number: u64, ) -> Result<(), LocalDbQueryError> { - let stmt = build_update_last_synced_block_stmt(ob_id, block_number); + let stmt = build_update_last_synced_block_stmt(raindex_id, block_number); exec.query_text(&stmt).await.map(|_| ()) } @@ -28,7 +28,7 @@ mod wasm_tests { async fn wrapper_uses_builder_sql_exactly() { let addr = Address::from([0x11u8; 20]); let expected_stmt = - build_update_last_synced_block_stmt(&OrderbookIdentifier::new(1, addr), 999); + build_update_last_synced_block_stmt(&RaindexIdentifier::new(1, addr), 999); let store = Rc::new(RefCell::new(( String::new(), wasm_bindgen::JsValue::UNDEFINED, @@ -37,7 +37,7 @@ mod wasm_tests { let exec = JsCallbackExecutor::from_ref(&callback); let res = - super::update_last_synced_block(&exec, &OrderbookIdentifier::new(1, addr), 999).await; + super::update_last_synced_block(&exec, &RaindexIdentifier::new(1, addr), 999).await; assert!(res.is_ok()); let captured = store.borrow().clone(); assert_eq!(captured.0, expected_stmt.sql); @@ -64,7 +64,7 @@ mod wasm_tests { let exec = JsCallbackExecutor::from_ref(&callback); let res = super::update_last_synced_block( &exec, - &OrderbookIdentifier::new(1, Address::from([0x22u8; 20])), + &RaindexIdentifier::new(1, Address::from([0x22u8; 20])), 999, ) .await; diff --git a/crates/common/src/raindex_client/local_db/state.rs b/crates/common/src/raindex_client/local_db/state.rs index 5f3a25e0fd..a7b38cb8a7 100644 --- a/crates/common/src/raindex_client/local_db/state.rs +++ b/crates/common/src/raindex_client/local_db/state.rs @@ -3,8 +3,8 @@ use super::LocalDb; use crate::raindex_client::local_db::pipeline::runner::scheduler::NativeSyncHandle; #[cfg(target_family = "wasm")] use crate::raindex_client::local_db::pipeline::runner::scheduler::SchedulerHandle; -use rain_orderbook_app_settings::network::NetworkCfg; -use rain_orderbook_app_settings::yaml::orderbook::OrderbookYaml; +use raindex_app_settings::network::NetworkCfg; +use raindex_app_settings::yaml::raindex::RaindexYaml; #[cfg(target_family = "wasm")] use std::cell::RefCell; use std::collections::HashSet; @@ -98,7 +98,7 @@ impl LocalDbState { } impl LocalDbState { - pub(crate) fn compute_chain_ids(yaml: &OrderbookYaml) -> HashSet { + pub(crate) fn compute_chain_ids(yaml: &RaindexYaml) -> HashSet { let syncs = match yaml.get_local_db_syncs() { Ok(s) => s, Err(_) => return HashSet::new(), @@ -223,9 +223,9 @@ mod tests { use crate::local_db::query::{ FromDbJson, LocalDbQueryError, LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::orderbook::{OrderbookYaml, OrderbookYamlValidation}; - use rain_orderbook_app_settings::yaml::YamlParsable; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::raindex::{RaindexYaml, RaindexYamlValidation}; + use raindex_app_settings::yaml::YamlParsable; struct NoopExec; @@ -414,8 +414,8 @@ local-db-sync: finality-depth: 12 bootstrap-block-threshold: 1000 sync-interval-ms: 5000 -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil @@ -423,8 +423,8 @@ orderbooks: "#, version = SpecVersion::current() ); - let yaml = OrderbookYaml::new(vec![yaml_str], OrderbookYamlValidation::default()) - .expect("valid yaml"); + let yaml = + RaindexYaml::new(vec![yaml_str], RaindexYamlValidation::default()).expect("valid yaml"); let ids = LocalDbState::compute_chain_ids(&yaml); assert_eq!(ids, HashSet::from([42161])); assert!(!ids.contains(&137)); @@ -442,8 +442,8 @@ networks: chain-id: 42161 subgraphs: anvil: https://subgraph.example/anvil -orderbooks: - ob-a: +raindexes: + raindex-a: address: 0x00000000000000000000000000000000000000a1 network: anvil subgraph: anvil @@ -451,8 +451,8 @@ orderbooks: "#, version = SpecVersion::current() ); - let yaml = OrderbookYaml::new(vec![yaml_str], OrderbookYamlValidation::default()) - .expect("valid yaml"); + let yaml = + RaindexYaml::new(vec![yaml_str], RaindexYamlValidation::default()).expect("valid yaml"); let ids = LocalDbState::compute_chain_ids(&yaml); assert!(ids.is_empty()); } diff --git a/crates/common/src/raindex_client/local_db/status.rs b/crates/common/src/raindex_client/local_db/status.rs index c7ee7554c7..18382981db 100644 --- a/crates/common/src/raindex_client/local_db/status.rs +++ b/crates/common/src/raindex_client/local_db/status.rs @@ -1,5 +1,5 @@ use crate::local_db::pipeline::SyncPhase; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use serde::{Deserialize, Serialize}; use tsify::Tsify; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; @@ -23,8 +23,8 @@ impl_wasm_traits!(SchedulerState); #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Tsify)] #[serde(rename_all = "camelCase")] -pub struct OrderbookSyncStatus { - pub ob_id: OrderbookIdentifier, +pub struct RaindexSyncStatus { + pub raindex_id: RaindexIdentifier, pub status: LocalDbStatus, pub scheduler_state: SchedulerState, #[serde(skip_serializing_if = "Option::is_none")] @@ -32,18 +32,18 @@ pub struct OrderbookSyncStatus { #[serde(skip_serializing_if = "Option::is_none")] pub error: Option, } -impl_wasm_traits!(OrderbookSyncStatus); +impl_wasm_traits!(RaindexSyncStatus); -impl OrderbookSyncStatus { +impl RaindexSyncStatus { pub fn new( - ob_id: OrderbookIdentifier, + raindex_id: RaindexIdentifier, status: LocalDbStatus, scheduler_state: SchedulerState, phase_message: Option, error: Option, ) -> Self { Self { - ob_id, + raindex_id, status, scheduler_state, phase_message, @@ -51,9 +51,9 @@ impl OrderbookSyncStatus { } } - pub fn syncing(ob_id: OrderbookIdentifier, phase: SyncPhase) -> Self { + pub fn syncing(raindex_id: RaindexIdentifier, phase: SyncPhase) -> Self { Self::new( - ob_id, + raindex_id, LocalDbStatus::Syncing, SchedulerState::Leader, Some(phase.to_message().to_string()), @@ -61,13 +61,19 @@ impl OrderbookSyncStatus { ) } - pub fn active(ob_id: OrderbookIdentifier, scheduler_state: SchedulerState) -> Self { - Self::new(ob_id, LocalDbStatus::Active, scheduler_state, None, None) + pub fn active(raindex_id: RaindexIdentifier, scheduler_state: SchedulerState) -> Self { + Self::new( + raindex_id, + LocalDbStatus::Active, + scheduler_state, + None, + None, + ) } - pub fn failure(ob_id: OrderbookIdentifier, error: String) -> Self { + pub fn failure(raindex_id: RaindexIdentifier, error: String) -> Self { Self::new( - ob_id, + raindex_id, LocalDbStatus::Failure, SchedulerState::Leader, None, @@ -157,30 +163,30 @@ mod tests { use super::*; #[test] - fn orderbook_sync_status_serializes_with_camel_case() { + fn raindex_sync_status_serializes_with_camel_case() { use crate::local_db::pipeline::SyncPhase; use alloy::primitives::address; - let ob_id = crate::local_db::OrderbookIdentifier::new( + let raindex_id = crate::local_db::RaindexIdentifier::new( 42161, address!("0000000000000000000000000000000000001234"), ); - let status = OrderbookSyncStatus::syncing(ob_id, SyncPhase::FetchingLatestBlock); + let status = RaindexSyncStatus::syncing(raindex_id, SyncPhase::FetchingLatestBlock); let json = serde_json::to_string(&status).unwrap(); assert!( - json.contains("\"obId\":{"), - "expected obId as nested object in JSON: {}", + json.contains("\"raindexId\":{"), + "expected raindexId as nested object in JSON: {}", json ); assert!( json.contains("\"chainId\":42161"), - "expected chainId in obId in JSON: {}", + "expected chainId in raindexId in JSON: {}", json ); assert!( - json.contains("\"orderbookAddress\":"), - "expected orderbookAddress in obId in JSON: {}", + json.contains("\"raindexAddress\":"), + "expected raindexAddress in raindexId in JSON: {}", json ); assert!( @@ -199,8 +205,8 @@ mod tests { json ); assert!( - !json.contains("orderbook_address"), - "should not have snake_case orderbook_address: {}", + !json.contains("raindex_address"), + "should not have snake_case raindex_address: {}", json ); } @@ -301,17 +307,17 @@ mod tests { } #[test] - fn orderbook_sync_status_deserializes_from_json() { + fn raindex_sync_status_deserializes_from_json() { let json = r#"{ - "obId": {"chainId": 137, "orderbookAddress": "0x0000000000000000000000000000000000001234"}, + "raindexId": {"chainId": 137, "raindexAddress": "0x0000000000000000000000000000000000001234"}, "status": "syncing", "schedulerState": "leader", "phaseMessage": "Fetching latest block" }"#; - let status: OrderbookSyncStatus = serde_json::from_str(json).unwrap(); + let status: RaindexSyncStatus = serde_json::from_str(json).unwrap(); - assert_eq!(status.ob_id.chain_id, 137); + assert_eq!(status.raindex_id.chain_id, 137); assert_eq!(status.status, LocalDbStatus::Syncing); assert_eq!(status.scheduler_state, SchedulerState::Leader); assert_eq!( diff --git a/crates/common/src/raindex_client/local_db/transactions.rs b/crates/common/src/raindex_client/local_db/transactions.rs index ca41839a2f..c5e5dd5481 100644 --- a/crates/common/src/raindex_client/local_db/transactions.rs +++ b/crates/common/src/raindex_client/local_db/transactions.rs @@ -5,7 +5,7 @@ use crate::local_db::query::fetch_transaction_by_hash::{ build_fetch_transaction_by_hash_stmt, LocalDbTransaction, }; use crate::local_db::query::LocalDbQueryExecutor; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use alloy::primitives::B256; pub struct LocalDbTransactions<'a> { @@ -21,10 +21,10 @@ impl<'a> LocalDbTransactions<'a> { /// Returns None if no transaction with that hash is found. pub async fn get_by_tx_hash( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, tx_hash: B256, ) -> Result, RaindexError> { - let stmt = build_fetch_transaction_by_hash_stmt(ob_id, tx_hash); + let stmt = build_fetch_transaction_by_hash_stmt(raindex_id, tx_hash); let results: Vec = self.db.query_json(&stmt).await?; if let Some(local_tx) = results.into_iter().next() { @@ -81,7 +81,7 @@ mod tests { let tx_hash = b256!("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"); let sender = address!("0x1111111111111111111111111111111111111111"); - let orderbook = address!("0x2222222222222222222222222222222222222222"); + let raindex_addr = address!("0x2222222222222222222222222222222222222222"); let tx_json = json!([{ "transactionHash": tx_hash.to_string(), @@ -95,9 +95,9 @@ mod tests { let local_db = LocalDb::new(exec); let transactions = LocalDbTransactions::new(&local_db); - let ob_id = OrderbookIdentifier::new(1, orderbook); + let raindex_id = RaindexIdentifier::new(1, raindex_addr); - let result = transactions.get_by_tx_hash(&ob_id, tx_hash).await; + let result = transactions.get_by_tx_hash(&raindex_id, tx_hash).await; assert!(result.is_ok()); let tx = result.unwrap(); @@ -110,16 +110,16 @@ mod tests { async fn test_get_by_tx_hash_returns_none_when_not_found() { let tx_hash = b256!("0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890"); - let orderbook = address!("0x2222222222222222222222222222222222222222"); + let raindex_addr = address!("0x2222222222222222222222222222222222222222"); let callback = create_mock_callback("[]"); let exec = JsCallbackExecutor::from_ref(&callback); let local_db = LocalDb::new(exec); let transactions = LocalDbTransactions::new(&local_db); - let ob_id = OrderbookIdentifier::new(1, orderbook); + let raindex_id = RaindexIdentifier::new(1, raindex_addr); - let result = transactions.get_by_tx_hash(&ob_id, tx_hash).await; + let result = transactions.get_by_tx_hash(&raindex_id, tx_hash).await; assert!(result.is_ok()); assert!(result.unwrap().is_none()); diff --git a/crates/common/src/raindex_client/local_db/vaults.rs b/crates/common/src/raindex_client/local_db/vaults.rs index c1dca627e0..ce2b9b54b6 100644 --- a/crates/common/src/raindex_client/local_db/vaults.rs +++ b/crates/common/src/raindex_client/local_db/vaults.rs @@ -2,7 +2,7 @@ use super::super::RaindexError; use super::{ query::fetch_all_tokens::fetch_all_tokens, query::fetch_vault_balance_changes::fetch_vault_balance_changes, - query::fetch_vaults::fetch_vaults, LocalDb, OrderbookIdentifier, + query::fetch_vaults::fetch_vaults, LocalDb, RaindexIdentifier, }; use crate::raindex_client::ClientRef; use crate::{ @@ -73,12 +73,12 @@ impl VaultsDataSource for LocalDbVaults<'_> { async fn get_by_id( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, vault_id: &Bytes, ) -> Result, RaindexError> { let fetch_args = FetchVaultsArgs { - chain_ids: vec![ob_id.chain_id], - orderbook_addresses: vec![ob_id.orderbook_address], + chain_ids: vec![raindex_id.chain_id], + raindex_addresses: vec![raindex_id.raindex_address], hide_zero_balance: false, ..FetchVaultsArgs::default() }; @@ -101,9 +101,9 @@ impl VaultsDataSource for LocalDbVaults<'_> { filter_types: Option<&[VaultBalanceChangeFilter]>, ) -> Result, RaindexError> { #[cfg(target_family = "wasm")] - let orderbook_address = Address::from_str(&vault.orderbook())?; + let raindex_address = Address::from_str(&vault.raindex())?; #[cfg(not(target_family = "wasm"))] - let orderbook_address = vault.orderbook(); + let raindex_address = vault.raindex(); #[cfg(target_family = "wasm")] let vault_id = U256::from_str(&vault.vault_id_hex())?; @@ -120,10 +120,10 @@ impl VaultsDataSource for LocalDbVaults<'_> { #[cfg(not(target_family = "wasm"))] let owner_address = vault.owner(); - let ob_id = crate::local_db::OrderbookIdentifier::new(vault.chain_id(), orderbook_address); + let raindex_id = crate::local_db::RaindexIdentifier::new(vault.chain_id(), raindex_address); let local_changes = fetch_vault_balance_changes( self.db, - &ob_id, + &raindex_id, vault_id, token_address, owner_address, @@ -208,7 +208,7 @@ mod tests { vault_id: U256::from_str(vault_id).unwrap(), token: Address::from_str(token).unwrap(), owner: Address::from_str(owner).unwrap(), - orderbook_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), + raindex_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), token_name: "Token".to_string(), token_symbol: "TKN".to_string(), token_decimals: 18, @@ -242,7 +242,7 @@ mod tests { assert_eq!(result_vault.chain_id(), 42161); assert_eq!(result_vault.owner().to_lowercase(), owner.to_string()); assert_eq!( - result_vault.orderbook().to_lowercase(), + result_vault.raindex().to_lowercase(), "0x2f209e5b67a33b8fe96e28f24628df6da301c8eb".to_string() ); assert_eq!(result_vault.formatted_balance(), "1".to_string()); @@ -271,11 +271,14 @@ mod tests { let vault_id_hex = derived_vault.id(); let vault_id_bytes = Bytes::from_str(&vault_id_hex).expect("valid vault id"); - let orderbook = + let raindex_addr = Address::from_str("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB").unwrap(); let data_source = LocalDbVaults::new(&local_db, Rc::new(client)); let retrieved = data_source - .get_by_id(&OrderbookIdentifier::new(42161, orderbook), &vault_id_bytes) + .get_by_id( + &RaindexIdentifier::new(42161, raindex_addr), + &vault_id_bytes, + ) .await .expect("local vault retrieval should succeed") .expect("vault should be found"); @@ -381,7 +384,7 @@ mod tests { owners: vec![Address::from_str(owner_kept).unwrap()], hide_zero_balance: true, tokens: Some(vec![Address::from_str(token_kept).unwrap()]), - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: false, }; @@ -442,7 +445,7 @@ mod tests { let token = LocalDbToken { chain_id: 42161, - orderbook_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), + raindex_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), token_address: address!("0x00000000000000000000000000000000000000aa"), name: "Test Token".to_string(), symbol: "TST".to_string(), @@ -481,7 +484,7 @@ mod tests { let token = LocalDbToken { chain_id: 42161, - orderbook_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), + raindex_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), token_address: address!("0x00000000000000000000000000000000000000aa"), name: "Test Token".to_string(), symbol: "TST".to_string(), @@ -519,7 +522,7 @@ mod tests { let token = LocalDbToken { chain_id: 42161, - orderbook_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), + raindex_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), token_address: address!("0x00000000000000000000000000000000000000aa"), name: "Test Token".to_string(), symbol: "TST".to_string(), @@ -558,7 +561,7 @@ mod tests { let owner = address!("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); let token = address!("0x00000000000000000000000000000000000000aa"); - let orderbook = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); + let raindex_addr = address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"); let vault_id = U256::from(1); let balance_change = LocalDbVaultBalanceChange { @@ -579,7 +582,7 @@ mod tests { vault_id, token, owner, - orderbook_address: orderbook, + raindex_address: raindex_addr, token_name: "Token".to_string(), token_symbol: "TKN".to_string(), token_decimals: 18, diff --git a/crates/common/src/raindex_client/mod.rs b/crates/common/src/raindex_client/mod.rs index 989c6d088a..3fe7e30b15 100644 --- a/crates/common/src/raindex_client/mod.rs +++ b/crates/common/src/raindex_client/mod.rs @@ -14,18 +14,18 @@ use alloy::{ }; pub(crate) use local_db::{ClassifiedChains, LocalDbState, QuerySource}; use rain_math_float::FloatError; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ network::NetworkCfg, remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, yaml::{ - orderbook::{OrderbookYaml, OrderbookYamlValidation}, + raindex::{RaindexYaml, RaindexYamlValidation}, YamlError, YamlParsable, }, }; -use rain_orderbook_subgraph_client::{ - types::order_detail_traits::OrderDetailError, MultiSubgraphArgs, OrderbookSubgraphClient, - OrderbookSubgraphClientError, +use raindex_subgraph_client::{ + types::order_detail_traits::OrderDetailError, MultiSubgraphArgs, RaindexSubgraphClient, + RaindexSubgraphClientError, }; use serde::{Deserialize, Serialize}; #[cfg(not(target_family = "wasm"))] @@ -47,9 +47,9 @@ use wasm_bindgen_utils::{impl_wasm_traits, prelude::*, wasm_export}; pub mod add_orders; pub mod local_db; pub mod order_quotes; -pub mod orderbook_yaml; pub mod orders; pub mod orders_list; +pub mod raindex_yaml; pub mod remove_orders; pub mod take_orders; pub mod trades; @@ -61,12 +61,12 @@ pub mod vaults_list; pub struct ChainIds(#[tsify(type = "number[]")] pub Vec); impl_wasm_traits!(ChainIds); -/// RaindexClient provides a simplified interface for querying orderbook data across +/// RaindexClient provides a simplified interface for querying raindex data across /// multiple networks with automatic configuration management. /// /// This client abstracts away complex network-specific configurations by parsing YAML -/// configuration files that define networks, tokens, orderbooks, and subgraph endpoints. -/// It enables querying orderbook data either from specific chains or across all +/// configuration files that define networks, tokens, raindexes, and subgraph endpoints. +/// It enables querying raindex data either from specific chains or across all /// configured networks with automatic fallback mechanisms. /// /// The client handles: @@ -96,7 +96,7 @@ impl_wasm_traits!(ChainIds); #[derive(Serialize, Deserialize, Debug, Clone)] #[wasm_bindgen] pub struct RaindexClient { - orderbook_yaml: OrderbookYaml, + raindex_yaml: RaindexYaml, #[serde(skip_serializing, skip_deserializing)] local_db_state: LocalDbState, } @@ -129,12 +129,12 @@ impl RaindexClient { )] pub async fn new( #[wasm_export( - js_name = "obYamls", + js_name = "raindexYamls", param_description = "List of YAML configuration strings. \ - The YAML files must match the [orderbook yaml spec](https://github.com/rainlanguage/specs/blob/main/ob-yaml.md) + The YAML files must match the [raindex yaml spec](https://github.com/rainlanguage/specs/blob/main/raindex-yaml.md) " )] - ob_yamls: Vec, + raindex_yamls: Vec, validate: Option, #[wasm_export( js_name = "queryCallback", @@ -152,16 +152,16 @@ impl RaindexClient { )] status_callback: Option, ) -> Result { - let mut orderbook_yaml = OrderbookYaml::new( - ob_yamls, + let mut raindex_yaml = RaindexYaml::new( + raindex_yamls, match validate { - Some(true) => OrderbookYamlValidation::full(), - _ => OrderbookYamlValidation::default(), + Some(true) => RaindexYamlValidation::full(), + _ => RaindexYamlValidation::default(), }, )?; - orderbook_yaml.fetch_remote_data().await?; + raindex_yaml.fetch_remote_data().await?; - let sync_configured_chains = LocalDbState::compute_chain_ids(&orderbook_yaml); + let sync_configured_chains = LocalDbState::compute_chain_ids(&raindex_yaml); let sync_readiness = SyncReadiness::new(); let has_syncs = !sync_configured_chains.is_empty(); @@ -179,7 +179,7 @@ impl RaindexClient { .expect("local_db should be set when has_syncs"); let settings = crate::local_db::pipeline::runner::utils::parse_runner_settings_from_yaml( - &orderbook_yaml, + &raindex_yaml, )?; let handle = crate::raindex_client::local_db::pipeline::runner::scheduler::start( settings, @@ -195,7 +195,7 @@ impl RaindexClient { let scheduler = Arc::new(std::sync::Mutex::new(None)); Ok(RaindexClient { - orderbook_yaml, + raindex_yaml, local_db_state: LocalDbState::new( local_db, scheduler, @@ -216,12 +216,12 @@ impl RaindexClient { Some(ids) if !ids.is_empty() => { let mut networks = Vec::with_capacity(ids.len()); for id in ids { - networks.push(self.orderbook_yaml.get_network_by_chain_id(id)?); + networks.push(self.raindex_yaml.get_network_by_chain_id(id)?); } Ok(networks) } Some(_) | None => { - let all_nets = self.orderbook_yaml.get_networks()?; + let all_nets = self.raindex_yaml.get_networks()?; let networks = all_nets.values().cloned().collect(); Ok(networks) } @@ -235,15 +235,15 @@ impl RaindexClient { let networks = self.resolve_networks(chain_ids)?; let mut result: BTreeMap> = BTreeMap::new(); for network in networks { - let orderbooks = self - .orderbook_yaml - .get_orderbooks_by_network_key(&network.key)?; - for orderbook in orderbooks { + let raindexes = self + .raindex_yaml + .get_raindexes_by_network_key(&network.key)?; + for raindex in raindexes { result .entry(network.chain_id) .or_default() .push(MultiSubgraphArgs { - url: orderbook.subgraph.url.clone(), + url: raindex.subgraph.url.clone(), name: network.label.clone().unwrap_or(network.key.clone()), }); } @@ -256,18 +256,16 @@ impl RaindexClient { } #[wasm_export(skip)] - pub fn get_orderbook_client( + pub fn get_raindex_subgraph_client( &self, - orderbook_address: Address, - ) -> Result { - let orderbook = self - .orderbook_yaml - .get_orderbook_by_address(orderbook_address)?; - Ok(OrderbookSubgraphClient::new(orderbook.subgraph.url.clone())) + raindex_address: Address, + ) -> Result { + let raindex = self.raindex_yaml.get_raindex_by_address(raindex_address)?; + Ok(RaindexSubgraphClient::new(raindex.subgraph.url.clone())) } fn get_rpc_urls_for_chain(&self, chain_id: u32) -> Result, RaindexError> { - let network = self.orderbook_yaml.get_network_by_chain_id(chain_id)?; + let network = self.raindex_yaml.get_network_by_chain_id(chain_id)?; Ok(network.rpcs.clone()) } @@ -287,20 +285,20 @@ impl RaindexClient { #[cfg(not(target_family = "wasm"))] impl RaindexClient { pub async fn new( - ob_yamls: Vec, + raindex_yamls: Vec, validate: Option, db_path: Option, ) -> Result { - let mut orderbook_yaml = OrderbookYaml::new( - ob_yamls, + let mut raindex_yaml = RaindexYaml::new( + raindex_yamls, match validate { - Some(true) => OrderbookYamlValidation::full(), - _ => OrderbookYamlValidation::default(), + Some(true) => RaindexYamlValidation::full(), + _ => RaindexYamlValidation::default(), }, )?; - orderbook_yaml.fetch_remote_data().await?; + raindex_yaml.fetch_remote_data().await?; - let sync_configured_chains = LocalDbState::compute_chain_ids(&orderbook_yaml); + let sync_configured_chains = LocalDbState::compute_chain_ids(&raindex_yaml); let sync_readiness = SyncReadiness::new(); let has_syncs = !sync_configured_chains.is_empty(); @@ -309,7 +307,7 @@ impl RaindexClient { db_path.ok_or_else(|| RaindexError::LocalDbSetupMissing("db_path".to_string()))?; let settings = crate::local_db::pipeline::runner::utils::parse_runner_settings_from_yaml( - &orderbook_yaml, + &raindex_yaml, )?; let handle = crate::raindex_client::local_db::pipeline::runner::scheduler::start( settings, @@ -323,7 +321,7 @@ impl RaindexClient { }; Ok(RaindexClient { - orderbook_yaml, + raindex_yaml, local_db_state: LocalDbState::new( local_db, Arc::new(std::sync::Mutex::new(scheduler)), @@ -382,7 +380,7 @@ pub enum RaindexError { #[error(transparent)] FromHexError(#[from] FromHexError), #[error(transparent)] - OrderbookSubgraphClientError(#[from] OrderbookSubgraphClientError), + RaindexSubgraphClientError(#[from] RaindexSubgraphClientError), #[error(transparent)] TryDecodeRainlangSourceError(#[from] TryDecodeRainlangSourceError), #[error(transparent)] @@ -405,8 +403,8 @@ pub enum RaindexError { WritableTransactionExecuteError(#[from] WritableTransactionExecuteError), #[error(transparent)] DepositArgsError(#[from] DepositError), - #[error("Orderbook not found for address: {0} on chain ID: {1}")] - OrderbookNotFound(String, u32), + #[error("Raindex not found for address: {0} on chain ID: {1}")] + RaindexNotFound(String, u32), #[error("Order not found for address: {0} on chain ID: {1} with hash: {2}")] OrderNotFound(String, u32, B256), #[error("Vault not found for address: {0} on chain ID: {1} with id: {2}")] @@ -416,7 +414,7 @@ pub enum RaindexError { #[error(transparent)] AddOrderArgsError(#[from] AddOrderArgsError), #[error(transparent)] - OrderbookQuoteError(#[from] rain_orderbook_quote::error::Error), + RaindexQuoteError(#[from] raindex_quote::error::Error), #[error("Missing subgraph {0} for order {1}")] SubgraphNotFound(String, String), #[error("Invalid vault balance change type: {0}")] @@ -537,7 +535,7 @@ impl RaindexError { err ) } - RaindexError::OrderbookSubgraphClientError(err) => { + RaindexError::RaindexSubgraphClientError(err) => { format!("Failed to query subgraph: {}. Check network connection and subgraph availability.", err) } RaindexError::TryDecodeRainlangSourceError(err) => { @@ -573,9 +571,9 @@ impl RaindexError { RaindexError::DepositArgsError(err) => { format!("Failed to create deposit arguments: {}", err) } - RaindexError::OrderbookNotFound(address, chain_id) => { + RaindexError::RaindexNotFound(address, chain_id) => { format!( - "Orderbook not found for address: {} on chain ID: {}", + "Raindex not found for address: {} on chain ID: {}", address, chain_id ) } @@ -595,7 +593,7 @@ impl RaindexError { RaindexError::AddOrderArgsError(e) => { format!("Failed to prepare the add order calldata: {}", e) } - RaindexError::OrderbookQuoteError(err) => { + RaindexError::RaindexQuoteError(err) => { format!("Failed to get order quote: {}", err) } RaindexError::SubgraphNotFound(subgraph, order) => { @@ -694,10 +692,10 @@ impl From for WasmEncodedError { #[cfg(test)] pub(crate) mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; #[cfg(not(target_family = "wasm"))] - pub const CHAIN_ID_1_ORDERBOOK_ADDRESS: &str = "0x1234567890123456789012345678901234567890"; + pub const CHAIN_ID_1_RAINDEX_ADDRESS: &str = "0x1234567890123456789012345678901234567890"; pub fn get_test_yaml(subgraph1: &str, subgraph2: &str, rpc1: &str, rpc2: &str) -> String { format!( r#" @@ -723,21 +721,21 @@ subgraphs: metaboards: mainnet: https://api.thegraph.com/subgraphs/name/xyz polygon: https://api.thegraph.com/subgraphs/name/polygon -orderbooks: - mainnet-orderbook: +raindexes: + mainnet-raindex: address: 0x1234567890123456789012345678901234567890 network: mainnet subgraph: mainnet local-db-remote: remote - label: Primary Orderbook + label: Primary Raindex deployment-block: 12345 - polygon-orderbook: + polygon-raindex: address: 0x0987654321098765432109876543210987654321 network: polygon subgraph: polygon local-db-remote: remote deployment-block: 12345 - label: Polygon Orderbook + label: Polygon Raindex tokens: weth: network: mainnet @@ -787,7 +785,7 @@ accounts: query_callback: js_sys::Function, chain_ids: Vec, ) -> RaindexClient { - let orderbook_yaml = OrderbookYaml::new(yamls, OrderbookYamlValidation::default()) + let raindex_yaml = RaindexYaml::new(yamls, RaindexYamlValidation::default()) .expect("test yaml should be valid"); let sync_readiness = SyncReadiness::new(); let mut db_chain_ids = std::collections::HashSet::new(); @@ -796,7 +794,7 @@ accounts: db_chain_ids.insert(id); } RaindexClient { - orderbook_yaml, + raindex_yaml, local_db_state: LocalDbState::new( Some(super::local_db::LocalDb::from_js_callback( query_callback, @@ -913,7 +911,7 @@ using-tokens-from: let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); - let tokens = client.orderbook_yaml.get_tokens().unwrap(); + let tokens = client.raindex_yaml.get_tokens().unwrap(); let expected_key = "test-network-RemoteToken-0x0000000000000000000000000000000000000001"; assert!(tokens.contains_key(expected_key)); @@ -946,8 +944,8 @@ subgraphs: arbitrum: https://arb.subgraph metaboards: arbitrum: https://arb.metaboard -orderbooks: - arbitrum-orderbook: +raindexes: + arbitrum-raindex: address: 0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB network: arbitrum subgraph: arbitrum @@ -980,7 +978,7 @@ accounts: #[cfg(target_family = "wasm")] mod wasm_tests { use super::*; - use rain_orderbook_app_settings::yaml::YamlError; + use raindex_app_settings::yaml::YamlError; use url::Url; use wasm_bindgen_test::wasm_bindgen_test; @@ -993,8 +991,8 @@ accounts: rpcs: - https://mainnet.infura.io chain-id: 1 - orderbooks: - invalid-orderbook: + raindexes: + invalid-raindex: address: 0x1234567890123456789012345678901234567890 network: nonexistent-network subgraph: nonexistent-subgraph @@ -1019,7 +1017,7 @@ accounts: ) .await .unwrap(); - assert!(!client.orderbook_yaml.documents.is_empty()); + assert!(!client.raindex_yaml.documents.is_empty()); } #[wasm_bindgen_test] @@ -1211,13 +1209,13 @@ accounts: test-rainlang: address: 0x2222222222222222222222222222222222222222 network: isolated - orderbooks: - test-orderbook: + raindexes: + test-raindex: address: 0x1111111111111111111111111111111111111111 network: some-network subgraph: test local-db-remote: remote - label: Test Orderbook + label: Test Raindex deployment-block: 12345 "#, spec_version = SpecVersion::current() @@ -1230,11 +1228,11 @@ accounts: let err = client.get_multi_subgraph_args(None).unwrap_err(); assert!(matches!( err, - RaindexError::YamlError(YamlError::NotFound(ref msg)) if msg.contains("orderbook with network key: isolated") + RaindexError::YamlError(YamlError::NotFound(ref msg)) if msg.contains("raindex with network key: isolated") )); assert!(err .to_readable_msg() - .contains("orderbook with network key: isolated not found")); + .contains("raindex with network key: isolated not found")); } } } diff --git a/crates/common/src/raindex_client/order_quotes.rs b/crates/common/src/raindex_client/order_quotes.rs index 2f4720bf1b..e7dabd7d59 100644 --- a/crates/common/src/raindex_client/order_quotes.rs +++ b/crates/common/src/raindex_client/order_quotes.rs @@ -2,9 +2,9 @@ use super::*; use crate::raindex_client::orders::RaindexOrder; use crate::raindex_client::orders_list::RaindexOrders; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::OrderV4; -use rain_orderbook_quote::{get_order_quotes, BatchOrderQuotesResponse, OrderQuoteValue, Pair}; -use rain_orderbook_subgraph_client::utils::float::{F0, F1}; +use raindex_bindings::IRaindexV6::OrderV4; +use raindex_quote::{get_order_quotes, BatchOrderQuotesResponse, OrderQuoteValue, Pair}; +use raindex_subgraph_client::utils::float::{F0, F1}; use std::ops::{Div, Mul}; #[derive(Serialize, Deserialize, Debug, Clone, Tsify)] @@ -268,14 +268,14 @@ mod tests { #[cfg(not(target_family = "wasm"))] mod quote_non_wasm_tests { use super::*; - use crate::local_db::OrderbookIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::local_db::RaindexIdentifier; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::hex::encode_prefixed; use alloy::primitives::{b256, Address, U256}; use alloy::{sol, sol_types::SolValue}; use httpmock::MockServer; use rain_math_float::Float; - use rain_orderbook_subgraph_client::utils::float::{F0_5, F2}; + use raindex_subgraph_client::utils::float::{F0_5, F2}; use serde_json::{json, Value}; sol!( @@ -311,8 +311,8 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], @@ -332,16 +332,16 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }, ], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -408,9 +408,9 @@ mod tests { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -508,9 +508,9 @@ mod tests { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -576,9 +576,9 @@ mod tests { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -669,9 +669,9 @@ mod tests { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) diff --git a/crates/common/src/raindex_client/orders.rs b/crates/common/src/raindex_client/orders.rs index c184c1f6c0..2662766bca 100644 --- a/crates/common/src/raindex_client/orders.rs +++ b/crates/common/src/raindex_client/orders.rs @@ -6,7 +6,7 @@ use super::QuerySource; use super::*; use crate::local_db::query::fetch_orders::LocalDbOrder; use crate::local_db::query::fetch_vaults::LocalDbVault; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use crate::parsed_meta::ParsedMeta; use crate::raindex_client::order_quotes::RaindexOrderQuote; use crate::raindex_client::take_orders::single::{RpcContext, TakeOrderExecutionParams}; @@ -33,15 +33,15 @@ use rain_metaboard_subgraph::metaboard_client::MetaboardSubgraphClient; use rain_metaboard_subgraph::types::metas::BigInt as MetaBigInt; use rain_metadata::types::dotrain::source_v1::DotrainSourceV1; use rain_metadata::{KnownMagic, RainMetaDocumentV1Item}; -use rain_orderbook_subgraph_client::{ +use raindex_subgraph_client::{ types::{ common::{ - SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgOrderbook, SgOrdersListFilterArgs, - SgOrdersTokensFilterArgs, SgVault, + SgBigInt, SgBytes, SgOrder, SgOrderAsIO, SgOrdersListFilterArgs, + SgOrdersTokensFilterArgs, SgRaindex, SgVault, }, Id, }, - MultiOrderbookSubgraphClient, OrderbookSubgraphClient, OrderbookSubgraphClientError, + MultiRaindexSubgraphClient, RaindexSubgraphClient, RaindexSubgraphClientError, SgPaginationArgs, }; use serde::{Deserialize, Serialize}; @@ -109,27 +109,27 @@ pub(crate) trait OrdersDataSource { async fn get_by_hash( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, ) -> Result, RaindexError>; async fn get_added_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError>; async fn get_removed_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError>; async fn trades_list( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, @@ -138,18 +138,18 @@ pub(crate) trait OrdersDataSource { async fn trades_count( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, ) -> Result; } -/// A single order representation within a given orderbook. +/// A single order representation within a given raindex. /// /// RaindexOrder represents a trading order on a specific blockchain with its associated /// input and output vaults, metadata, and performance tracking capabilities. Each order -/// is deployed on a specific orderbook contract and can be queried for volume and +/// is deployed on a specific raindex contract and can be queried for volume and /// performance metrics over time. /// /// The order contains both the raw order data (bytes and hash) and structured access @@ -166,7 +166,7 @@ pub struct RaindexOrder { owner: Address, inputs: Vec, outputs: Vec, - orderbook: Address, + raindex: Address, active: bool, timestamp_added: U256, meta: Option, @@ -197,7 +197,7 @@ impl RaindexOrder { .as_ref() .and_then(|meta| meta.to_string().try_decode_rainlangsource().ok()); - let mut id = Vec::from(order.orderbook_address.as_slice()); + let mut id = Vec::from(order.raindex_address.as_slice()); id.extend_from_slice(order.order_hash.as_ref()); Ok(Self { @@ -227,7 +227,7 @@ impl RaindexOrder { ) }) .collect::, RaindexError>>()?, - orderbook: order.orderbook_address, + raindex: order.raindex_address, active: order.active, timestamp_added: U256::from(order.block_timestamp), meta: order.meta.clone(), @@ -272,8 +272,8 @@ impl RaindexOrder { self.owner.to_string() } #[wasm_bindgen(getter, unchecked_return_type = "Address")] - pub fn orderbook(&self) -> String { - self.orderbook.to_string() + pub fn raindex(&self) -> String { + self.raindex.to_string() } #[wasm_bindgen(getter)] pub fn active(&self) -> bool { @@ -364,8 +364,8 @@ impl RaindexOrder { pub fn owner(&self) -> Address { self.owner } - pub fn orderbook(&self) -> Address { - self.orderbook + pub fn raindex(&self) -> Address { + self.raindex } pub fn active(&self) -> bool { self.active @@ -462,8 +462,9 @@ impl RaindexOrder { ClientRef::clone(&self.raindex_client) } #[wasm_export(skip)] - pub fn get_orderbook_client(&self) -> Result { - self.raindex_client.get_orderbook_client(self.orderbook) + pub fn get_raindex_subgraph_client(&self) -> Result { + self.raindex_client + .get_raindex_subgraph_client(self.raindex) } #[wasm_export(skip)] pub fn get_rpc_urls(&self) -> Result, RaindexError> { @@ -473,9 +474,9 @@ impl RaindexOrder { pub fn get_metaboard_client(&self) -> Result, RaindexError> { let raindex_client = self.get_raindex_client(); let network = raindex_client - .orderbook_yaml + .raindex_yaml .get_network_by_chain_id(self.chain_id)?; - let metaboard = match raindex_client.orderbook_yaml.get_metaboard(&network.key) { + let metaboard = match raindex_client.raindex_yaml.get_metaboard(&network.key) { Ok(metaboard) => metaboard, Err(YamlError::KeyNotFound(_) | YamlError::NotFound(_)) => return Ok(None), Err(err) => return Err(err.into()), @@ -504,9 +505,9 @@ impl RaindexOrder { ) -> Result, RaindexError> { let chain_id = self.chain_id(); #[cfg(target_family = "wasm")] - let orderbook = Address::from_str(&self.orderbook())?; + let raindex_addr = Address::from_str(&self.raindex())?; #[cfg(not(target_family = "wasm"))] - let orderbook = self.orderbook(); + let raindex_addr = self.raindex(); let raindex_client = self.get_raindex_client(); match raindex_client.query_source(chain_id) { @@ -518,7 +519,7 @@ impl RaindexOrder { let volumes = fetch_order_vaults_volume( &local_db, - &OrderbookIdentifier::new(chain_id, orderbook), + &RaindexIdentifier::new(chain_id, raindex_addr), order_hash, start_timestamp, end_timestamp, @@ -531,7 +532,7 @@ impl RaindexOrder { .collect() } QuerySource::Subgraph => { - let client = self.get_orderbook_client()?; + let client = self.get_raindex_subgraph_client()?; let volumes = client .order_vaults_volume( Id::new(self.id.to_string()), @@ -584,7 +585,7 @@ impl RaindexOrder { // )] // end_timestamp: Option, // ) -> Result { - // let client = self.get_orderbook_client()?; + // let client = self.get_raindex_subgraph_client()?; // let performance = client // .order_performance(Id::new(self.id.to_string()), start_timestamp, end_timestamp) // .await?; @@ -645,7 +646,7 @@ impl RaindexOrder { /// if (res.error) { /// console.error(res.error.readableMsg); /// } else { - /// const { calldata, effectivePrice, expectedSell, maxSellCap, prices, orderbook } = res.value; + /// const { calldata, effectivePrice, expectedSell, maxSellCap, prices, raindex } = res.value; /// } /// ``` #[wasm_export( @@ -970,11 +971,11 @@ impl RaindexClient { )] chain_id: u32, #[wasm_export( - js_name = "orderbookAddress", - param_description = "Orderbook contract address", + js_name = "raindexAddress", + param_description = "Raindex contract address", unchecked_param_type = "Address" )] - orderbook_address: String, + raindex_address: String, #[wasm_export( js_name = "orderHash", param_description = "The unique hash identifier of the order", @@ -982,10 +983,10 @@ impl RaindexClient { )] order_hash: String, ) -> Result { - let orderbook_address = Address::from_str(&orderbook_address)?; + let raindex_address = Address::from_str(&raindex_address)?; let order_hash = B256::from_str(&order_hash)?; self.get_order_by_hash( - &OrderbookIdentifier::new(chain_id, orderbook_address), + &RaindexIdentifier::new(chain_id, raindex_address), order_hash, ) .await @@ -1005,7 +1006,7 @@ impl OrdersDataSource for SubgraphOrders<'_> { let raindex_client = ClientRef::new(self.client.clone()); let multi_subgraph_args = self.client.get_multi_subgraph_args(chain_ids)?; - let client = MultiOrderbookSubgraphClient::new( + let client = MultiRaindexSubgraphClient::new( multi_subgraph_args.values().flatten().cloned().collect(), ); @@ -1056,31 +1057,34 @@ impl OrdersDataSource for SubgraphOrders<'_> { async fn get_by_hash( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_orderbook_client(ob_id.orderbook_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = match client .order_detail_by_hash(SgBytes(order_hash.to_string())) .await { Ok(order) => order, - Err(OrderbookSubgraphClientError::Empty) => return Ok(None), + Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; - let order = RaindexOrder::try_from_sg_order(raindex_client, ob_id.chain_id, order, None)?; + let order = + RaindexOrder::try_from_sg_order(raindex_client, raindex_id.chain_id, order, None)?; Ok(Some(order)) } async fn get_added_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_orderbook_client(orderbook)?; + let client = self.client.get_raindex_subgraph_client(raindex)?; let sg_orders = client .transaction_add_orders(Id::new(tx_hash.to_string())) .await?; @@ -1101,11 +1105,11 @@ impl OrdersDataSource for SubgraphOrders<'_> { async fn get_removed_by_tx_hash( &self, chain_id: u32, - orderbook: Address, + raindex: Address, tx_hash: B256, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_orderbook_client(orderbook)?; + let client = self.client.get_raindex_subgraph_client(raindex)?; let sg_orders = client .transaction_remove_orders(Id::new(tx_hash.to_string())) .await?; @@ -1125,13 +1129,15 @@ impl OrdersDataSource for SubgraphOrders<'_> { async fn trades_list( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, page: Option, ) -> Result, RaindexError> { - let client = self.client.get_orderbook_client(ob_id.orderbook_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = client .order_detail_by_hash(SgBytes(order_hash.to_string())) @@ -1151,18 +1157,20 @@ impl OrdersDataSource for SubgraphOrders<'_> { trades .into_iter() - .map(|trade| RaindexTrade::try_from_sg_trade(ob_id.chain_id, trade)) + .map(|trade| RaindexTrade::try_from_sg_trade(raindex_id.chain_id, trade)) .collect() } async fn trades_count( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: &B256, start_timestamp: Option, end_timestamp: Option, ) -> Result { - let client = self.client.get_orderbook_client(ob_id.orderbook_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let order = client .order_detail_by_hash(SgBytes(order_hash.to_string())) @@ -1179,27 +1187,27 @@ impl OrdersDataSource for SubgraphOrders<'_> { impl RaindexClient { pub async fn get_order_by_hash( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, order_hash: B256, ) -> Result { - let orderbook_cfg = self.get_orderbook_by_address(ob_id.orderbook_address)?; - if orderbook_cfg.network.chain_id != ob_id.chain_id { - return Err(RaindexError::OrderbookNotFound( - ob_id.orderbook_address.to_string(), - ob_id.chain_id, + let raindex_cfg = self.get_raindex_by_address(raindex_id.raindex_address)?; + if raindex_cfg.network.chain_id != raindex_id.chain_id { + return Err(RaindexError::RaindexNotFound( + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, )); } - match self.query_source(ob_id.chain_id) { + match self.query_source(raindex_id.chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::new(self.clone())); let mut order = local_source - .get_by_hash(ob_id, &order_hash) + .get_by_hash(raindex_id, &order_hash) .await? .ok_or_else(|| { RaindexError::OrderNotFound( - ob_id.orderbook_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, order_hash, ) })?; @@ -1208,12 +1216,12 @@ impl RaindexClient { } QuerySource::Subgraph => { let mut order = SubgraphOrders::new(self) - .get_by_hash(ob_id, &order_hash) + .get_by_hash(raindex_id, &order_hash) .await? .ok_or_else(|| { RaindexError::OrderNotFound( - ob_id.orderbook_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, order_hash, ) })?; @@ -1239,7 +1247,7 @@ impl RaindexClient { inputs: Some(vec![sell_token]), outputs: Some(vec![buy_token]), }), - orderbook_addresses: None, + raindex_addresses: None, }; let ids = Some(vec![chain_id]); @@ -1283,7 +1291,7 @@ pub struct GetOrdersFilters { #[tsify(optional)] pub tokens: Option, #[tsify(optional, type = "Address[]")] - pub orderbook_addresses: Option>, + pub raindex_addresses: Option>, } impl_wasm_traits!(GetOrdersFilters); @@ -1328,8 +1336,8 @@ impl TryFrom for SgOrdersListFilterArgs { .order_hash .map(|order_hash| SgBytes(order_hash.to_string())), tokens: tokens.flatten(), - orderbooks: filters - .orderbook_addresses + raindexes: filters + .raindex_addresses .map(|addrs| { addrs .into_iter() @@ -1442,7 +1450,7 @@ impl RaindexOrder { }) .collect::, RaindexError>>()? }, - orderbook: Address::from_str(&order.orderbook.id.0)?, + raindex: Address::from_str(&order.raindex.id.0)?, active: order.active, timestamp_added: U256::from_str(&order.timestamp_added.0)?, meta: order @@ -1485,8 +1493,8 @@ impl RaindexOrder { .into_iter() .map(|v| v.into_sg_vault()) .collect::, RaindexError>>()?, - orderbook: SgOrderbook { - id: SgBytes(self.orderbook().to_string()), + raindex: SgRaindex { + id: SgBytes(self.raindex().to_string()), }, active: self.active(), timestamp_added: SgBigInt(timestamp_added), @@ -1517,7 +1525,7 @@ mod tests { mod non_wasm { use super::super::*; use crate::raindex_client::tests::{ - get_test_yaml, new_with_local_db, CHAIN_ID_1_ORDERBOOK_ADDRESS, + get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS, }; use crate::{ local_db::query::{ @@ -1536,11 +1544,10 @@ mod tests { use rain_metadata::{ ContentEncoding, ContentLanguage, ContentType, KnownMagic, RainMetaDocumentV1Item, }; - use rain_orderbook_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgTransaction, - SgVault, + use raindex_subgraph_client::types::common::{ + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTransaction, SgVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_bytes::ByteBuf; use serde_json::{json, Value}; use std::collections::BTreeMap; @@ -1655,7 +1662,7 @@ mod tests { owner: address!("0x0000000000000000000000000000000000000001"), block_timestamp: 1, block_number: 1, - orderbook_address: Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + raindex_address: Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), order_bytes: Bytes::from_str("0x01").unwrap(), transaction_hash: b256!( "0000000000000000000000000000000000000000000000000000000000000002" @@ -1956,16 +1963,16 @@ mod tests { } #[test] - fn get_orders_filters_to_sg_filter_args_maps_orderbook_addresses() { + fn get_orders_filters_to_sg_filter_args_maps_raindex_addresses() { use alloy::primitives::address; - use rain_orderbook_subgraph_client::types::common::SgOrdersListFilterArgs; + use raindex_subgraph_client::types::common::SgOrdersListFilterArgs; let filters = GetOrdersFilters { owners: vec![], active: None, order_hash: None, tokens: None, - orderbook_addresses: Some(vec![ + raindex_addresses: Some(vec![ address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"), ]), @@ -1973,54 +1980,54 @@ mod tests { let sg_filter_args: SgOrdersListFilterArgs = filters.try_into().unwrap(); - assert_eq!(sg_filter_args.orderbooks.len(), 2); + assert_eq!(sg_filter_args.raindexes.len(), 2); assert_eq!( - sg_filter_args.orderbooks[0], + sg_filter_args.raindexes[0], "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); assert_eq!( - sg_filter_args.orderbooks[1], + sg_filter_args.raindexes[1], "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); } #[test] - fn get_orders_filters_to_sg_filter_args_empty_orderbook_addresses() { - use rain_orderbook_subgraph_client::types::common::SgOrdersListFilterArgs; + fn get_orders_filters_to_sg_filter_args_empty_raindex_addresses() { + use raindex_subgraph_client::types::common::SgOrdersListFilterArgs; let filters = GetOrdersFilters { owners: vec![], active: None, order_hash: None, tokens: None, - orderbook_addresses: None, + raindex_addresses: None, }; let sg_filter_args: SgOrdersListFilterArgs = filters.try_into().unwrap(); - assert!(sg_filter_args.orderbooks.is_empty()); + assert!(sg_filter_args.raindexes.is_empty()); } #[test] fn get_orders_filters_to_sg_filter_args_lowercases_mixed_case_addresses() { use alloy::primitives::address; - use rain_orderbook_subgraph_client::types::common::SgOrdersListFilterArgs; + use raindex_subgraph_client::types::common::SgOrdersListFilterArgs; let filters = GetOrdersFilters { owners: vec![], active: None, order_hash: None, tokens: None, - orderbook_addresses: Some(vec![address!( + raindex_addresses: Some(vec![address!( "0xDeaDbEEfDeaDbEEfDeaDbEEfDeaDbEEfDeaDbEEf" )]), }; let sg_filter_args: SgOrdersListFilterArgs = filters.try_into().unwrap(); - assert_eq!(sg_filter_args.orderbooks.len(), 1); + assert_eq!(sg_filter_args.raindexes.len(), 1); assert_eq!( - sg_filter_args.orderbooks[0], + sg_filter_args.raindexes[0], "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ); } @@ -2044,7 +2051,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -2072,7 +2079,7 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -2090,7 +2097,7 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -2118,13 +2125,13 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } ], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -2162,7 +2169,7 @@ mod tests { symbol: Some("sFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![SgOrderAsIO { @@ -2188,7 +2195,7 @@ mod tests { orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0x0000000000000000000000000000000000000000".to_string()), } }], @@ -2204,7 +2211,7 @@ mod tests { symbol: Some("WFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![], @@ -2230,12 +2237,12 @@ mod tests { orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0x0000000000000000000000000000000000000000".to_string()), } }], - orderbook: SgOrderbook { - id: SgBytes(CHAIN_ID_1_ORDERBOOK_ADDRESS.to_string()), + raindex: SgRaindex { + id: SgBytes(CHAIN_ID_1_RAINDEX_ADDRESS.to_string()), }, active: true, timestamp_added: SgBigInt("1739448802".to_string()), @@ -2293,7 +2300,7 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -2314,7 +2321,7 @@ mod tests { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -2332,7 +2339,7 @@ mod tests { ], "meta": null, "timestampAdded": "0", - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "trades": [], @@ -2348,7 +2355,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbook_addresses: None, + raindex_addresses: None, }; let raindex_client = RaindexClient::new( vec![get_test_yaml( @@ -2406,7 +2413,7 @@ mod tests { order1_output.token().decimals(), expected_output.token().decimals() ); - assert_eq!(order1_output.orderbook(), expected_output.orderbook()); + assert_eq!(order1_output.raindex(), expected_output.raindex()); } assert_eq!(order1.inputs.len(), expected_order1.inputs.len()); for (order1_input, expected_input) in @@ -2429,10 +2436,10 @@ mod tests { order1_input.token().decimals(), expected_input.token().decimals() ); - assert_eq!(order1_input.orderbook(), expected_input.orderbook()); + assert_eq!(order1_input.raindex(), expected_input.raindex()); } - assert_eq!(order1.orderbook(), expected_order1.orderbook()); + assert_eq!(order1.raindex(), expected_order1.raindex()); assert_eq!(order1.timestamp_added(), expected_order1.timestamp_added()); let order2 = result.orders()[1].clone(); @@ -2479,7 +2486,7 @@ mod tests { assert_eq!(order2_outputs.token().symbol(), Some("T1".to_string())); assert_eq!(order2_outputs.token().decimals(), 0); assert_eq!( - order2_outputs.orderbook(), + order2_outputs.raindex(), Address::from_str("0x0000000000000000000000000000000000000000").unwrap() ); @@ -2506,11 +2513,11 @@ mod tests { assert_eq!(order2_inputs.token().symbol(), Some("T2".to_string())); assert_eq!(order2_inputs.token().decimals(), 0); assert_eq!( - order2_inputs.orderbook(), + order2_inputs.raindex(), Address::from_str("0x0000000000000000000000000000000000000000").unwrap() ); assert_eq!( - order2.orderbook(), + order2.raindex(), Address::from_str("0x0000000000000000000000000000000000000000").unwrap() ); assert_eq!(order2.timestamp_added(), U256::from(0)); @@ -2543,9 +2550,9 @@ mod tests { .unwrap(); let res = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -2613,9 +2620,9 @@ mod tests { b256!("0x0000000000000000000000000000000000000000000000000000000000000123"); let res = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), order_hash, ) @@ -2623,7 +2630,7 @@ mod tests { match res { Err(RaindexError::OrderNotFound(address, chain_id, hash)) => { - assert_eq!(address, CHAIN_ID_1_ORDERBOOK_ADDRESS.to_string()); + assert_eq!(address, CHAIN_ID_1_RAINDEX_ADDRESS.to_string()); assert_eq!(chain_id, 1); assert_eq!(hash, order_hash); } @@ -2647,8 +2654,8 @@ mod tests { "owner": "0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11", "outputs": [], "inputs": [], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -2677,9 +2684,9 @@ mod tests { .unwrap(); let res = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -2714,9 +2721,9 @@ mod tests { .unwrap(); let res = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -2729,7 +2736,7 @@ mod tests { #[tokio::test] async fn local_db_orders_parse_ios() { - let local_orderbook = "0x0987654321098765432109876543210987654321"; + let local_raindex = "0x0987654321098765432109876543210987654321"; let owner = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; let token = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"; let inputs_payload = serde_json::to_string(&vec![json!({ @@ -2739,7 +2746,7 @@ mod tests { "vaultId": "0x01", "token": token, "owner": owner, - "orderbookAddress": local_orderbook, + "raindexAddress": local_raindex, "tokenName": "USDC", "tokenSymbol": "USDC", "tokenDecimals": 6, @@ -2756,7 +2763,7 @@ mod tests { "vaultId": "0x02", "token": token, "owner": owner, - "orderbookAddress": local_orderbook, + "raindexAddress": local_raindex, "tokenName": "USDC", "tokenSymbol": "USDC", "tokenDecimals": 6, @@ -2775,7 +2782,7 @@ mod tests { owner: Address::from_str(owner).unwrap(), block_timestamp: 1, block_number: 1, - orderbook_address: Address::from_str(local_orderbook).unwrap(), + raindex_address: Address::from_str(local_raindex).unwrap(), order_bytes: Bytes::from_str("0x01").unwrap(), transaction_hash: b256!( "0x0000000000000000000000000000000000000000000000000000000000000010" @@ -2814,7 +2821,7 @@ mod tests { assert_eq!(order.inputs.len(), 1); assert_eq!(order.outputs.len(), 1); assert_eq!(order.trades_count, 2); - assert_eq!(order.orderbook, Address::from_str(local_orderbook).unwrap()); + assert_eq!(order.raindex, Address::from_str(local_raindex).unwrap()); } #[tokio::test] @@ -2874,7 +2881,7 @@ mod tests { ], "meta": null, "timestampAdded": "0", - "orderbook": { + "raindex": { "id": "0x0987654321098765432109876543210987654321" }, "trades": [], @@ -2924,7 +2931,7 @@ mod tests { owner: Address::from_str("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(), block_timestamp: 1, block_number: 1, - orderbook_address: Address::from_str("0x0987654321098765432109876543210987654321") + raindex_address: Address::from_str("0x0987654321098765432109876543210987654321") .unwrap(), order_bytes: Bytes::from_str("0x01").unwrap(), transaction_hash: b256!( @@ -2956,7 +2963,7 @@ mod tests { let order = client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 137, Address::from_str("0x0987654321098765432109876543210987654321").unwrap(), ), @@ -2991,8 +2998,8 @@ mod tests { "id": "0x557147dd0daa80d5beff0023fe6a3505469b2b8c4406ce1ab873e1a652572dd4", "orderHash": "0x557147dd0daa80d5beff0023fe6a3505469b2b8c4406ce1ab873e1a652572dd4" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "inputVaultBalanceChange": { "id": "input-change-1", @@ -3007,7 +3014,7 @@ mod tests { "timestamp": "1632000000", "blockNumber": "0" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "vault": { "id": "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d", "vaultId": "0x1234", @@ -3038,7 +3045,7 @@ mod tests { "timestamp": "1632000000", "blockNumber": "0" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "vault": { "id": "0x12e605bc104e93b45e1ad99f9e555f659051c2bb", "vaultId": "0x5678", @@ -3109,9 +3116,9 @@ mod tests { let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x557147dd0daa80d5beff0023fe6a3505469b2b8c4406ce1ab873e1a652572dd4"), ) @@ -3347,7 +3354,7 @@ mod tests { use crate::take_orders::TakeOrdersMode; use alloy::primitives::{Address, Bytes}; use rain_math_float::Float; - use rain_orderbook_quote::Pair; + use raindex_quote::Pair; use std::ops::Mul; use wasm_bindgen_test::wasm_bindgen_test; use wasm_bindgen_utils::prelude::{from_js_value, to_js_value}; @@ -3386,7 +3393,7 @@ mod tests { fn make_test_calldata_result() -> TakeOrdersCalldataResult { use crate::raindex_client::take_orders::result::TakeOrdersInfoData; - let orderbook = Address::from([0x11u8; 20]); + let raindex = Address::from([0x11u8; 20]); let calldata = Bytes::from(vec![0x01, 0x02, 0x03, 0x04]); let effective_price = Float::parse("1.5".to_string()).unwrap(); let prices = vec![ @@ -3397,7 +3404,7 @@ mod tests { let max_sell_cap = Float::parse("200".to_string()).unwrap(); TakeOrdersCalldataResult::ready(TakeOrdersInfoData { - orderbook, + raindex, calldata, effective_price, prices, @@ -3463,7 +3470,7 @@ mod tests { let roundtrip: crate::raindex_client::take_orders::TakeOrdersInfo = from_js_value(js_value).expect("Should deserialize TakeOrdersInfo from JS"); - assert_eq!(roundtrip.orderbook(), result_info.orderbook()); + assert_eq!(roundtrip.raindex(), result_info.raindex()); assert_eq!(roundtrip.calldata(), result_info.calldata()); assert!(roundtrip .effective_price() diff --git a/crates/common/src/raindex_client/orders_list.rs b/crates/common/src/raindex_client/orders_list.rs index 987ab92dd3..1e0dfba056 100644 --- a/crates/common/src/raindex_client/orders_list.rs +++ b/crates/common/src/raindex_client/orders_list.rs @@ -50,8 +50,8 @@ impl RaindexOrders { #[cfg(not(target_family = "wasm"))] mod tests { use super::*; - use crate::local_db::OrderbookIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::local_db::RaindexIdentifier; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::{b256, Address}; use httpmock::MockServer; use serde_json::json; @@ -78,7 +78,7 @@ mod tests { "address": "0x12e605bc104e93b45e1ad99f9e555f659051c2bb", "name": "sFLR", "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], "inputs": [{ @@ -91,10 +91,10 @@ mod tests { "address": "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d", "name": "WFLR", "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "0", "meta": null, "addEvents": [], "trades": [], "removeEvents": [] }] @@ -116,10 +116,7 @@ mod tests { .unwrap(); client .get_order_by_hash( - &OrderbookIdentifier::new( - 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), - ), + &RaindexIdentifier::new(1, Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap()), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) .await diff --git a/crates/common/src/raindex_client/orderbook_yaml.rs b/crates/common/src/raindex_client/raindex_yaml.rs similarity index 78% rename from crates/common/src/raindex_client/orderbook_yaml.rs rename to crates/common/src/raindex_client/raindex_yaml.rs index a83bdbf177..55825faf4c 100644 --- a/crates/common/src/raindex_client/orderbook_yaml.rs +++ b/crates/common/src/raindex_client/raindex_yaml.rs @@ -1,6 +1,6 @@ use super::*; -use rain_orderbook_app_settings::{ - accounts::AccountCfg, network::NetworkCfg, orderbook::OrderbookCfg, token::TokenCfg, +use raindex_app_settings::{ + accounts::AccountCfg, network::NetworkCfg, raindex::RaindexCfg, token::TokenCfg, }; use std::collections::{HashMap, HashSet}; @@ -9,7 +9,7 @@ impl RaindexClient { /// Retrieves a list of unique chain IDs from all configured networks /// /// Extracts and returns all unique blockchain network chain IDs that are available - /// in the current orderbook configuration. + /// in the current raindex configuration. /// /// ## Examples /// @@ -35,7 +35,7 @@ impl RaindexClient { /// Retrieves all available networks with their configurations /// - /// Returns a comprehensive map of all network configurations available in the orderbook YAML. + /// Returns a comprehensive map of all network configurations available in the raindex YAML. /// Each entry contains detailed network information including RPC endpoints and chain-specific settings. /// /// ## Examples @@ -57,7 +57,7 @@ impl RaindexClient { unchecked_return_type = "Map" )] pub fn get_all_networks(&self) -> Result, RaindexError> { - Ok(self.orderbook_yaml.get_networks()?) + Ok(self.raindex_yaml.get_networks()?) } /// Retrieves network configuration for a specific chain ID @@ -89,40 +89,40 @@ impl RaindexClient { )] chain_id: u32, ) -> Result { - Ok(self.orderbook_yaml.get_network_by_chain_id(chain_id)?) + Ok(self.raindex_yaml.get_network_by_chain_id(chain_id)?) } - /// Retrieves orderbook configuration by contract address + /// Retrieves raindex configuration by contract address /// - /// Finds and returns the orderbook configuration that matches the provided contract address. - /// This allows you to access orderbook-specific settings including subgraph endpoints, + /// Finds and returns the raindex configuration that matches the provided contract address. + /// This allows you to access raindex-specific settings including subgraph endpoints, /// network information, and other details. /// /// ## Examples /// /// ```javascript - /// const result = client.getOrderbookByAddress("0x1234567890123456789012345678901234567890"); + /// const result = client.getRaindexByAddress("0x1234567890123456789012345678901234567890"); /// if (result.error) { - /// console.error("Orderbook not found:", result.error.readableMsg); + /// console.error("Raindex not found:", result.error.readableMsg); /// return; /// } - /// const orderbookConfig = result.value; - /// console.log(`Found orderbook ${orderbookConfig}`); + /// const raindexConfig = result.value; + /// console.log(`Found raindex ${raindexConfig}`); /// ``` #[wasm_export( - js_name = "getOrderbookByAddress", - return_description = "Returns the configuration for a specific orderbook identified by its address", - unchecked_return_type = "OrderbookCfg" + js_name = "getRaindexByAddress", + return_description = "Returns the configuration for a specific raindex identified by its address", + unchecked_return_type = "RaindexCfg" )] - pub fn get_orderbook_by_address_wasm_binding( + pub fn get_raindex_by_address_wasm_binding( &self, #[wasm_export( - param_description = "The address of the orderbook to retrieve the configuration for" + param_description = "The address of the raindex to retrieve the configuration for" )] address: String, - ) -> Result { + ) -> Result { let address = Address::from_str(&address)?; - Ok(self.orderbook_yaml.get_orderbook_by_address(address)?) + Ok(self.raindex_yaml.get_raindex_by_address(address)?) } /// Checks if Sentry error tracking is enabled in the YAML configuration @@ -145,11 +145,11 @@ impl RaindexClient { unchecked_return_type = "boolean" )] pub fn is_sentry_enabled(&self) -> Result { - let sentry = self.orderbook_yaml.get_sentry()?; + let sentry = self.raindex_yaml.get_sentry()?; Ok(sentry.unwrap_or(false)) } - /// Retrieves all accounts from the orderbook YAML configuration + /// Retrieves all accounts from the raindex YAML configuration /// /// Returns a map of account configurations where the keys are account names /// and the values are `AccountCfg` objects containing account details. @@ -169,41 +169,41 @@ impl RaindexClient { /// ``` #[wasm_export( js_name = "getAllAccounts", - return_description = "Returns the list of accounts from the orderbook YAML configuration.", + return_description = "Returns the list of accounts from the raindex YAML configuration.", unchecked_return_type = "Map" )] pub fn get_all_accounts(&self) -> Result, RaindexError> { - Ok(self.orderbook_yaml.get_accounts()?) + Ok(self.raindex_yaml.get_accounts()?) } - /// Retrieves all orderbooks from the orderbook YAML configuration + /// Retrieves all raindexes from the raindex YAML configuration /// - /// Returns a map of orderbook configurations where the keys are orderbook names - /// and the values are `OrderbookCfg` objects. + /// Returns a map of raindex configurations where the keys are raindex names + /// and the values are `RaindexCfg` objects. /// /// ## Examples /// /// ```javascript - /// const result = client.getAllOrderbooks(); + /// const result = client.getAllRaindexes(); /// if (result.error) { - /// console.error("Error getting orderbooks:", result.error.readableMsg); + /// console.error("Error getting raindexes:", result.error.readableMsg); /// return; /// } - /// const orderbooks = result.value; - /// for (const [name, orderbook] of orderbooks) { - /// console.log(`Orderbook: ${name}, Address: ${orderbook.address}, Chain: ${orderbook.network.chainId}`); + /// const raindexes = result.value; + /// for (const [name, raindex] of raindexes) { + /// console.log(`Raindex: ${name}, Address: ${raindex.address}, Chain: ${raindex.network.chainId}`); /// } /// ``` #[wasm_export( - js_name = "getAllOrderbooks", - return_description = "Returns the list of orderbooks from the orderbook YAML configuration.", - unchecked_return_type = "Map" + js_name = "getAllRaindexes", + return_description = "Returns the list of raindexes from the raindex YAML configuration.", + unchecked_return_type = "Map" )] - pub fn get_all_orderbooks(&self) -> Result, RaindexError> { - Ok(self.orderbook_yaml.get_orderbooks()?) + pub fn get_all_raindexes(&self) -> Result, RaindexError> { + Ok(self.raindex_yaml.get_raindexes()?) } - /// Retrieves all tokens from the orderbook YAML configuration + /// Retrieves all tokens from the raindex YAML configuration /// /// Returns a map of token configurations where the keys are token names /// and the values are `TokenCfg` objects containing token details such as @@ -230,12 +230,12 @@ impl RaindexClient { unchecked_return_type = "Map" )] pub fn get_all_tokens(&self) -> Result, RaindexError> { - Ok(self.orderbook_yaml.get_tokens()?) + Ok(self.raindex_yaml.get_tokens()?) } } impl RaindexClient { - pub fn get_orderbook_by_address(&self, address: Address) -> Result { - Ok(self.orderbook_yaml.get_orderbook_by_address(address)?) + pub fn get_raindex_by_address(&self, address: Address) -> Result { + Ok(self.raindex_yaml.get_raindex_by_address(address)?) } } @@ -316,7 +316,7 @@ mod tests { } #[wasm_bindgen_test] - async fn test_get_orderbook_by_address_wasm_binding() { + async fn test_get_raindex_by_address_wasm_binding() { let yaml = get_test_yaml( "http://localhost:3001", "http://localhost:3002", @@ -328,29 +328,29 @@ mod tests { .unwrap(); let mainnet_address = "0x1234567890123456789012345678901234567890".to_string(); - let mainnet_orderbook = client - .get_orderbook_by_address_wasm_binding(mainnet_address.clone()) + let mainnet_raindex = client + .get_raindex_by_address_wasm_binding(mainnet_address.clone()) .unwrap(); assert_eq!( - mainnet_orderbook.address.to_string().to_lowercase(), + mainnet_raindex.address.to_string().to_lowercase(), mainnet_address.to_lowercase() ); let polygon_address = "0x0987654321098765432109876543210987654321".to_string(); - let polygon_orderbook = client - .get_orderbook_by_address_wasm_binding(polygon_address.clone()) + let polygon_raindex = client + .get_raindex_by_address_wasm_binding(polygon_address.clone()) .unwrap(); assert_eq!( - polygon_orderbook.address.to_string().to_lowercase(), + polygon_raindex.address.to_string().to_lowercase(), polygon_address.to_lowercase() ); - let result = client.get_orderbook_by_address_wasm_binding( + let result = client.get_raindex_by_address_wasm_binding( "0x1111111111111111111111111111111111111111".to_string(), ); assert!(result.is_err()); - let result = client.get_orderbook_by_address_wasm_binding("invalid_address".to_string()); + let result = client.get_raindex_by_address_wasm_binding("invalid_address".to_string()); assert!(result.is_err()); } @@ -444,7 +444,7 @@ mod tests { } #[wasm_bindgen_test] - async fn test_get_all_orderbooks() { + async fn test_get_all_raindexes() { let yaml = get_test_yaml( "http://localhost:3001", "http://localhost:3002", @@ -454,26 +454,26 @@ mod tests { let client = RaindexClient::new(vec![yaml], None, None, None, None) .await .unwrap(); - let result = client.get_all_orderbooks().unwrap(); + let result = client.get_all_raindexes().unwrap(); assert_eq!(result.len(), 2); - assert!(result.contains_key("mainnet-orderbook")); - assert!(result.contains_key("polygon-orderbook")); + assert!(result.contains_key("mainnet-raindex")); + assert!(result.contains_key("polygon-raindex")); - let mainnet_ob = result.get("mainnet-orderbook").unwrap(); + let mainnet_ob = result.get("mainnet-raindex").unwrap(); assert_eq!( mainnet_ob.address, Address::from_str("0x1234567890123456789012345678901234567890").unwrap() ); assert_eq!(mainnet_ob.network.chain_id, 1); - assert_eq!(mainnet_ob.label, Some("Primary Orderbook".to_string())); + assert_eq!(mainnet_ob.label, Some("Primary Raindex".to_string())); - let polygon_ob = result.get("polygon-orderbook").unwrap(); + let polygon_ob = result.get("polygon-raindex").unwrap(); assert_eq!( polygon_ob.address, Address::from_str("0x0987654321098765432109876543210987654321").unwrap() ); assert_eq!(polygon_ob.network.chain_id, 137); - assert_eq!(polygon_ob.label, Some("Polygon Orderbook".to_string())); + assert_eq!(polygon_ob.label, Some("Polygon Raindex".to_string())); } } diff --git a/crates/common/src/raindex_client/remove_orders.rs b/crates/common/src/raindex_client/remove_orders.rs index b97ac218ac..de7ef3ad95 100644 --- a/crates/common/src/raindex_client/remove_orders.rs +++ b/crates/common/src/raindex_client/remove_orders.rs @@ -7,8 +7,8 @@ use crate::raindex_client::QuerySource; use crate::retry::{retry_with_constant_interval, RetryError}; use alloy::primitives::{hex::decode, Bytes, B256}; use alloy::sol_types::{SolCall, SolValue}; -use rain_orderbook_bindings::IRaindexV6::{removeOrder3Call, OrderV4}; -use rain_orderbook_subgraph_client::types::order_detail_traits::OrderDetailError; +use raindex_bindings::IRaindexV6::{removeOrder3Call, OrderV4}; +use raindex_subgraph_client::types::order_detail_traits::OrderDetailError; const DEFAULT_REMOVE_ORDER_POLL_ATTEMPTS: usize = 10; const DEFAULT_REMOVE_ORDER_POLL_INTERVAL_MS: u64 = 1_000; @@ -48,11 +48,11 @@ impl RaindexClient { #[wasm_export(js_name = "chainId", param_description = "Chain ID for the network")] chain_id: u32, #[wasm_export( - js_name = "orderbookAddress", - param_description = "Orderbook contract address", + js_name = "raindexAddress", + param_description = "Raindex contract address", unchecked_param_type = "Address" )] - orderbook_address: String, + raindex_address: String, #[wasm_export( js_name = "txHash", param_description = "Transaction hash", @@ -70,11 +70,11 @@ impl RaindexClient { )] interval_ms: Option, ) -> Result, RaindexError> { - let orderbook_address = Address::from_str(&orderbook_address)?; + let raindex_address = Address::from_str(&raindex_address)?; let tx_hash = B256::from_str(&tx_hash)?; self.get_remove_orders_for_transaction( chain_id, - orderbook_address, + raindex_address, tx_hash, max_attempts.map(|v| v as usize), interval_ms.map(|v| v as u64), @@ -86,7 +86,7 @@ impl RaindexClient { async fn get_remove_orders_for_transaction( &self, chain_id: u32, - orderbook_address: Address, + raindex_address: Address, tx_hash: B256, max_attempts: Option, interval_ms: Option, @@ -104,7 +104,7 @@ impl RaindexClient { let local_result = retry_with_constant_interval( || async { let orders = local_source - .get_removed_by_tx_hash(chain_id, orderbook_address, tx_hash) + .get_removed_by_tx_hash(chain_id, raindex_address, tx_hash) .await .map_err(PollError::Inner)?; if orders.is_empty() { @@ -136,12 +136,12 @@ impl RaindexClient { let subgraph_result = retry_with_constant_interval( || async { let orders = match subgraph_source - .get_removed_by_tx_hash(chain_id, orderbook_address, tx_hash) + .get_removed_by_tx_hash(chain_id, raindex_address, tx_hash) .await { Ok(orders) => orders, - Err(RaindexError::OrderbookSubgraphClientError( - rain_orderbook_subgraph_client::OrderbookSubgraphClientError::Empty, + Err(RaindexError::RaindexSubgraphClientError( + raindex_subgraph_client::RaindexSubgraphClientError::Empty, )) => return Err(PollError::Empty), Err(e) => return Err(PollError::Inner(e)), }; @@ -175,10 +175,10 @@ impl RaindexClient { #[wasm_export] impl RaindexOrder { - /// Generates ABI-encoded calldata for the `removeOrder2()` function on the orderbook contract + /// Generates ABI-encoded calldata for the `removeOrder2()` function on the raindex contract /// /// Takes an existing order from the subgraph and creates the transaction calldata needed - /// to remove it from the orderbook. The order must be active and owned by the caller. + /// to remove it from the raindex. The order must be active and owned by the caller. /// /// ## Examples /// @@ -227,16 +227,14 @@ mod tests { fetch_orders::LocalDbOrder, FromDbJson, LocalDbQueryError, LocalDbQueryExecutor, SqlStatement, SqlStatementBatch, }, - local_db::OrderbookIdentifier, + local_db::RaindexIdentifier, raindex_client::local_db::LocalDb, - raindex_client::tests::{ - get_test_yaml, new_with_local_db, CHAIN_ID_1_ORDERBOOK_ADDRESS, - }, + raindex_client::tests::{get_test_yaml, new_with_local_db, CHAIN_ID_1_RAINDEX_ADDRESS}, }; use alloy::primitives::{b256, Address, Bytes, U256}; use async_trait::async_trait; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; use std::{ str::FromStr, @@ -319,7 +317,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -346,7 +344,7 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -360,7 +358,7 @@ mod tests { "balanceChanges": [] } ], - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "active": true, @@ -409,7 +407,7 @@ mod tests { let res = raindex_client .get_remove_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), None, None, @@ -453,7 +451,7 @@ mod tests { assert_eq!(order.meta(), Some(Bytes::from_str("0xff0a89c674ee7874a3005902252f2a20302e2063616c63756c6174652d696f202a2f200a7573696e672d776f7264732d66726f6d203078466532343131434461313933443945346538334135633233344337466433323031303138383361430a616d743a203130302c0a696f3a2063616c6c3c323e28293b0a0a2f2a20312e2068616e646c652d696f202a2f200a3a63616c6c3c333e28292c0a3a656e7375726528657175616c2d746f286f75747075742d7661756c742d64656372656173652829203130302920226d7573742074616b652066756c6c20616d6f756e7422293b0a0a2f2a20322e206765742d696f2d726174696f2d6e6f77202a2f200a656c61707365643a2063616c6c3c343e28292c0a696f3a2073617475726174696e672d73756228302e3031373733353620646976286d756c28656c61707365642073756228302e3031373733353620302e30313733383434292920363029293b0a0a2f2a20332e206f6e652d73686f74202a2f200a3a656e737572652869732d7a65726f286765742868617368286f726465722d68617368282920226861732d657865637574656422292929202268617320657865637574656422292c0a3a7365742868617368286f726465722d68617368282920226861732d657865637574656422292031293b0a0a2f2a20342e206765742d656c6170736564202a2f200a5f3a20737562286e6f772829206765742868617368286f726465722d68617368282920226465706c6f792d74696d65222929293b011bff13109e41336ff20278186170706c69636174696f6e2f6f637465742d73747265616d").unwrap())); assert!(order.active()); assert_eq!( - order.orderbook(), + order.raindex(), Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); @@ -490,7 +488,7 @@ mod tests { assert_eq!(output.token().symbol(), Some("sFLR".to_string())); assert_eq!(output.token().decimals(), 18); assert_eq!( - output.orderbook(), + output.raindex(), Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); assert_eq!(output.orders_as_outputs().len(), 1); @@ -538,7 +536,7 @@ mod tests { assert_eq!(input.token().symbol(), Some("WFLR".to_string())); assert_eq!(input.token().decimals(), 18); assert_eq!( - input.orderbook(), + input.raindex(), Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); assert!(input.orders_as_outputs().is_empty()); @@ -577,8 +575,8 @@ mod tests { "owner": "0xf08bcbce72f62c95dcb7c07dcb5ed26acfcfbc11", "outputs": [], "inputs": [], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -615,9 +613,9 @@ mod tests { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -655,7 +653,7 @@ mod tests { let res = raindex_client .get_remove_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_REMOVE_ORDER_POLL_ATTEMPTS), Some(10), @@ -690,7 +688,7 @@ mod tests { let err = raindex_client .get_remove_orders_for_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_REMOVE_ORDER_POLL_ATTEMPTS), Some(10), @@ -710,7 +708,7 @@ mod tests { async fn test_get_transaction_remove_orders_prefers_local_db() { let tx_hash = b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"); - let orderbook_address = + let raindex_address = Address::from_str("0x0987654321098765432109876543210987654321").unwrap(); let owner = Address::from_str("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(); @@ -722,7 +720,7 @@ mod tests { owner, block_timestamp: 1_000, block_number: 50, - orderbook_address, + raindex_address, order_bytes: Bytes::from_str("0x01").unwrap(), transaction_hash: tx_hash, inputs: None, @@ -759,13 +757,7 @@ mod tests { .await; let res = client - .get_remove_orders_for_transaction( - 137, - orderbook_address, - tx_hash, - Some(3), - Some(1), - ) + .get_remove_orders_for_transaction(137, raindex_address, tx_hash, Some(3), Some(1)) .await .unwrap(); @@ -785,7 +777,7 @@ mod tests { async fn test_get_transaction_remove_orders_exhausts_local_without_fallback() { let tx_hash = b256!("0x00000000000000000000000000000000000000000000000000000000cafebabe"); - let orderbook_address = + let raindex_address = Address::from_str("0x0987654321098765432109876543210987654321").unwrap(); let local_exec = CountingJsonExec { @@ -815,13 +807,7 @@ mod tests { .await; let err = client - .get_remove_orders_for_transaction( - 137, - orderbook_address, - tx_hash, - Some(2), - Some(1), - ) + .get_remove_orders_for_transaction(137, raindex_address, tx_hash, Some(2), Some(1)) .await .unwrap_err(); diff --git a/crates/common/src/raindex_client/take_orders/approval.rs b/crates/common/src/raindex_client/take_orders/approval.rs index 62a02ab8c9..8f2c8c9153 100644 --- a/crates/common/src/raindex_client/take_orders/approval.rs +++ b/crates/common/src/raindex_client/take_orders/approval.rs @@ -13,7 +13,7 @@ pub struct ApprovalCheckParams { pub rpc_urls: Vec, pub sell_token: Address, pub taker: Address, - pub orderbook: Address, + pub raindex: Address, pub mode: ParsedTakeOrdersMode, pub price_cap: Float, } @@ -28,14 +28,14 @@ pub async fn check_approval_needed( let required_u256 = max_sell_cap.to_fixed_decimal_lossy(decimals)?.0; let allowance_result = - check_taker_allowance(&erc20, params.taker, params.orderbook, required_u256) + check_taker_allowance(&erc20, params.taker, params.raindex, required_u256) .await .map_err(|e| RaindexError::PreflightError(e.to_string()))?; if allowance_result.needs_approval { Ok(Some(build_approval_result( params.sell_token, - params.orderbook, + params.raindex, max_sell_cap, decimals, )?)) @@ -163,7 +163,7 @@ mod local_evm_tests { use super::*; use crate::take_orders::TakeOrdersMode; use alloy::primitives::U256; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_test_fixtures::LocalEvm; use url::Url; fn make_mode(mode: TakeOrdersMode, amount: &str) -> ParsedTakeOrdersMode { @@ -181,7 +181,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -202,7 +202,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::SpendUpTo, "100"), price_cap: Float::parse("2".to_string()).unwrap(), }; @@ -227,8 +227,8 @@ mod local_evm_tests { ); assert_eq!( approval_info.spender(), - orderbook, - "spender should be orderbook" + raindex, + "spender should be raindex" ); assert!( !approval_info.calldata().is_empty(), @@ -244,7 +244,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -260,7 +260,7 @@ mod local_evm_tests { .unwrap(); token - .approve(orderbook, U256::MAX) + .approve(raindex, U256::MAX) .from(taker) .send() .await @@ -275,7 +275,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::SpendUpTo, "100"), price_cap: Float::parse("2".to_string()).unwrap(), }; @@ -296,7 +296,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("USDC", "USDC", 6, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -317,7 +317,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::SpendUpTo, "1.57126799999999998"), price_cap: Float::parse("1".to_string()).unwrap(), }; @@ -338,7 +338,7 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); token .transfer( @@ -355,7 +355,7 @@ mod local_evm_tests { token .approve( - orderbook, + raindex, U256::from(150u64) * U256::from(10).pow(U256::from(18)), ) .from(taker) @@ -372,7 +372,7 @@ mod local_evm_tests { rpc_urls: vec![rpc_url], sell_token: *token.address(), taker, - orderbook, + raindex, mode: make_mode(TakeOrdersMode::BuyUpTo, "100"), price_cap: Float::parse("2".to_string()).unwrap(), }; diff --git a/crates/common/src/raindex_client/take_orders/e2e_tests.rs b/crates/common/src/raindex_client/take_orders/e2e_tests.rs index 4ac72d826d..650ff5e155 100644 --- a/crates/common/src/raindex_client/take_orders/e2e_tests.rs +++ b/crates/common/src/raindex_client/take_orders/e2e_tests.rs @@ -4,18 +4,18 @@ use crate::raindex_client::RaindexClient; use crate::raindex_client::RaindexError; use crate::take_orders::TakeOrdersMode; use crate::test_helpers::dotrain::{ - create_dotrain_config_for_orderbook, create_dotrain_config_with_params, + create_dotrain_config_for_raindex, create_dotrain_config_with_params, create_dotrain_config_with_vault_and_ratio, }; use crate::test_helpers::local_evm::{ - approve_taker, create_vault, create_vault_for_orderbook, deposit_to_orderbook, - fund_and_approve_taker, fund_and_approve_taker_multi_orderbook, fund_standard_two_token_vault, - fund_taker, setup_multi_orderbook_test, setup_test as base_setup_test, standard_deposit_amount, + approve_taker, create_vault, create_vault_for_raindex, deposit_to_raindex, + fund_and_approve_taker, fund_and_approve_taker_multi_raindex, fund_standard_two_token_vault, + fund_taker, setup_multi_raindex_test, setup_test as base_setup_test, standard_deposit_amount, }; -use crate::test_helpers::orders::deploy::{deploy_order, deploy_order_to_orderbook}; +use crate::test_helpers::orders::deploy::{deploy_order, deploy_order_to_raindex}; use crate::test_helpers::subgraph::{ - create_sg_order_json, create_sg_order_json_with_orderbook, get_minimal_yaml_for_chain, - get_multi_orderbook_yaml, + create_sg_order_json, create_sg_order_json_with_raindex, get_minimal_yaml_for_chain, + get_multi_raindex_yaml, }; use alloy::network::TransactionBuilder; use alloy::primitives::{Address, B256, U256}; @@ -24,7 +24,7 @@ use alloy::serde::WithOtherFields; use alloy::sol_types::SolCall; use httpmock::MockServer; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; +use raindex_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; use serde_json::json; use std::ops::{Mul, Sub}; @@ -122,7 +122,7 @@ async fn test_get_take_orders_calldata_no_candidates_returns_no_liquidity() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -181,7 +181,7 @@ async fn test_get_take_orders_calldata_happy_path_returns_valid_config() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -191,7 +191,7 @@ async fn test_get_take_orders_calldata_happy_path_returns_valid_config() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -212,9 +212,9 @@ async fn test_get_take_orders_calldata_happy_path_returns_valid_config() { let result = result.take_orders_info().unwrap(); assert_eq!( - result.orderbook(), - setup.orderbook, - "Orderbook address should match" + result.raindex(), + setup.raindex, + "Raindex address should match" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -285,7 +285,7 @@ async fn test_get_take_orders_calldata_min_receive_mode_exact_vs_partial() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -295,7 +295,7 @@ async fn test_get_take_orders_calldata_min_receive_mode_exact_vs_partial() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -414,7 +414,7 @@ async fn test_get_take_orders_calldata_wrong_direction_returns_no_liquidity() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -474,7 +474,7 @@ async fn test_min_receive_mode_exact_returns_error_when_insufficient_liquidity() 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -484,7 +484,7 @@ async fn test_min_receive_mode_exact_returns_error_when_insufficient_liquidity() &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -593,7 +593,7 @@ async fn test_maximum_io_ratio_enforcement_skips_overpriced_leg() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -603,7 +603,7 @@ async fn test_maximum_io_ratio_enforcement_skips_overpriced_leg() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -674,7 +674,7 @@ async fn test_maximum_io_ratio_enforcement_skips_overpriced_leg() { let tx = WithOtherFields::new( TransactionRequest::default() .with_input(modified_calldata_bytes.clone()) - .with_to(setup.orderbook) + .with_to(setup.raindex) .with_from(taker), ); @@ -736,7 +736,7 @@ async fn test_maximum_io_ratio_enforcement_skips_overpriced_leg() { let exact_tx = WithOtherFields::new( TransactionRequest::default() .with_input(exact_calldata_bytes) - .with_to(setup.orderbook) + .with_to(setup.raindex) .with_from(taker), ); @@ -812,7 +812,7 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -822,7 +822,7 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -858,7 +858,7 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { let withdraw_tx = setup .local_evm - .orderbook + .raindex .withdraw4(setup.token2, vault_id_2, withdraw_amount, vec![]) .from(setup.owner) .into_transaction_request(); @@ -880,7 +880,7 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { let tx = WithOtherFields::new( TransactionRequest::default() .with_input(result.calldata().to_vec()) - .with_to(setup.orderbook) + .with_to(setup.raindex) .with_from(taker), ); @@ -935,7 +935,7 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { let exact_tx = WithOtherFields::new( TransactionRequest::default() .with_input(exact_calldata_bytes) - .with_to(setup.orderbook) + .with_to(setup.raindex) .with_from(taker), ); @@ -948,66 +948,64 @@ async fn test_maximum_io_ratio_enforcement_with_worsened_on_chain_price() { } #[tokio::test] -async fn test_cross_orderbook_selection_picks_best_book() { - let setup = setup_multi_orderbook_test().await; +async fn test_cross_raindex_selection_picks_best_book() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; assert_ne!( - setup.orderbook_a, setup.orderbook_b, - "Orderbook addresses should be different" + setup.raindex_a, setup.raindex_b, + "Raindex addresses should be different" ); let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, setup.token2, deposit_amount, vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, setup.token2, deposit_amount, vault_id_b, ) .await; - let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_a, "0x01", "5", "2"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "2"); let (order_bytes_a, order_hash_a, _order_v4_a) = - deploy_order_to_orderbook(&setup, setup.orderbook_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_b, "0x02", "8", "2"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "2"); let (order_bytes_b, order_hash_b, order_v4_b) = - deploy_order_to_orderbook(&setup, setup.orderbook_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, &order_bytes_a, order_hash_a, vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, &order_bytes_b, order_hash_b, vec![vault_b_input], @@ -1023,22 +1021,22 @@ async fn test_cross_orderbook_selection_picks_best_book() { })); }); - let yaml = get_multi_orderbook_yaml( + let yaml = get_multi_raindex_yaml( 123, &setup.local_evm.url(), &sg_server.url("/sg"), - &setup.orderbook_a.to_string(), - &setup.orderbook_b.to_string(), + &setup.raindex_a.to_string(), + &setup.raindex_b.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, - setup.orderbook_b, + setup.raindex_b, U256::from(10).pow(U256::from(22)), ) .await; @@ -1055,7 +1053,7 @@ async fn test_cross_orderbook_selection_picks_best_book() { price_cap: high_price_cap(), }) .await - .expect("Should succeed with orders from multiple orderbooks"); + .expect("Should succeed with orders from multiple raindexes"); assert!(result.is_ready(), "Expected Ready variant"); let result = result.take_orders_info().unwrap(); @@ -1063,32 +1061,32 @@ async fn test_cross_orderbook_selection_picks_best_book() { let config = decoded.config; assert_eq!( - result.orderbook(), - setup.orderbook_b, - "Should select orderbook B (max_output=8 > max_output=5)" + result.raindex(), + setup.raindex_b, + "Should select raindex B (max_output=8 > max_output=5)" ); assert!( !config.orders.is_empty(), - "Should have at least one order from the winning orderbook" + "Should have at least one order from the winning raindex" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_b.owner, - "All orders should be from orderbook B" + "All orders should be from raindex B" ); assert_eq!( config_order.evaluable.bytecode, order_v4_b.evaluable.bytecode, - "All order bytecodes should match orderbook B's order" + "All order bytecodes should match raindex B's order" ); } let expected_ratio = Float::parse("2".to_string()).unwrap(); assert!( result.prices()[0].eq(expected_ratio).unwrap(), - "Price should be 2 (orderbook B's ratio)" + "Price should be 2 (raindex B's ratio)" ); let tolerance = Float::parse("0.0001".to_string()).unwrap(); @@ -1105,61 +1103,59 @@ async fn test_cross_orderbook_selection_picks_best_book() { } #[tokio::test] -async fn test_cross_orderbook_selection_flips_when_economics_flip() { - let setup = setup_multi_orderbook_test().await; +async fn test_cross_raindex_selection_flips_when_economics_flip() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, setup.token2, deposit_amount, vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, setup.token2, deposit_amount, vault_id_b, ) .await; - let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_a, "0x01", "10", "2"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "10", "2"); let (order_bytes_a, order_hash_a, order_v4_a) = - deploy_order_to_orderbook(&setup, setup.orderbook_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_b, "0x02", "3", "2"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "3", "2"); let (order_bytes_b, order_hash_b, _order_v4_b) = - deploy_order_to_orderbook(&setup, setup.orderbook_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, &order_bytes_a, order_hash_a, vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, &order_bytes_b, order_hash_b, vec![vault_b_input], @@ -1175,22 +1171,22 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { })); }); - let yaml = get_multi_orderbook_yaml( + let yaml = get_multi_raindex_yaml( 123, &setup.local_evm.url(), &sg_server.url("/sg"), - &setup.orderbook_a.to_string(), - &setup.orderbook_b.to_string(), + &setup.raindex_a.to_string(), + &setup.raindex_b.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, - setup.orderbook_a, + setup.raindex_a, U256::from(10).pow(U256::from(22)), ) .await; @@ -1212,9 +1208,9 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { let result = result.take_orders_info().unwrap(); assert_eq!( - result.orderbook(), - setup.orderbook_a, - "Should select orderbook A (max_output=10 > max_output=3)" + result.raindex(), + setup.raindex_a, + "Should select raindex A (max_output=10 > max_output=3)" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -1222,18 +1218,18 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { assert!( !config.orders.is_empty(), - "Should have at least one order from the winning orderbook" + "Should have at least one order from the winning raindex" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_a.owner, - "All orders should be from orderbook A" + "All orders should be from raindex A" ); assert_eq!( config_order.evaluable.bytecode, order_v4_a.evaluable.bytecode, - "All order bytecodes should match orderbook A's order" + "All order bytecodes should match raindex A's order" ); } @@ -1241,67 +1237,65 @@ async fn test_cross_orderbook_selection_flips_when_economics_flip() { let min_expected = Float::parse("10".to_string()).unwrap(); assert!( actual_max_input.gte(min_expected).unwrap(), - "maximumIO should be at least 10 (orderbook A's max_output), got: {:?}", + "maximumIO should be at least 10 (raindex A's max_output), got: {:?}", actual_max_input.format() ); } #[tokio::test] -async fn test_cross_orderbook_economic_selection_prefers_best_yield() { - let setup = setup_multi_orderbook_test().await; +async fn test_cross_raindex_economic_selection_prefers_best_yield() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, setup.token2, deposit_amount, vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, setup.token2, deposit_amount, vault_id_b, ) .await; - let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_a, "0x01", "5", "1"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "5", "1"); let (order_bytes_a, order_hash_a, order_v4_a) = - deploy_order_to_orderbook(&setup, setup.orderbook_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_b, "0x02", "8", "1.5"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "8", "1.5"); let (order_bytes_b, order_hash_b, _order_v4_b) = - deploy_order_to_orderbook(&setup, setup.orderbook_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, &order_bytes_a, order_hash_a, vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, &order_bytes_b, order_hash_b, vec![vault_b_input], @@ -1317,22 +1311,22 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { })); }); - let yaml = get_multi_orderbook_yaml( + let yaml = get_multi_raindex_yaml( 123, &setup.local_evm.url(), &sg_server.url("/sg"), - &setup.orderbook_a.to_string(), - &setup.orderbook_b.to_string(), + &setup.raindex_a.to_string(), + &setup.raindex_b.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, - setup.orderbook_a, + setup.raindex_a, U256::from(10).pow(U256::from(22)), ) .await; @@ -1349,13 +1343,13 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { price_cap: high_price_cap(), }) .await - .expect("Should succeed with orders from multiple orderbooks"); + .expect("Should succeed with orders from multiple raindexes"); assert!(result.is_ready(), "Expected Ready variant"); let result = result.take_orders_info().unwrap(); assert_eq!( - result.orderbook(), setup.orderbook_a, - "Should select orderbook A (can fill 5 buy at ratio 1.0) over B (can fill 5 buy but at worse price 1.5)" + result.raindex(), setup.raindex_a, + "Should select raindex A (can fill 5 buy at ratio 1.0) over B (can fill 5 buy but at worse price 1.5)" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -1363,30 +1357,30 @@ async fn test_cross_orderbook_economic_selection_prefers_best_yield() { assert!( !config.orders.is_empty(), - "Should have at least one order from the winning orderbook" + "Should have at least one order from the winning raindex" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_a.owner, - "All orders should be from orderbook A" + "All orders should be from raindex A" ); assert_eq!( config_order.evaluable.bytecode, order_v4_a.evaluable.bytecode, - "All order bytecodes should match orderbook A's order" + "All order bytecodes should match raindex A's order" ); } assert_eq!( result.prices().len(), 1, - "Should have exactly one price (from orderbook A only)" + "Should have exactly one price (from raindex A only)" ); let expected_ratio = Float::parse("1".to_string()).unwrap(); assert!( result.prices()[0].eq(expected_ratio).unwrap(), - "Price should be 1.0 (orderbook A's ratio), got: {:?}", + "Price should be 1.0 (raindex A's ratio), got: {:?}", result.prices()[0].format() ); @@ -1528,7 +1522,7 @@ async fn test_prices_sorted_best_to_worst_matching_config_orders() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -1538,7 +1532,7 @@ async fn test_prices_sorted_best_to_worst_matching_config_orders() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1639,7 +1633,7 @@ async fn test_spend_up_to_mode_happy_path() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -1649,7 +1643,7 @@ async fn test_spend_up_to_mode_happy_path() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1670,9 +1664,9 @@ async fn test_spend_up_to_mode_happy_path() { let result = result.take_orders_info().unwrap(); assert_eq!( - result.orderbook(), - setup.orderbook, - "Orderbook address should match" + result.raindex(), + setup.raindex, + "Raindex address should match" ); let decoded = takeOrders4Call::abi_decode(result.calldata()).expect("Should decode calldata"); @@ -1748,7 +1742,7 @@ async fn test_spend_exact_vs_spend_up_to_modes() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -1758,7 +1752,7 @@ async fn test_spend_exact_vs_spend_up_to_modes() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1886,7 +1880,7 @@ async fn test_spend_exact_mode_insufficient_liquidity() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -1896,7 +1890,7 @@ async fn test_spend_exact_mode_insufficient_liquidity() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1983,7 +1977,7 @@ async fn test_spend_mode_max_sell_cap_equals_spend_budget() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -1993,7 +1987,7 @@ async fn test_spend_mode_max_sell_cap_equals_spend_budget() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -2056,61 +2050,59 @@ async fn test_spend_mode_max_sell_cap_equals_spend_budget() { } #[tokio::test] -async fn test_spend_mode_cross_orderbook_selection() { - let setup = setup_multi_orderbook_test().await; +async fn test_spend_mode_cross_raindex_selection() { + let setup = setup_multi_raindex_test().await; let sg_server = MockServer::start_async().await; let vault_id_a = B256::from(U256::from(1u64)); let vault_id_b = B256::from(U256::from(2u64)); let deposit_amount = U256::from(10).pow(U256::from(22)); - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, setup.token2, deposit_amount, vault_id_a, ) .await; - deposit_to_orderbook( + deposit_to_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, setup.token2, deposit_amount, vault_id_b, ) .await; - let dotrain_a = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_a, "0x01", "50", "2"); + let dotrain_a = create_dotrain_config_for_raindex(&setup, setup.raindex_a, "0x01", "50", "2"); let (order_bytes_a, order_hash_a, _order_v4_a) = - deploy_order_to_orderbook(&setup, setup.orderbook_a, dotrain_a).await; + deploy_order_to_raindex(&setup, setup.raindex_a, dotrain_a).await; - let dotrain_b = - create_dotrain_config_for_orderbook(&setup, setup.orderbook_b, "0x02", "80", "2"); + let dotrain_b = create_dotrain_config_for_raindex(&setup, setup.raindex_b, "0x02", "80", "2"); let (order_bytes_b, order_hash_b, order_v4_b) = - deploy_order_to_orderbook(&setup, setup.orderbook_b, dotrain_b).await; + deploy_order_to_raindex(&setup, setup.raindex_b, dotrain_b).await; let vault_a_input = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token1_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token1_sg); let vault_a_output = - create_vault_for_orderbook(vault_id_a, &setup, setup.orderbook_a, &setup.token2_sg); + create_vault_for_raindex(vault_id_a, &setup, setup.raindex_a, &setup.token2_sg); let vault_b_input = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token1_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token1_sg); let vault_b_output = - create_vault_for_orderbook(vault_id_b, &setup, setup.orderbook_b, &setup.token2_sg); + create_vault_for_raindex(vault_id_b, &setup, setup.raindex_b, &setup.token2_sg); - let sg_order_a = create_sg_order_json_with_orderbook( + let sg_order_a = create_sg_order_json_with_raindex( &setup, - setup.orderbook_a, + setup.raindex_a, &order_bytes_a, order_hash_a, vec![vault_a_input], vec![vault_a_output], ); - let sg_order_b = create_sg_order_json_with_orderbook( + let sg_order_b = create_sg_order_json_with_raindex( &setup, - setup.orderbook_b, + setup.raindex_b, &order_bytes_b, order_hash_b, vec![vault_b_input], @@ -2126,22 +2118,22 @@ async fn test_spend_mode_cross_orderbook_selection() { })); }); - let yaml = get_multi_orderbook_yaml( + let yaml = get_multi_raindex_yaml( 123, &setup.local_evm.url(), &sg_server.url("/sg"), - &setup.orderbook_a.to_string(), - &setup.orderbook_b.to_string(), + &setup.raindex_a.to_string(), + &setup.raindex_b.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let taker = setup.local_evm.signer_wallets[1].default_signer().address(); - fund_and_approve_taker_multi_orderbook( + fund_and_approve_taker_multi_raindex( &setup, setup.token1, taker, - setup.orderbook_b, + setup.raindex_b, U256::from(10).pow(U256::from(22)), ) .await; @@ -2157,7 +2149,7 @@ async fn test_spend_mode_cross_orderbook_selection() { price_cap: high_price_cap(), }) .await - .expect("Should succeed with spend mode across multiple orderbooks"); + .expect("Should succeed with spend mode across multiple raindexes"); assert!(result.is_ready(), "Expected Ready variant"); let result = result.take_orders_info().unwrap(); @@ -2170,16 +2162,16 @@ async fn test_spend_mode_cross_orderbook_selection() { ); assert_eq!( - result.orderbook(), - setup.orderbook_b, - "Should select orderbook B (can spend more: 80*2=160 vs 50*2=100)" + result.raindex(), + setup.raindex_b, + "Should select raindex B (can spend more: 80*2=160 vs 50*2=100)" ); for config_item in &config.orders { let config_order = &config_item.order; assert_eq!( config_order.owner, order_v4_b.owner, - "All orders should be from orderbook B" + "All orders should be from raindex B" ); } } @@ -2219,7 +2211,7 @@ async fn test_get_take_orders_calldata_returns_approval_when_no_allowance() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -2259,8 +2251,8 @@ async fn test_get_take_orders_calldata_returns_approval_when_no_allowance() { ); assert_eq!( approval.spender(), - setup.orderbook, - "Approval spender should be orderbook" + setup.raindex, + "Approval spender should be raindex" ); assert!( !approval.calldata().is_empty(), @@ -2303,7 +2295,7 @@ async fn test_get_take_orders_calldata_returns_approval_when_insufficient_allowa 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -2322,7 +2314,7 @@ async fn test_get_take_orders_calldata_returns_approval_when_insufficient_allowa &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, insufficient_allowance, ) .await; @@ -2353,8 +2345,8 @@ async fn test_get_take_orders_calldata_returns_approval_when_insufficient_allowa ); assert_eq!( approval.spender(), - setup.orderbook, - "Approval spender should be orderbook" + setup.raindex, + "Approval spender should be raindex" ); } @@ -2393,7 +2385,7 @@ async fn test_get_take_orders_calldata_returns_take_orders_when_sufficient_allow 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); @@ -2415,7 +2407,7 @@ async fn test_get_take_orders_calldata_returns_take_orders_when_sufficient_allow &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, sufficient_allowance, ) .await; @@ -2440,9 +2432,9 @@ async fn test_get_take_orders_calldata_returns_take_orders_when_sufficient_allow let take_orders = result.take_orders_info().unwrap(); assert_eq!( - take_orders.orderbook(), - setup.orderbook, - "Orderbook address should match" + take_orders.raindex(), + setup.raindex, + "Raindex address should match" ); assert!( !take_orders.calldata().is_empty(), diff --git a/crates/common/src/raindex_client/take_orders/mod.rs b/crates/common/src/raindex_client/take_orders/mod.rs index c0ee93b2ad..86ebeeafcf 100644 --- a/crates/common/src/raindex_client/take_orders/mod.rs +++ b/crates/common/src/raindex_client/take_orders/mod.rs @@ -20,7 +20,7 @@ use crate::take_orders::{ build_take_orders_config_from_simulation, find_failing_order_index, simulate_take_orders, }; use approval::{check_approval_needed, ApprovalCheckParams}; -use rain_orderbook_bindings::provider::mk_read_provider; +use raindex_bindings::provider::mk_read_provider; use wasm_bindgen_utils::prelude::*; use wasm_bindgen_utils::wasm_export; @@ -61,7 +61,7 @@ impl RaindexClient { /// if (res.error) { /// console.error(res.error.readableMsg); /// } else { - /// const { calldata, effectivePrice, expectedSell, maxSellCap, prices, orderbook } = res.value; + /// const { calldata, effectivePrice, expectedSell, maxSellCap, prices, raindex } = res.value; /// } /// ``` #[wasm_export( @@ -97,11 +97,8 @@ impl RaindexClient { ) .await?; - let (best_orderbook, best_sim) = selection::select_best_orderbook_simulation( - candidates.clone(), - req.mode, - req.price_cap, - )?; + let (best_raindex, best_sim) = + selection::select_best_raindex_simulation(candidates.clone(), req.mode, req.price_cap)?; let mut built = build_take_orders_config_from_simulation(best_sim.clone(), req.mode, req.price_cap)? @@ -111,7 +108,7 @@ impl RaindexClient { rpc_urls: rpc_urls.clone(), sell_token: req.sell_token, taker: req.taker, - orderbook: best_orderbook, + raindex: best_raindex, mode: req.mode, price_cap: req.price_cap, }; @@ -126,7 +123,7 @@ impl RaindexClient { for _ in 0..built.config.orders.len() { let sim_result = simulate_take_orders( &provider, - best_orderbook, + best_raindex, req.taker, &built.config, Some(block_number), @@ -136,7 +133,7 @@ impl RaindexClient { match sim_result { Ok(()) => { return result::build_calldata_result( - best_orderbook, + best_raindex, built, req.mode, req.price_cap, @@ -145,7 +142,7 @@ impl RaindexClient { Err(sim_error) => { if let Some(failing_idx) = find_failing_order_index( &provider, - best_orderbook, + best_raindex, req.taker, &built.config, Some(block_number), diff --git a/crates/common/src/raindex_client/take_orders/result.rs b/crates/common/src/raindex_client/take_orders/result.rs index c456d12555..9ddf4419f3 100644 --- a/crates/common/src/raindex_client/take_orders/result.rs +++ b/crates/common/src/raindex_client/take_orders/result.rs @@ -3,7 +3,7 @@ use crate::take_orders::{build_approval_calldata, BuiltTakeOrdersConfig, ParsedT use alloy::primitives::{Address, Bytes}; use alloy::sol_types::SolCall; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::takeOrders4Call; +use raindex_bindings::IRaindexV6::takeOrders4Call; use serde::{Deserialize, Serialize}; use std::ops::{Div, Mul}; use wasm_bindgen_utils::prelude::*; @@ -19,7 +19,7 @@ pub(crate) struct ApprovalInfoData { #[derive(Clone)] pub(crate) struct TakeOrdersInfoData { - pub orderbook: Address, + pub raindex: Address, pub calldata: Bytes, pub effective_price: Float, pub prices: Vec, @@ -110,7 +110,7 @@ impl ApprovalInfo { #[serde(rename_all = "camelCase")] #[wasm_bindgen] pub struct TakeOrdersInfo { - orderbook: Address, + raindex: Address, calldata: Bytes, effective_price: Float, prices: Vec, @@ -120,7 +120,7 @@ pub struct TakeOrdersInfo { impl TakeOrdersInfo { pub(crate) fn new( - orderbook: Address, + raindex: Address, calldata: Bytes, effective_price: Float, prices: Vec, @@ -128,7 +128,7 @@ impl TakeOrdersInfo { max_sell_cap: Float, ) -> Self { Self { - orderbook, + raindex, calldata, effective_price, prices, @@ -142,8 +142,8 @@ impl TakeOrdersInfo { #[wasm_bindgen] impl TakeOrdersInfo { #[wasm_bindgen(getter, unchecked_return_type = "Hex")] - pub fn orderbook(&self) -> String { - self.orderbook.to_string() + pub fn raindex(&self) -> String { + self.raindex.to_string() } #[wasm_bindgen(getter, unchecked_return_type = "Hex")] pub fn calldata(&self) -> String { @@ -169,8 +169,8 @@ impl TakeOrdersInfo { #[cfg(not(target_family = "wasm"))] impl TakeOrdersInfo { - pub fn orderbook(&self) -> Address { - self.orderbook + pub fn raindex(&self) -> Address { + self.raindex } pub fn calldata(&self) -> &Bytes { &self.calldata @@ -204,7 +204,7 @@ impl std::fmt::Debug for TakeOrdersCalldataResult { .finish(), TakeOrdersCalldataResultInner::Ready(data) => f .debug_struct("TakeOrdersCalldataResult::Ready") - .field("orderbook", &data.orderbook) + .field("raindex", &data.raindex) .finish(), } } @@ -256,7 +256,7 @@ impl TakeOrdersCalldataResult { match &self.inner { TakeOrdersCalldataResultInner::NeedsApproval(_) => None, TakeOrdersCalldataResultInner::Ready(data) => Some(TakeOrdersInfo::new( - data.orderbook, + data.raindex, data.calldata.clone(), data.effective_price, data.prices.clone(), @@ -294,7 +294,7 @@ impl TakeOrdersCalldataResult { match &self.inner { TakeOrdersCalldataResultInner::NeedsApproval(_) => None, TakeOrdersCalldataResultInner::Ready(data) => Some(TakeOrdersInfo::new( - data.orderbook, + data.raindex, data.calldata.clone(), data.effective_price, data.prices.clone(), @@ -374,7 +374,7 @@ pub(crate) fn build_approval_result( } pub(crate) fn build_calldata_result( - orderbook: Address, + raindex_addr: Address, built_config: BuiltTakeOrdersConfig, mode: ParsedTakeOrdersMode, price_cap: Float, @@ -410,7 +410,7 @@ pub(crate) fn build_calldata_result( }; Ok(TakeOrdersCalldataResult::ready(TakeOrdersInfoData { - orderbook, + raindex: raindex_addr, calldata, effective_price, prices, @@ -422,12 +422,12 @@ pub(crate) fn build_calldata_result( #[cfg(all(test, not(target_family = "wasm")))] mod tests { use super::*; - use crate::raindex_client::take_orders::selection::select_best_orderbook_simulation; + use crate::raindex_client::take_orders::selection::select_best_raindex_simulation; use crate::take_orders::build_take_orders_config_from_simulation; use crate::test_helpers::candidates::make_candidate; use alloy::primitives::U256; - use rain_orderbook_bindings::IRaindexV6::takeOrders4Call; - use rain_orderbook_bindings::IERC20::approveCall; + use raindex_bindings::IRaindexV6::takeOrders4Call; + use raindex_bindings::IERC20::approveCall; fn high_price_cap() -> Float { Float::parse("1000000".to_string()).unwrap() @@ -449,27 +449,27 @@ mod tests { #[test] fn test_build_calldata_result_produces_valid_calldata_buy_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = high_price_cap(); let mode = buy_up_to(buy_target); - let (_, sim) = select_best_orderbook_simulation(candidates, mode, price_cap).unwrap(); + let (_, sim) = select_best_raindex_simulation(candidates, mode, price_cap).unwrap(); let built = build_take_orders_config_from_simulation(sim, mode, price_cap) .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap); + let result = build_calldata_result(raindex_addr, built, mode, price_cap); assert!(result.is_ok()); let result = result.unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); - assert_eq!(take_orders_info.orderbook(), ob); + assert_eq!(take_orders_info.raindex(), raindex_addr); assert!(!take_orders_info.calldata().is_empty()); assert!(!take_orders_info.prices().is_empty()); @@ -484,27 +484,27 @@ mod tests { #[test] fn test_build_calldata_result_produces_valid_calldata_spend_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("100".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let spend_budget = Float::parse("20".to_string()).unwrap(); let price_cap = high_price_cap(); let mode = spend_up_to(spend_budget); - let (_, sim) = select_best_orderbook_simulation(candidates, mode, price_cap).unwrap(); + let (_, sim) = select_best_raindex_simulation(candidates, mode, price_cap).unwrap(); let built = build_take_orders_config_from_simulation(sim, mode, price_cap) .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap); + let result = build_calldata_result(raindex_addr, built, mode, price_cap); assert!(result.is_ok()); let result = result.unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); - assert_eq!(take_orders_info.orderbook(), ob); + assert_eq!(take_orders_info.raindex(), raindex_addr); assert!(!take_orders_info.calldata().is_empty()); assert!(!take_orders_info.prices().is_empty()); @@ -519,21 +519,21 @@ mod tests { #[test] fn test_build_calldata_result_effective_price_calculation() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = high_price_cap(); let mode = buy_up_to(buy_target); - let (_, sim) = select_best_orderbook_simulation(candidates, mode, price_cap).unwrap(); + let (_, sim) = select_best_raindex_simulation(candidates, mode, price_cap).unwrap(); let built = build_take_orders_config_from_simulation(sim, mode, price_cap) .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); @@ -546,22 +546,22 @@ mod tests { #[test] fn test_build_calldata_result_prices_match_legs() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = high_price_cap(); let mode = buy_up_to(buy_target); - let (_, sim) = select_best_orderbook_simulation(candidates, mode, price_cap).unwrap(); + let (_, sim) = select_best_raindex_simulation(candidates, mode, price_cap).unwrap(); let leg_count = sim.legs.len(); let built = build_take_orders_config_from_simulation(sim, mode, price_cap) .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); @@ -578,21 +578,21 @@ mod tests { #[test] fn test_build_calldata_result_expected_sell_and_max_sell_cap_buy_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let buy_target = Float::parse("10".to_string()).unwrap(); let price_cap = Float::parse("3".to_string()).unwrap(); let mode = buy_up_to(buy_target); - let (_, sim) = select_best_orderbook_simulation(candidates, mode, price_cap).unwrap(); + let (_, sim) = select_best_raindex_simulation(candidates, mode, price_cap).unwrap(); let built = build_take_orders_config_from_simulation(sim, mode, price_cap) .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); @@ -614,21 +614,21 @@ mod tests { #[test] fn test_build_calldata_result_expected_sell_and_max_sell_cap_spend_mode() { - let ob = Address::from([0x11u8; 20]); + let raindex_addr = Address::from([0x11u8; 20]); let max_output = Float::parse("100".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); - let candidate = make_candidate(ob, max_output, ratio); + let candidate = make_candidate(raindex_addr, max_output, ratio); let candidates = vec![candidate]; let spend_budget = Float::parse("20".to_string()).unwrap(); let price_cap = Float::parse("3".to_string()).unwrap(); let mode = spend_up_to(spend_budget); - let (_, sim) = select_best_orderbook_simulation(candidates, mode, price_cap).unwrap(); + let (_, sim) = select_best_raindex_simulation(candidates, mode, price_cap).unwrap(); let built = build_take_orders_config_from_simulation(sim, mode, price_cap) .unwrap() .unwrap(); - let result = build_calldata_result(ob, built, mode, price_cap).unwrap(); + let result = build_calldata_result(raindex_addr, built, mode, price_cap).unwrap(); assert!(result.is_ready()); let take_orders_info = result.take_orders_info().unwrap(); diff --git a/crates/common/src/raindex_client/take_orders/selection.rs b/crates/common/src/raindex_client/take_orders/selection.rs index 28a2ec2a93..1f1673080d 100644 --- a/crates/common/src/raindex_client/take_orders/selection.rs +++ b/crates/common/src/raindex_client/take_orders/selection.rs @@ -46,15 +46,15 @@ pub(crate) fn worst_price(sim: &SimulationResult) -> Result, Raind Ok(max) } -pub(crate) fn select_best_orderbook_simulation( +pub(crate) fn select_best_raindex_simulation( candidates: Vec, mode: ParsedTakeOrdersMode, price_cap: Float, ) -> Result<(Address, SimulationResult), RaindexError> { - let mut orderbook_candidates: HashMap> = HashMap::new(); + let mut raindex_candidates: HashMap> = HashMap::new(); for candidate in candidates { - orderbook_candidates - .entry(candidate.orderbook) + raindex_candidates + .entry(candidate.raindex) .or_default() .push(candidate); } @@ -64,7 +64,7 @@ pub(crate) fn select_best_orderbook_simulation( let mut best_result: Option<(Address, SimulationResult)> = None; - for (orderbook, candidates) in orderbook_candidates { + for (raindex_addr, candidates) in raindex_candidates { let sim = if is_buy_mode { simulate_buy_over_candidates(candidates, target, price_cap)? } else { @@ -90,10 +90,10 @@ pub(crate) fn select_best_orderbook_simulation( match (sim_worst, best_worst) { (Some(sw), Some(bw)) => match cmp_float(&sw, &bw)? { std::cmp::Ordering::Less => true, - std::cmp::Ordering::Equal => orderbook < *best_addr, + std::cmp::Ordering::Equal => raindex_addr < *best_addr, std::cmp::Ordering::Greater => false, }, - _ => orderbook < *best_addr, + _ => raindex_addr < *best_addr, } } else { false @@ -102,7 +102,7 @@ pub(crate) fn select_best_orderbook_simulation( }; if is_better { - best_result = Some((orderbook, sim)); + best_result = Some((raindex_addr, sim)); } } @@ -133,7 +133,7 @@ mod tests { } #[test] - fn test_select_best_orderbook_single_orderbook() { + fn test_select_best_raindex_single_raindex() { let ob1 = Address::from([0x11u8; 20]); let max_output = Float::parse("10".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); @@ -142,7 +142,7 @@ mod tests { let buy_target = Float::parse("10".to_string()).unwrap(); let result = - select_best_orderbook_simulation(candidates, buy_up_to(buy_target), high_price_cap()); + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_ok()); let (addr, sim) = result.unwrap(); @@ -153,7 +153,7 @@ mod tests { } #[test] - fn test_select_best_orderbook_multiple_books_picks_best() { + fn test_select_best_raindex_multiple_books_picks_best() { let ob1 = Address::from([0x11u8; 20]); let ob2 = Address::from([0x22u8; 20]); @@ -169,7 +169,7 @@ mod tests { let buy_target = Float::parse("100".to_string()).unwrap(); let result = - select_best_orderbook_simulation(candidates, buy_up_to(buy_target), high_price_cap()); + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); @@ -179,7 +179,7 @@ mod tests { } #[test] - fn test_select_best_orderbook_skips_empty_sims() { + fn test_select_best_raindex_skips_empty_sims() { let ob1 = Address::from([0x11u8; 20]); let ob2 = Address::from([0x22u8; 20]); @@ -195,13 +195,13 @@ mod tests { let buy_target = Float::zero().unwrap(); let result = - select_best_orderbook_simulation(candidates, buy_up_to(buy_target), high_price_cap()); + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(matches!(result, Err(RaindexError::NoLiquidity))); } #[test] - fn test_select_best_orderbook_all_empty_returns_no_liquidity() { + fn test_select_best_raindex_all_empty_returns_no_liquidity() { let ob1 = Address::from([0x11u8; 20]); let ob2 = Address::from([0x22u8; 20]); @@ -217,14 +217,14 @@ mod tests { let buy_target = Float::zero().unwrap(); let result = - select_best_orderbook_simulation(candidates, buy_up_to(buy_target), high_price_cap()); + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_err()); assert!(matches!(result, Err(RaindexError::NoLiquidity))); } #[test] - fn test_select_best_orderbook_price_cap_filters_expensive() { + fn test_select_best_raindex_price_cap_filters_expensive() { let ob_expensive = Address::from([0x11u8; 20]); let ob_cheap = Address::from([0x22u8; 20]); @@ -241,20 +241,20 @@ mod tests { let buy_target = Float::parse("100".to_string()).unwrap(); let price_cap = Float::parse("2".to_string()).unwrap(); - let result = select_best_orderbook_simulation(candidates, buy_up_to(buy_target), price_cap); + let result = select_best_raindex_simulation(candidates, buy_up_to(buy_target), price_cap); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); assert_eq!( winner, ob_cheap, - "Should pick the cheap orderbook since expensive is filtered by price cap" + "Should pick the cheap raindex since expensive is filtered by price cap" ); let expected_output = Float::parse("50".to_string()).unwrap(); assert!(sim.total_output.eq(expected_output).unwrap()); } #[test] - fn test_select_best_orderbook_tiebreak_identical_totals_prefers_lower_address() { + fn test_select_best_raindex_tiebreak_identical_totals_prefers_lower_address() { let ob_higher = Address::from([0x22u8; 20]); let ob_lower = Address::from([0x11u8; 20]); @@ -268,27 +268,24 @@ mod tests { for _ in 0..20 { let candidates = vec![higher_candidate.clone(), lower_candidate.clone()]; - let result = select_best_orderbook_simulation( - candidates, - buy_up_to(buy_target), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); assert_eq!( winner, ob_lower, "Tie-break rule: when total_output amounts and worst prices are equal, \ - prefer the lower orderbook address (0x{:x} < 0x{:x})", + prefer the lower raindex address (0x{:x} < 0x{:x})", ob_lower, ob_higher ); assert_eq!(sim.legs.len(), 1); - assert_eq!(sim.legs[0].candidate.orderbook, ob_lower); + assert_eq!(sim.legs[0].candidate.raindex, ob_lower); } } #[test] - fn test_select_best_orderbook_tiebreak_identical_totals_prefers_lower_worst_price() { + fn test_select_best_raindex_tiebreak_identical_totals_prefers_lower_worst_price() { let ob_better_price = Address::from([0x22u8; 20]); let ob_worse_price = Address::from([0x11u8; 20]); @@ -303,26 +300,23 @@ mod tests { for _ in 0..20 { let candidates = vec![worse_candidate.clone(), better_candidate.clone()]; - let result = select_best_orderbook_simulation( - candidates, - buy_up_to(buy_target), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, buy_up_to(buy_target), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); assert_eq!( winner, ob_better_price, "Tie-break rule: when total_output amounts are equal, \ - prefer the orderbook with the lower worst price (ratio 0.9 < 1.1)" + prefer the raindex with the lower worst price (ratio 0.9 < 1.1)" ); assert_eq!(sim.legs.len(), 1); - assert_eq!(sim.legs[0].candidate.orderbook, ob_better_price); + assert_eq!(sim.legs[0].candidate.raindex, ob_better_price); } } #[test] - fn test_select_best_orderbook_spend_mode() { + fn test_select_best_raindex_spend_mode() { let ob1 = Address::from([0x11u8; 20]); let max_output = Float::parse("100".to_string()).unwrap(); let ratio = Float::parse("2".to_string()).unwrap(); @@ -330,11 +324,8 @@ mod tests { let candidates = vec![candidate]; let spend_budget = Float::parse("100".to_string()).unwrap(); - let result = select_best_orderbook_simulation( - candidates, - spend_up_to(spend_budget), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, spend_up_to(spend_budget), high_price_cap()); assert!(result.is_ok()); let (addr, sim) = result.unwrap(); @@ -346,7 +337,7 @@ mod tests { } #[test] - fn test_select_best_orderbook_spend_mode_prefers_higher_output() { + fn test_select_best_raindex_spend_mode_prefers_higher_output() { let ob_bad_rate = Address::from([0x11u8; 20]); let ob_good_rate = Address::from([0x22u8; 20]); @@ -362,17 +353,14 @@ mod tests { let candidates = vec![bad_rate_candidate, good_rate_candidate]; let spend_budget = Float::parse("100".to_string()).unwrap(); - let result = select_best_orderbook_simulation( - candidates, - spend_up_to(spend_budget), - high_price_cap(), - ); + let result = + select_best_raindex_simulation(candidates, spend_up_to(spend_budget), high_price_cap()); assert!(result.is_ok()); let (winner, sim) = result.unwrap(); assert_eq!( winner, ob_good_rate, - "Should pick orderbook with higher output (90) over one that can absorb more input but yields less output (50)" + "Should pick raindex with higher output (90) over one that can absorb more input but yields less output (50)" ); let expected_output = Float::parse("90".to_string()).unwrap(); assert!(sim.total_output.eq(expected_output).unwrap()); diff --git a/crates/common/src/raindex_client/take_orders/single.rs b/crates/common/src/raindex_client/take_orders/single.rs index 1e6741d48b..b4d0e27634 100644 --- a/crates/common/src/raindex_client/take_orders/single.rs +++ b/crates/common/src/raindex_client/take_orders/single.rs @@ -8,8 +8,8 @@ use crate::take_orders::{ }; use alloy::primitives::Address; use rain_math_float::Float; -use rain_orderbook_bindings::provider::mk_read_provider; -use rain_orderbook_bindings::IRaindexV6::OrderV4; +use raindex_bindings::provider::mk_read_provider; +use raindex_bindings::IRaindexV6::OrderV4; use std::ops::{Div, Mul}; #[cfg(target_family = "wasm")] use std::str::FromStr; @@ -53,9 +53,9 @@ pub fn build_candidate_from_quote( } #[cfg(target_family = "wasm")] - let orderbook = Address::from_str(&order.orderbook())?; + let raindex_addr = Address::from_str(&order.raindex())?; #[cfg(not(target_family = "wasm"))] - let orderbook = order.orderbook(); + let raindex_addr = order.raindex(); let order_v4: OrderV4 = order.try_into()?; let input_io_index = quote.pair.input_index; let output_io_index = quote.pair.output_index; @@ -65,7 +65,7 @@ pub fn build_candidate_from_quote( } Ok(Some(TakeOrderCandidate { - orderbook, + raindex: raindex_addr, order: order_v4, input_io_index, output_io_index, @@ -131,13 +131,13 @@ pub async fn execute_single_take( return Err(RaindexError::NoLiquidity); } - let orderbook = candidate.orderbook; + let raindex_addr = candidate.raindex; let approval_params = ApprovalCheckParams { rpc_urls: rpc_context.rpc_urls.to_vec(), sell_token: execution_params.sell_token, taker: execution_params.taker, - orderbook, + raindex: raindex_addr, mode: execution_params.mode, price_cap: execution_params.price_cap, }; @@ -216,7 +216,7 @@ pub async fn execute_single_take( let sim_result = simulate_take_orders( &provider, - orderbook, + raindex_addr, execution_params.taker, &built.config, rpc_context.block_number, @@ -225,7 +225,7 @@ pub async fn execute_single_take( match sim_result { Ok(()) => build_calldata_result( - orderbook, + raindex_addr, built, execution_params.mode, execution_params.price_cap, @@ -238,7 +238,7 @@ pub async fn execute_single_take( ))) } else if let Some(_failing_idx) = find_failing_order_index( &provider, - orderbook, + raindex_addr, execution_params.taker, &built.config, rpc_context.block_number, @@ -265,7 +265,7 @@ mod tests { use super::*; use crate::raindex_client::order_quotes::{RaindexOrderQuote, RaindexOrderQuoteValue}; use rain_math_float::Float; - use rain_orderbook_quote::Pair; + use raindex_quote::Pair; use std::ops::Mul; fn make_quote_value(max_output: Float, ratio: Float) -> RaindexOrderQuoteValue { @@ -348,8 +348,8 @@ mod tests { let ratio = Float::parse("1".to_string()).unwrap(); let quote = make_quote(0, 0, Some(make_quote_value(max_output, ratio)), false); - use crate::local_db::OrderbookIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::local_db::RaindexIdentifier; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::Address; use std::str::FromStr; @@ -357,7 +357,7 @@ mod tests { rt.block_on(async { use alloy::primitives::b256; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::F1; + use raindex_subgraph_client::utils::float::F1; use serde_json::json; let server = MockServer::start_async().await; @@ -382,7 +382,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -399,12 +399,12 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -431,9 +431,9 @@ mod tests { let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -449,8 +449,8 @@ mod tests { fn test_quote_no_data_returns_none() { let quote = make_quote(0, 0, None, true); - use crate::local_db::OrderbookIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::local_db::RaindexIdentifier; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::Address; use std::str::FromStr; @@ -458,7 +458,7 @@ mod tests { rt.block_on(async { use alloy::primitives::b256; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::F1; + use raindex_subgraph_client::utils::float::F1; use serde_json::json; let server = MockServer::start_async().await; @@ -483,7 +483,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -500,12 +500,12 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -532,9 +532,9 @@ mod tests { let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -552,8 +552,8 @@ mod tests { let ratio = Float::parse("1".to_string()).unwrap(); let quote = make_quote(0, 0, Some(make_quote_value(max_output, ratio)), true); - use crate::local_db::OrderbookIdentifier; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::local_db::RaindexIdentifier; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::Address; use std::str::FromStr; @@ -561,7 +561,7 @@ mod tests { rt.block_on(async { use alloy::primitives::b256; use httpmock::MockServer; - use rain_orderbook_subgraph_client::utils::float::F1; + use raindex_subgraph_client::utils::float::F1; use serde_json::json; let server = MockServer::start_async().await; @@ -586,7 +586,7 @@ mod tests { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -603,12 +603,12 @@ mod tests { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": CHAIN_ID_1_ORDERBOOK_ADDRESS }, + "raindex": { "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -635,9 +635,9 @@ mod tests { let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) diff --git a/crates/common/src/raindex_client/take_orders/single_tests.rs b/crates/common/src/raindex_client/take_orders/single_tests.rs index 5cae73b305..292a4019e2 100644 --- a/crates/common/src/raindex_client/take_orders/single_tests.rs +++ b/crates/common/src/raindex_client/take_orders/single_tests.rs @@ -1,4 +1,4 @@ -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use crate::raindex_client::order_quotes::RaindexOrderQuote; use crate::raindex_client::take_orders::single::{ build_candidate_from_quote, estimate_take_order, execute_single_take, RpcContext, @@ -22,8 +22,8 @@ use alloy::serde::WithOtherFields; use alloy::sol_types::SolCall; use httpmock::MockServer; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::takeOrders4Call; -use rain_orderbook_quote::Pair; +use raindex_bindings::IRaindexV6::takeOrders4Call; +use raindex_quote::Pair; use serde_json::json; use std::ops::{Div, Mul}; @@ -94,13 +94,13 @@ async fn test_single_order_take_happy_path_buy_up_to() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -109,7 +109,7 @@ async fn test_single_order_take_happy_path_buy_up_to() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -144,7 +144,7 @@ async fn test_single_order_take_happy_path_buy_up_to() { assert!(result.is_ready()); let result = result.take_orders_info().unwrap(); - assert_eq!(result.orderbook(), setup.orderbook); + assert_eq!(result.raindex(), setup.raindex); assert!(!result.calldata().is_empty()); assert_eq!( result.prices().len(), @@ -200,13 +200,13 @@ async fn test_single_order_take_happy_path_buy_exact() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -215,7 +215,7 @@ async fn test_single_order_take_happy_path_buy_exact() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -301,13 +301,13 @@ async fn test_single_order_take_happy_path_spend_up_to() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -316,7 +316,7 @@ async fn test_single_order_take_happy_path_spend_up_to() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -408,13 +408,13 @@ async fn test_single_order_take_no_capacity_returns_error() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -458,13 +458,13 @@ async fn test_single_order_take_invalid_io_index_returns_none() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -525,13 +525,13 @@ async fn test_single_order_take_buy_exact_insufficient_liquidity() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -540,7 +540,7 @@ async fn test_single_order_take_buy_exact_insufficient_liquidity() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -613,13 +613,13 @@ async fn test_single_order_take_price_exceeds_cap() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -628,7 +628,7 @@ async fn test_single_order_take_price_exceeds_cap() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -699,13 +699,13 @@ async fn test_single_order_take_failed_quote_returns_none() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -750,13 +750,13 @@ async fn test_single_order_take_preflight_insufficient_balance() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -797,7 +797,7 @@ async fn test_single_order_take_preflight_insufficient_balance() { ); let approval_info = result.approval_info().expect("Should have approval info"); assert_eq!(approval_info.token(), setup.token1); - assert_eq!(approval_info.spender(), setup.orderbook); + assert_eq!(approval_info.spender(), setup.raindex); } #[tokio::test] @@ -835,13 +835,13 @@ async fn test_single_order_take_preflight_insufficient_allowance() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -900,7 +900,7 @@ async fn test_single_order_take_preflight_insufficient_allowance() { ); let approval_info = result.approval_info().expect("Should have approval info"); assert_eq!(approval_info.token(), setup.token1); - assert_eq!(approval_info.spender(), setup.orderbook); + assert_eq!(approval_info.spender(), setup.raindex); } #[tokio::test] @@ -938,13 +938,13 @@ async fn test_single_order_take_approval_then_ready_flow() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1005,7 +1005,7 @@ async fn test_single_order_take_approval_then_ready_flow() { let approval_info = result.approval_info().expect("Should have approval info"); assert_eq!(approval_info.token(), setup.token1); - assert_eq!(approval_info.spender(), setup.orderbook); + assert_eq!(approval_info.spender(), setup.raindex); assert!( !approval_info.calldata().is_empty(), "Approval calldata should not be empty" @@ -1050,7 +1050,7 @@ async fn test_single_order_take_approval_then_ready_flow() { let take_info = result .take_orders_info() .expect("Should have take orders info"); - assert_eq!(take_info.orderbook(), setup.orderbook); + assert_eq!(take_info.raindex(), setup.raindex); assert!( !take_info.calldata().is_empty(), "Take orders calldata should not be empty" @@ -1101,13 +1101,13 @@ async fn test_single_order_take_calldata_encoding_buy_mode() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1116,7 +1116,7 @@ async fn test_single_order_take_calldata_encoding_buy_mode() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1208,13 +1208,13 @@ async fn test_single_order_take_expected_spend_calculation() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1223,7 +1223,7 @@ async fn test_single_order_take_expected_spend_calculation() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1316,13 +1316,13 @@ async fn test_single_order_take_spend_exact_mode() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1331,7 +1331,7 @@ async fn test_single_order_take_spend_exact_mode() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1545,13 +1545,13 @@ async fn test_single_order_take_spend_exact_insufficient_liquidity() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1560,7 +1560,7 @@ async fn test_single_order_take_spend_exact_insufficient_liquidity() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1633,13 +1633,13 @@ async fn test_single_order_take_calldata_encoding_spend_mode() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1648,7 +1648,7 @@ async fn test_single_order_take_calldata_encoding_spend_mode() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; @@ -1766,13 +1766,13 @@ async fn test_single_order_take_expected_receive_calculation() { 123, &setup.local_evm.url().to_string(), &sg_server.url("/sg"), - &setup.orderbook.to_string(), + &setup.raindex.to_string(), ); let client = RaindexClient::new(vec![yaml], None, None).await.unwrap(); let order = client - .get_order_by_hash(&OrderbookIdentifier::new(123, setup.orderbook), order_hash) + .get_order_by_hash(&RaindexIdentifier::new(123, setup.raindex), order_hash) .await .unwrap(); @@ -1781,7 +1781,7 @@ async fn test_single_order_take_expected_receive_calculation() { &setup, setup.token1, taker, - setup.orderbook, + setup.raindex, U256::from(10).pow(U256::from(22)), ) .await; diff --git a/crates/common/src/raindex_client/trades.rs b/crates/common/src/raindex_client/trades.rs index 2f1d30ac85..80e6b9b001 100644 --- a/crates/common/src/raindex_client/trades.rs +++ b/crates/common/src/raindex_client/trades.rs @@ -3,7 +3,7 @@ use super::orders::{OrdersDataSource, SubgraphOrders}; use super::ClientRef; use super::*; use crate::local_db::query::fetch_order_trades::LocalDbOrderTrade; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use crate::raindex_client::QuerySource; use crate::raindex_client::{ orders::RaindexOrder, @@ -11,7 +11,7 @@ use crate::raindex_client::{ vaults::{LocalTradeBalanceInfo, LocalTradeTokenInfo, RaindexVaultBalanceChange}, }; use alloy::primitives::{Address, Bytes, B256, U256}; -use rain_orderbook_subgraph_client::types::{common::SgTrade, Id}; +use raindex_subgraph_client::types::{common::SgTrade, Id}; use std::str::FromStr; #[cfg(target_family = "wasm")] use wasm_bindgen_utils::prelude::js_sys::BigInt; @@ -26,7 +26,7 @@ pub struct RaindexTrade { input_vault_balance_change: RaindexVaultBalanceChange, output_vault_balance_change: RaindexVaultBalanceChange, timestamp: U256, - orderbook: Address, + raindex: Address, } #[cfg(target_family = "wasm")] #[wasm_bindgen] @@ -57,8 +57,8 @@ impl RaindexTrade { .map_err(|e| RaindexError::JsError(e.to_string().into())) } #[wasm_bindgen(getter, unchecked_return_type = "Address")] - pub fn orderbook(&self) -> String { - self.orderbook.to_string() + pub fn raindex(&self) -> String { + self.raindex.to_string() } } #[cfg(not(target_family = "wasm"))] @@ -81,8 +81,8 @@ impl RaindexTrade { pub fn timestamp(&self) -> U256 { self.timestamp } - pub fn orderbook(&self) -> Address { - self.orderbook + pub fn raindex(&self) -> Address { + self.raindex } } @@ -129,29 +129,41 @@ impl RaindexOrder { ) -> Result, RaindexError> { let chain_id = self.chain_id(); #[cfg(target_family = "wasm")] - let orderbook = Address::from_str(&self.orderbook())?; + let raindex_addr = Address::from_str(&self.raindex())?; #[cfg(not(target_family = "wasm"))] - let orderbook = self.orderbook(); + let raindex_addr = self.raindex(); #[cfg(target_family = "wasm")] let order_hash = B256::from_str(&self.order_hash())?; #[cfg(not(target_family = "wasm"))] let order_hash = B256::from_str(&self.order_hash().to_string())?; - let ob_id = OrderbookIdentifier::new(chain_id, orderbook); + let raindex_id = RaindexIdentifier::new(chain_id, raindex_addr); let raindex_client = self.get_raindex_client(); match raindex_client.query_source(chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::clone(&raindex_client)); local_source - .trades_list(&ob_id, &order_hash, start_timestamp, end_timestamp, page) + .trades_list( + &raindex_id, + &order_hash, + start_timestamp, + end_timestamp, + page, + ) .await } QuerySource::Subgraph => { let subgraph_source = SubgraphOrders::new(&raindex_client); subgraph_source - .trades_list(&ob_id, &order_hash, start_timestamp, end_timestamp, page) + .trades_list( + &raindex_id, + &order_hash, + start_timestamp, + end_timestamp, + page, + ) .await } } @@ -227,29 +239,29 @@ impl RaindexOrder { ) -> Result { let chain_id = self.chain_id(); #[cfg(target_family = "wasm")] - let orderbook = Address::from_str(&self.orderbook())?; + let raindex_addr = Address::from_str(&self.raindex())?; #[cfg(not(target_family = "wasm"))] - let orderbook = self.orderbook(); + let raindex_addr = self.raindex(); #[cfg(target_family = "wasm")] let order_hash = B256::from_str(&self.order_hash())?; #[cfg(not(target_family = "wasm"))] let order_hash = self.order_hash(); - let ob_id = OrderbookIdentifier::new(chain_id, orderbook); + let raindex_id = RaindexIdentifier::new(chain_id, raindex_addr); let raindex_client = self.get_raindex_client(); match raindex_client.query_source(chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbOrders::new(&local_db, ClientRef::clone(&raindex_client)); local_source - .trades_count(&ob_id, &order_hash, start_timestamp, end_timestamp) + .trades_count(&raindex_id, &order_hash, start_timestamp, end_timestamp) .await } QuerySource::Subgraph => { let subgraph_source = SubgraphOrders::new(&raindex_client); subgraph_source - .trades_count(&ob_id, &order_hash, start_timestamp, end_timestamp) + .trades_count(&raindex_id, &order_hash, start_timestamp, end_timestamp) .await } } @@ -257,7 +269,7 @@ impl RaindexOrder { } impl RaindexOrder { pub async fn get_trade_detail(&self, trade_id: Bytes) -> Result { - let client = self.get_orderbook_client()?; + let client = self.get_raindex_subgraph_client()?; RaindexTrade::try_from_sg_trade( self.chain_id(), client @@ -284,7 +296,7 @@ impl RaindexTrade { trade.output_vault_balance_change, )?, timestamp: U256::from_str(&trade.timestamp.0)?, - orderbook: Address::from_str(&trade.orderbook.id.0)?, + raindex: Address::from_str(&trade.raindex.id.0)?, }) } @@ -301,7 +313,7 @@ impl RaindexTrade { let input_change = RaindexVaultBalanceChange::try_from_local_trade_side( chain_id, - trade.orderbook, + trade.raindex, &transaction, trade.input_vault_id, LocalTradeTokenInfo { @@ -320,7 +332,7 @@ impl RaindexTrade { let output_change = RaindexVaultBalanceChange::try_from_local_trade_side( chain_id, - trade.orderbook, + trade.raindex, &transaction, trade.output_vault_id, LocalTradeTokenInfo { @@ -344,7 +356,7 @@ impl RaindexTrade { input_vault_balance_change: input_change, output_vault_balance_change: output_change, timestamp: U256::from(trade.block_timestamp), - orderbook: trade.orderbook, + raindex: trade.raindex, }) } } @@ -368,7 +380,7 @@ mod test_helpers { }; use alloy::primitives::{address, b256, bytes, Address, Bytes, B256, U256}; use js_sys::Array; - use rain_orderbook_subgraph_client::utils::float::{F1, F2, F3, NEG2}; + use raindex_subgraph_client::utils::float::{F1, F2, F3, NEG2}; use serde_json::{self, json}; use std::collections::HashMap; use std::str::FromStr; @@ -382,7 +394,7 @@ mod test_helpers { input_vault: LocalDbVault, output_vault: LocalDbVault, trade: LocalDbOrderTrade, - orderbook_address: Address, + raindex_address: Address, order_hash: B256, input_token: Address, output_token: Address, @@ -394,7 +406,7 @@ mod test_helpers { trade_count: u64, ) -> LocalTradeFixture { const CHAIN_ID: u32 = 42161; - let orderbook_address = address!("0x2f209e5b67a33b8fe96e28f24628df6da301c8eb"); + let raindex_address = address!("0x2f209e5b67a33b8fe96e28f24628df6da301c8eb"); let order_hash = b256!("0x0000000000000000000000000000000000000000000000000000000000000abc"); let owner = address!("0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); @@ -429,7 +441,7 @@ mod test_helpers { vault_id: input_vault_id, token: input_token, owner, - orderbook_address, + raindex_address, token_name: "Token A".to_string(), token_symbol: "TKNA".to_string(), token_decimals: 18, @@ -443,7 +455,7 @@ mod test_helpers { vault_id: output_vault_id, token: output_token, owner, - orderbook_address, + raindex_address, token_name: "Token B".to_string(), token_symbol: "TKNB".to_string(), token_decimals: 6, @@ -470,7 +482,7 @@ mod test_helpers { owner, block_timestamp: 1_700_000_010, block_number: 123_456, - orderbook_address, + raindex_address, order_bytes: order_bytes.clone(), transaction_hash, inputs: Some(order_inputs_payload), @@ -482,7 +494,7 @@ mod test_helpers { let trade = LocalDbOrderTrade { trade_kind: "take".into(), - orderbook: orderbook_address, + raindex: raindex_address, order_hash: order_hash.clone(), order_owner: owner, order_nonce: "0".into(), @@ -513,7 +525,7 @@ mod test_helpers { input_vault, output_vault, trade, - orderbook_address, + raindex_address, order_hash, input_token, output_token, @@ -645,7 +657,7 @@ mod test_helpers { let order = client .get_order_by_hash( - &OrderbookIdentifier::new(42161, fixture.orderbook_address), + &RaindexIdentifier::new(42161, fixture.raindex_address), fixture.order_hash.clone(), ) .await @@ -659,8 +671,8 @@ mod test_helpers { assert_eq!(trade.id(), trade_id); assert_eq!(trade.order_hash(), fixture.order_hash.to_string()); assert_eq!( - trade.orderbook().to_lowercase(), - fixture.orderbook_address.to_string().to_lowercase() + trade.raindex().to_lowercase(), + fixture.raindex_address.to_string().to_lowercase() ); let transaction = trade.transaction(); @@ -744,7 +756,7 @@ mod test_helpers { let order = client .get_order_by_hash( - &OrderbookIdentifier::new(42161, fixture.orderbook_address), + &RaindexIdentifier::new(42161, fixture.raindex_address), fixture.order_hash.clone(), ) .await @@ -763,13 +775,13 @@ mod test_helpers { mod non_wasm { use super::*; use crate::{ - local_db::OrderbookIdentifier, - raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}, + local_db::RaindexIdentifier, + raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}, }; use alloy::primitives::{b256, Bytes}; use httpmock::MockServer; use rain_math_float::Float; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; fn get_order1_json() -> Value { @@ -791,7 +803,7 @@ mod test_helpers { "symbol": "sFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [ @@ -819,7 +831,7 @@ mod test_helpers { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } @@ -837,7 +849,7 @@ mod test_helpers { "symbol": "WFLR", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" }, "ordersAsOutput": [], @@ -865,13 +877,13 @@ mod test_helpers { "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [], - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" } } ], - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "active": true, "timestampAdded": "1739448802", @@ -927,7 +939,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700000000" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345678" }, "trade": { @@ -964,7 +976,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700000000" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345678" }, "trade": { @@ -974,7 +986,7 @@ mod test_helpers { } }, "timestamp": "0", - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345678" } }) @@ -1017,7 +1029,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700086400" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345679" }, "trade": { @@ -1054,7 +1066,7 @@ mod test_helpers { "blockNumber": "0", "timestamp": "1700086400" }, - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345679" }, "trade": { @@ -1064,7 +1076,7 @@ mod test_helpers { } }, "timestamp": "1700086400", - "orderbook": { + "raindex": { "id": "0x1234567890abcdef1234567890abcdef12345679" } } @@ -1113,9 +1125,9 @@ mod test_helpers { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -1258,7 +1270,7 @@ mod test_helpers { ); assert_eq!(trade1.timestamp(), U256::ZERO); assert_eq!( - trade1.orderbook(), + trade1.raindex(), Address::from_str("0x1234567890abcdef1234567890abcdef12345678").unwrap() ); assert_eq!(trade1.order_hash(), Bytes::from_str("0x0123").unwrap()); @@ -1301,9 +1313,9 @@ mod test_helpers { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) @@ -1436,7 +1448,7 @@ mod test_helpers { ); assert_eq!(trade.timestamp(), U256::ZERO); assert_eq!( - trade.orderbook(), + trade.raindex(), Address::from_str("0x1234567890abcdef1234567890abcdef12345678").unwrap() ); assert_eq!(trade.order_hash(), Bytes::from_str("0x0123").unwrap()); @@ -1486,9 +1498,9 @@ mod test_helpers { .unwrap(); let order = raindex_client .get_order_by_hash( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), ) diff --git a/crates/common/src/raindex_client/transactions.rs b/crates/common/src/raindex_client/transactions.rs index 309125c386..43fdd88264 100644 --- a/crates/common/src/raindex_client/transactions.rs +++ b/crates/common/src/raindex_client/transactions.rs @@ -1,14 +1,14 @@ use std::str::FromStr; use super::*; -use crate::local_db::OrderbookIdentifier; +use crate::local_db::RaindexIdentifier; use crate::raindex_client::local_db::transactions::LocalDbTransactions; use crate::raindex_client::QuerySource; use alloy::primitives::{Address, B256, U256}; #[cfg(target_family = "wasm")] use gloo_timers::future::TimeoutFuture; -use rain_orderbook_subgraph_client::types::{common::SgTransaction, Id}; -use rain_orderbook_subgraph_client::OrderbookSubgraphClientError; +use raindex_subgraph_client::types::{common::SgTransaction, Id}; +use raindex_subgraph_client::RaindexSubgraphClientError; use serde::{Deserialize, Serialize}; #[cfg(not(target_family = "wasm"))] use std::time::Duration; @@ -126,11 +126,11 @@ impl RaindexClient { #[wasm_export(js_name = "chainId", param_description = "Chain ID for the network")] chain_id: u32, #[wasm_export( - js_name = "orderbookAddress", - param_description = "Orderbook contract address", + js_name = "raindexAddress", + param_description = "Raindex contract address", unchecked_param_type = "Address" )] - orderbook_address: String, + raindex_address: String, #[wasm_export( js_name = "txHash", param_description = "Transaction hash", @@ -148,11 +148,11 @@ impl RaindexClient { )] interval_ms: Option, ) -> Result { - let orderbook_address = Address::from_str(&orderbook_address)?; + let raindex_address = Address::from_str(&raindex_address)?; let tx_hash = B256::from_str(&tx_hash)?; self.get_transaction( chain_id, - orderbook_address, + raindex_address, tx_hash, max_attempts.map(|v| v as usize), interval_ms.map(|v| v as u64), @@ -164,7 +164,7 @@ impl RaindexClient { pub async fn get_transaction( &self, chain_id: u32, - orderbook_address: Address, + raindex_address: Address, tx_hash: B256, max_attempts: Option, interval_ms: Option, @@ -177,10 +177,10 @@ impl RaindexClient { match self.query_source(chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbTransactions::new(&local_db); - let ob_id = OrderbookIdentifier::new(chain_id, orderbook_address); + let raindex_id = RaindexIdentifier::new(chain_id, raindex_address); for attempt in 1..=attempts { - if let Some(tx) = local_source.get_by_tx_hash(&ob_id, tx_hash).await? { + if let Some(tx) = local_source.get_by_tx_hash(&raindex_id, tx_hash).await? { return Ok(tx); } if attempt < attempts { @@ -191,7 +191,7 @@ impl RaindexClient { Err(RaindexError::TransactionIndexingTimeout { tx_hash, attempts }) } QuerySource::Subgraph => { - let client = self.get_orderbook_client(orderbook_address)?; + let client = self.get_raindex_subgraph_client(raindex_address)?; for attempt in 1..=attempts { match client .transaction_detail(Id::new(tx_hash.to_string())) @@ -200,7 +200,7 @@ impl RaindexClient { Ok(transaction) => { return transaction.try_into(); } - Err(OrderbookSubgraphClientError::Empty) => { + Err(RaindexSubgraphClientError::Empty) => { if attempt < attempts { sleep_ms(interval_ms).await; continue; @@ -236,7 +236,7 @@ mod test_helpers { #[cfg(not(target_family = "wasm"))] mod non_wasm { use super::*; - use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_ORDERBOOK_ADDRESS}; + use crate::raindex_client::tests::{get_test_yaml, CHAIN_ID_1_RAINDEX_ADDRESS}; use alloy::primitives::b256; use httpmock::MockServer; use serde_json::{json, Value}; @@ -286,7 +286,7 @@ mod test_helpers { let tx = raindex_client .get_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), None, None, @@ -330,7 +330,7 @@ mod test_helpers { let tx = raindex_client .get_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(DEFAULT_TRANSACTION_POLL_ATTEMPTS), Some(10), @@ -369,7 +369,7 @@ mod test_helpers { let err = raindex_client .get_transaction( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), b256!("0x0000000000000000000000000000000000000000000000000000000000000123"), Some(3), Some(10), diff --git a/crates/common/src/raindex_client/vaults.rs b/crates/common/src/raindex_client/vaults.rs index f265750108..2b28d254c1 100644 --- a/crates/common/src/raindex_client/vaults.rs +++ b/crates/common/src/raindex_client/vaults.rs @@ -3,7 +3,7 @@ use super::*; use crate::local_db::query::fetch_order_vaults_volume::LocalDbVaultVolume; use crate::local_db::query::fetch_vaults::LocalDbVault; use crate::local_db::{ - query::fetch_vault_balance_changes::LocalDbVaultBalanceChange, OrderbookIdentifier, + query::fetch_vault_balance_changes::LocalDbVaultBalanceChange, RaindexIdentifier, }; use crate::raindex_client::local_db::vaults::LocalDbVaults; use crate::raindex_client::QuerySource; @@ -24,18 +24,17 @@ use alloy::{ }; use async_trait::async_trait; use rain_math_float::Float; -use rain_orderbook_bindings::{IRaindexV6::deposit4Call, IERC20::approveCall}; -use rain_orderbook_subgraph_client::{ +use raindex_bindings::{IRaindexV6::deposit4Call, IERC20::approveCall}; +use raindex_subgraph_client::{ performance::vol::{VaultVolume, VolumeDetails}, types::{ common::{ - SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgTradeVaultBalanceChange, - SgVault, SgVaultBalanceChangeType, SgVaultBalanceChangeUnwrapped, - SgVaultsListFilterArgs, + SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgTradeVaultBalanceChange, SgVault, + SgVaultBalanceChangeType, SgVaultBalanceChangeUnwrapped, SgVaultsListFilterArgs, }, Id, }, - MultiOrderbookSubgraphClient, OrderbookSubgraphClient, OrderbookSubgraphClientError, + MultiRaindexSubgraphClient, RaindexSubgraphClient, RaindexSubgraphClientError, SgPaginationArgs, }; use std::str::FromStr; @@ -65,7 +64,7 @@ pub(crate) trait VaultsDataSource { async fn get_by_id( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, vault_id: &Bytes, ) -> Result, RaindexError>; @@ -91,11 +90,11 @@ pub enum RaindexVaultType { } impl_wasm_traits!(RaindexVaultType); -/// Represents a vault with balance and token information within a given orderbook. +/// Represents a vault with balance and token information within a given raindex. /// /// A vault is a fundamental component that holds tokens and participates in order execution. /// Each vault has a unique identifier, current balance, associated token metadata, and -/// belongs to a specific orderbook contract on the blockchain. +/// belongs to a specific raindex contract on the blockchain. /// /// Vaults can serve different roles in relation to orders - they can provide tokens (input), /// receive tokens (output), or both (input/output), depending on the trading algorithm. @@ -112,7 +111,7 @@ pub struct RaindexVault { balance: Float, formatted_balance: String, token: RaindexVaultToken, - orderbook: Address, + raindex: Address, orders_as_inputs: Vec, orders_as_outputs: Vec, } @@ -161,8 +160,8 @@ impl RaindexVault { self.token.clone() } #[wasm_bindgen(getter, unchecked_return_type = "Address")] - pub fn orderbook(&self) -> String { - self.orderbook.to_string() + pub fn raindex(&self) -> String { + self.raindex.to_string() } #[wasm_bindgen(getter = ordersAsInput)] pub fn orders_as_inputs(&self) -> Vec { @@ -200,8 +199,8 @@ impl RaindexVault { pub fn token(&self) -> RaindexVaultToken { self.token.clone() } - pub fn orderbook(&self) -> Address { - self.orderbook + pub fn raindex(&self) -> Address { + self.raindex } pub fn orders_as_inputs(&self) -> Vec { self.orders_as_inputs.clone() @@ -320,8 +319,9 @@ impl RaindexVaultToken { #[wasm_export] impl RaindexVault { #[wasm_export(skip)] - pub fn get_orderbook_client(&self) -> Result { - self.raindex_client.get_orderbook_client(self.orderbook) + pub fn get_raindex_subgraph_client(&self) -> Result { + self.raindex_client + .get_raindex_subgraph_client(self.raindex) } /// Fetches balance change history for a vault @@ -467,7 +467,7 @@ impl RaindexVault { }; let transaction_args = TransactionArgs { - orderbook_address: self.orderbook, + raindex_address: self.raindex, rpcs: rpcs.iter().map(|rpc| rpc.to_string()).collect(), ..Default::default() }; @@ -477,7 +477,7 @@ impl RaindexVault { /// Generates ERC20 approval calldata for vault deposits /// - /// Creates the contract calldata needed to approve the orderbook contract to spend + /// Creates the contract calldata needed to approve the raindex contract to spend /// tokens for a vault deposit, but only if additional approval is needed. /// /// ## Examples @@ -516,7 +516,7 @@ impl RaindexVault { } let calldata = approveCall { - spender: transaction_args.orderbook_address, + spender: transaction_args.raindex_address, amount: amount.to_fixed_decimal(self.token.decimals)?, } .abi_encode(); @@ -526,7 +526,7 @@ impl RaindexVault { /// Gets the current ERC20 allowance for a vault /// - /// Determines how much the orderbook contract is currently approved to spend + /// Determines how much the raindex contract is currently approved to spend /// on behalf of the vault owner. /// /// ## Examples @@ -701,7 +701,7 @@ pub struct RaindexVaultBalanceChange { formatted_old_balance: String, timestamp: U256, transaction: RaindexTransaction, - orderbook: Address, + raindex: Address, } #[cfg(target_family = "wasm")] #[wasm_bindgen] @@ -757,8 +757,8 @@ impl RaindexVaultBalanceChange { self.transaction.clone() } #[wasm_bindgen(getter, unchecked_return_type = "Address")] - pub fn orderbook(&self) -> String { - self.orderbook.to_string() + pub fn raindex(&self) -> String { + self.raindex.to_string() } } #[cfg(not(target_family = "wasm"))] @@ -799,8 +799,8 @@ impl RaindexVaultBalanceChange { pub fn transaction(&self) -> RaindexTransaction { self.transaction.clone() } - pub fn orderbook(&self) -> Address { - self.orderbook + pub fn raindex(&self) -> Address { + self.raindex } } @@ -850,7 +850,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance, timestamp: U256::from_str(&balance_change.timestamp.0)?, transaction: RaindexTransaction::try_from(balance_change.transaction)?, - orderbook: Address::from_str(&balance_change.orderbook.id.0)?, + raindex: Address::from_str(&balance_change.raindex.id.0)?, }) } } @@ -888,7 +888,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance, timestamp: U256::from_str(&balance_change.timestamp.0)?, transaction: RaindexTransaction::try_from(balance_change.transaction)?, - orderbook: Address::from_str(&balance_change.orderbook.id.0)?, + raindex: Address::from_str(&balance_change.raindex.id.0)?, }) } } @@ -917,7 +917,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance: old_balance.format()?, timestamp: U256::from_str(&deposit.timestamp.0)?, transaction: RaindexTransaction::try_from(deposit.transaction)?, - orderbook: Address::from_str(&deposit.orderbook.id.0)?, + raindex: Address::from_str(&deposit.raindex.id.0)?, }) } SgVaultBalanceChangeType::Withdrawal(withdrawal) => { @@ -938,7 +938,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance: old_balance.format()?, timestamp: U256::from_str(&withdrawal.timestamp.0)?, transaction: RaindexTransaction::try_from(withdrawal.transaction)?, - orderbook: Address::from_str(&withdrawal.orderbook.id.0)?, + raindex: Address::from_str(&withdrawal.raindex.id.0)?, }) } SgVaultBalanceChangeType::TradeVaultBalanceChange(trade_change) => { @@ -962,7 +962,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance: old_balance.format()?, timestamp: U256::from_str(&bounty.timestamp.0)?, transaction: RaindexTransaction::try_from(bounty.transaction)?, - orderbook: Address::from_str(&bounty.orderbook.id.0)?, + raindex: Address::from_str(&bounty.raindex.id.0)?, }) } SgVaultBalanceChangeType::Unknown => Err(RaindexError::InvalidVaultBalanceChangeType( @@ -1006,13 +1006,13 @@ impl RaindexVaultBalanceChange { formatted_old_balance, timestamp: U256::from(change.block_timestamp), transaction, - orderbook: vault.orderbook, + raindex: vault.raindex, }) } pub(crate) fn try_from_local_trade_side( chain_id: u32, - orderbook: Address, + raindex_addr: Address, transaction: &RaindexTransaction, vault_id: U256, token: LocalTradeTokenInfo, @@ -1061,7 +1061,7 @@ impl RaindexVaultBalanceChange { formatted_old_balance, timestamp: U256::from(block_timestamp), transaction: transaction.clone(), - orderbook, + raindex: raindex_addr, }) } } @@ -1351,11 +1351,11 @@ impl RaindexClient { )] chain_id: u32, #[wasm_export( - js_name = "orderbookAddress", - param_description = "Orderbook contract address", + js_name = "raindexAddress", + param_description = "Raindex contract address", unchecked_param_type = "Address" )] - orderbook_address: String, + raindex_address: String, #[wasm_export( js_name = "vaultId", param_description = "Unique vault identifier", @@ -1363,13 +1363,10 @@ impl RaindexClient { )] vault_id: String, ) -> Result { - let orderbook_address = Address::from_str(&orderbook_address)?; + let raindex_address = Address::from_str(&raindex_address)?; let vault_id = Bytes::from_str(&vault_id)?; - self.get_vault( - &OrderbookIdentifier::new(chain_id, orderbook_address), - vault_id, - ) - .await + self.get_vault(&RaindexIdentifier::new(chain_id, raindex_address), vault_id) + .await } /// Fetches all unique tokens that exist in vaults. @@ -1426,38 +1423,38 @@ impl RaindexClient { impl RaindexClient { pub async fn get_vault( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, vault_id: Bytes, ) -> Result { - let orderbook_cfg = self.get_orderbook_by_address(ob_id.orderbook_address)?; - if orderbook_cfg.network.chain_id != ob_id.chain_id { - return Err(RaindexError::OrderbookNotFound( - ob_id.orderbook_address.to_string(), - ob_id.chain_id, + let raindex_cfg = self.get_raindex_by_address(raindex_id.raindex_address)?; + if raindex_cfg.network.chain_id != raindex_id.chain_id { + return Err(RaindexError::RaindexNotFound( + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, )); } - match self.query_source(ob_id.chain_id) { + match self.query_source(raindex_id.chain_id) { QuerySource::LocalDb(local_db) => { let local_source = LocalDbVaults::new(&local_db, ClientRef::new(self.clone())); local_source - .get_by_id(ob_id, &vault_id) + .get_by_id(raindex_id, &vault_id) .await? .ok_or_else(|| { RaindexError::VaultNotFound( - ob_id.orderbook_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, vault_id.to_string(), ) }) } QuerySource::Subgraph => SubgraphVaults::new(self) - .get_by_id(ob_id, &vault_id) + .get_by_id(raindex_id, &vault_id) .await? .ok_or_else(|| { RaindexError::VaultNotFound( - ob_id.orderbook_address.to_string(), - ob_id.chain_id, + raindex_id.raindex_address.to_string(), + raindex_id.chain_id, vault_id.to_string(), ) }), @@ -1476,7 +1473,7 @@ impl VaultsDataSource for SubgraphVaults<'_> { ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); let multi_subgraph_args = self.client.get_multi_subgraph_args(chain_ids)?; - let client = MultiOrderbookSubgraphClient::new( + let client = MultiRaindexSubgraphClient::new( multi_subgraph_args.values().flatten().cloned().collect(), ); @@ -1518,18 +1515,21 @@ impl VaultsDataSource for SubgraphVaults<'_> { async fn get_by_id( &self, - ob_id: &OrderbookIdentifier, + raindex_id: &RaindexIdentifier, vault_id: &Bytes, ) -> Result, RaindexError> { let raindex_client = ClientRef::new(self.client.clone()); - let client = self.client.get_orderbook_client(ob_id.orderbook_address)?; + let client = self + .client + .get_raindex_subgraph_client(raindex_id.raindex_address)?; let vault = match client.vault_detail(Id::new(vault_id.to_string())).await { Ok(vault) => vault, - Err(OrderbookSubgraphClientError::Empty) => return Ok(None), + Err(RaindexSubgraphClientError::Empty) => return Ok(None), Err(err) => return Err(err.into()), }; - let vault = RaindexVault::try_from_sg_vault(raindex_client, ob_id.chain_id, vault, None)?; + let vault = + RaindexVault::try_from_sg_vault(raindex_client, raindex_id.chain_id, vault, None)?; Ok(Some(vault)) } @@ -1539,7 +1539,7 @@ impl VaultsDataSource for SubgraphVaults<'_> { page: Option, filter_types: Option<&[VaultBalanceChangeFilter]>, ) -> Result, RaindexError> { - let client = self.client.get_orderbook_client(vault.orderbook)?; + let client = self.client.get_raindex_subgraph_client(vault.raindex)?; let filter_typenames: Option> = filter_types.map(|filters| { filters @@ -1576,7 +1576,7 @@ impl VaultsDataSource for SubgraphVaults<'_> { chain_ids: Option>, ) -> Result, RaindexError> { let multi_subgraph_args = self.client.get_multi_subgraph_args(chain_ids)?; - let client = MultiOrderbookSubgraphClient::new( + let client = MultiRaindexSubgraphClient::new( multi_subgraph_args.values().flatten().cloned().collect(), ); @@ -1607,7 +1607,7 @@ pub struct GetVaultsFilters { #[tsify(optional, type = "Address[]")] pub tokens: Option>, #[tsify(optional, type = "Address[]")] - pub orderbook_addresses: Option>, + pub raindex_addresses: Option>, #[serde(default)] pub only_active_orders: bool, } @@ -1632,8 +1632,8 @@ impl TryFrom for SgVaultsListFilterArgs { .collect() }) .unwrap_or_default(), - orderbooks: filters - .orderbook_addresses + raindexes: filters + .raindex_addresses .map(|addrs| { addrs .into_iter() @@ -1668,7 +1668,7 @@ impl RaindexVault { balance, formatted_balance, token, - orderbook: Address::from_str(&vault.orderbook.id.0)?, + raindex: Address::from_str(&vault.raindex.id.0)?, orders_as_inputs: vault .orders_as_input .iter() @@ -1693,7 +1693,7 @@ impl RaindexVault { balance: self.balance, formatted_balance: self.formatted_balance.clone(), token: self.token.clone(), - orderbook: self.orderbook, + raindex: self.raindex, orders_as_inputs: self.orders_as_inputs.clone(), orders_as_outputs: self.orders_as_outputs.clone(), } @@ -1706,8 +1706,8 @@ impl RaindexVault { balance: SgBytes(self.balance.as_hex()), owner: SgBytes(self.owner.to_string()), token: self.token.try_into()?, - orderbook: SgOrderbook { - id: SgBytes(self.orderbook.to_string()), + raindex: SgRaindex { + id: SgBytes(self.raindex.to_string()), }, orders_as_input: self .orders_as_inputs @@ -1731,7 +1731,7 @@ impl RaindexVault { let balance = Float::from_hex(&vault.balance)?; let formatted_balance = balance.format()?; - let mut id = Vec::from(vault.orderbook_address.as_slice()); + let mut id = Vec::from(vault.raindex_address.as_slice()); id.extend_from_slice(vault.owner.as_slice()); id.extend_from_slice(vault.token.as_slice()); id.extend_from_slice(&vault.vault_id.to_le_bytes::<32>()); @@ -1753,7 +1753,7 @@ impl RaindexVault { symbol: Some(vault.token_symbol), decimals: vault.token_decimals, }, - orderbook: vault.orderbook_address, + raindex: vault.raindex_address, orders_as_inputs: RaindexOrderAsIO::try_from_local_db_orders_csv( "inputOrders", &vault.input_orders, @@ -1900,7 +1900,7 @@ mod tests { vault_id: U256::from_str(vault_id).unwrap(), token: Address::from_str(token).unwrap(), owner: Address::from_str(owner).unwrap(), - orderbook_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), + raindex_address: address!("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB"), token_name: "Token".to_string(), token_symbol: "TKN".to_string(), token_decimals: 18, @@ -1936,7 +1936,7 @@ mod tests { assert_eq!(result_vault.chain_id(), 42161); assert_eq!(result_vault.owner().to_lowercase(), owner.to_string()); assert_eq!( - result_vault.orderbook().to_lowercase(), + result_vault.raindex().to_lowercase(), "0x2f209e5b67a33b8fe96e28f24628df6da301c8eb".to_string() ); assert_eq!(result_vault.formatted_balance(), "1".to_string()); @@ -1967,10 +1967,10 @@ mod tests { let vault_id_hex = derived_vault.id(); let vault_id_bytes = Bytes::from_str(&vault_id_hex).expect("valid vault id"); - let orderbook = + let raindex_addr = Address::from_str("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB").unwrap(); let retrieved = client - .get_vault(&OrderbookIdentifier::new(42161, orderbook), vault_id_bytes) + .get_vault(&RaindexIdentifier::new(42161, raindex_addr), vault_id_bytes) .await .expect("local vault retrieval should succeed"); @@ -2033,10 +2033,10 @@ mod tests { let vault_id_bytes = Bytes::from_str(&derived_vault.id()).expect("valid vault id"); - let orderbook = + let raindex_addr = Address::from_str("0x2f209e5b67A33B8fE96E28f24628dF6Da301c8eB").unwrap(); let vault = client - .get_vault(&OrderbookIdentifier::new(42161, orderbook), vault_id_bytes) + .get_vault(&RaindexIdentifier::new(42161, raindex_addr), vault_id_bytes) .await .expect("local vault retrieval should succeed"); @@ -2084,7 +2084,7 @@ mod tests { owners: vec![Address::from_str(owner_kept).unwrap()], hide_zero_balance: true, tokens: Some(vec![Address::from_str(token_kept).unwrap()]), - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: false, }; @@ -2149,17 +2149,17 @@ mod tests { mod non_wasm { use super::*; use crate::raindex_client::tests::get_test_yaml; - use crate::raindex_client::tests::CHAIN_ID_1_ORDERBOOK_ADDRESS; + use crate::raindex_client::tests::CHAIN_ID_1_RAINDEX_ADDRESS; use alloy::hex::encode_prefixed; use alloy::primitives::{address, b256}; use alloy::sol_types::SolCall; use httpmock::MockServer; - use rain_orderbook_bindings::IERC20Metadata::decimalsCall; - use rain_orderbook_bindings::{ + use raindex_bindings::IERC20Metadata::decimalsCall; + use raindex_bindings::{ IRaindexV6::{deposit4Call, withdraw4Call}, IERC20::approveCall, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; use serde_json::{json, Value}; use std::sync::Arc; use LocalDbVault; @@ -2167,7 +2167,7 @@ mod tests { #[test] fn test_try_from_local_trade_side_with_running_balance() { let chain_id = 42161; - let orderbook = address!("0x0000000000000000000000000000000000000001"); + let raindex_addr = address!("0x0000000000000000000000000000000000000001"); let transaction = RaindexTransaction::from_local_parts( b256!("0x00000000000000000000000000000000000000000000000000000000deadbeef"), address!("0x0000000000000000000000000000000000000002"), @@ -2184,7 +2184,7 @@ mod tests { let change = RaindexVaultBalanceChange::try_from_local_trade_side( chain_id, - orderbook, + raindex_addr, &transaction, U256::from(16), LocalTradeTokenInfo { @@ -2216,7 +2216,7 @@ mod tests { expected_old_balance.format().unwrap() ); assert_eq!(change.timestamp(), U256::from(789)); - assert_eq!(change.orderbook(), orderbook); + assert_eq!(change.raindex(), raindex_addr); assert_eq!(change.transaction().id(), transaction.id()); let token = change.token(); @@ -2237,7 +2237,7 @@ mod tests { #[test] fn test_try_from_local_trade_side_defaults() { let chain_id = 1; - let orderbook = address!("0x0000000000000000000000000000000000000004"); + let raindex_addr = address!("0x0000000000000000000000000000000000000004"); let transaction = RaindexTransaction::from_local_parts( b256!("0x00000000000000000000000000000000000000000000000000000000feedface"), address!("0x0000000000000000000000000000000000000005"), @@ -2252,7 +2252,7 @@ mod tests { let change = RaindexVaultBalanceChange::try_from_local_trade_side( chain_id, - orderbook, + raindex_addr, &transaction, U256::from(2), LocalTradeTokenInfo { @@ -2314,7 +2314,7 @@ mod tests { vault_id: U256::from(1), token: address!("0x0000000000000000000000000000000000000000"), owner: address!("0x0000000000000000000000000000000000000000"), - orderbook_address: Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + raindex_address: Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), token_name: "Test Token".to_string(), token_symbol: "TST".to_string(), token_decimals: 6, @@ -2348,8 +2348,8 @@ mod tests { "symbol": "TKN1", "decimals": "18" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], @@ -2370,7 +2370,7 @@ mod tests { "symbol": "TKN2", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "ordersAsOutput": [], @@ -2432,8 +2432,8 @@ mod tests { assert_eq!(vault1.formatted_balance, "1"); assert_eq!(vault1.token.id, "token1"); assert_eq!( - vault1.orderbook, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap() + vault1.raindex, + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap() ); let vault2 = result[1].clone(); @@ -2448,7 +2448,7 @@ mod tests { assert_eq!(vault2.formatted_balance, "2"); assert_eq!(vault2.token.id, "token2"); assert_eq!( - vault2.orderbook, + vault2.raindex, Address::from_str("0x0000000000000000000000000000000000000000").unwrap() ); } @@ -2481,9 +2481,9 @@ mod tests { let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x10").unwrap(), ) @@ -2507,8 +2507,8 @@ mod tests { assert_eq!(vault.token.id, "token1"); assert_eq!( - vault.orderbook, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap() + vault.raindex, + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap() ); } @@ -2531,8 +2531,8 @@ mod tests { "symbol": "TKN1", "decimals": null // Missing decimals }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], @@ -2571,9 +2571,9 @@ mod tests { .unwrap(); let err = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -2628,7 +2628,7 @@ mod tests { "blockNumber": "34407047", "timestamp": "1734054063" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } @@ -2662,9 +2662,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -2703,7 +2703,7 @@ mod tests { assert_eq!(result[0].transaction.block_number(), U256::from(34407047)); assert_eq!(result[0].transaction.timestamp(), U256::from(1734054063)); assert_eq!( - result[0].orderbook, + result[0].raindex, Address::from_str("0xcee8cd002f151a536394e564b84076c41bbbcd4d").unwrap() ); } @@ -2722,8 +2722,8 @@ mod tests { "symbol": "USDC", "decimals": "6" }, - "orderbook": { - "id": CHAIN_ID_1_ORDERBOOK_ADDRESS + "raindex": { + "id": CHAIN_ID_1_RAINDEX_ADDRESS }, "ordersAsOutput": [], "ordersAsInput": [], @@ -2755,9 +2755,9 @@ mod tests { let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0456").unwrap(), ) @@ -2810,7 +2810,7 @@ mod tests { "blockNumber": "34407047", "timestamp": "1734054063" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } @@ -2843,9 +2843,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -2908,7 +2908,7 @@ mod tests { "blockNumber": "34407047", "timestamp": "1734054063" }, - "orderbook": { + "raindex": { "id": "0xcee8cd002f151a536394e564b84076c41bbbcd4d" } } @@ -2955,9 +2955,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -3007,9 +3007,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -3076,9 +3076,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -3143,9 +3143,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -3159,7 +3159,7 @@ mod tests { result, Bytes::copy_from_slice( &approveCall { - spender: Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + spender: Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), amount: U256::from(600000000000000000000u128), } .abi_encode(), @@ -3221,9 +3221,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -3275,7 +3275,7 @@ mod tests { "0x1d80c49bbbcd1c0911346656b529df9e5c2f783d", ) .unwrap()]), - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: false, }; @@ -3334,7 +3334,7 @@ mod tests { Address::from_str("0x1d80c49bbbcd1c0911346656b529df9e5c2f783d").unwrap(), Address::from_str("0x12e605bc104e93b45e1ad99f9e555f659051c2bb").unwrap(), ]), - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: false, }; @@ -3486,9 +3486,9 @@ mod tests { .unwrap(); let vault = raindex_client .get_vault( - &OrderbookIdentifier::new( + &RaindexIdentifier::new( 1, - Address::from_str(CHAIN_ID_1_ORDERBOOK_ADDRESS).unwrap(), + Address::from_str(CHAIN_ID_1_RAINDEX_ADDRESS).unwrap(), ), Bytes::from_str("0x0123").unwrap(), ) @@ -3500,14 +3500,14 @@ mod tests { } #[test] - fn get_vaults_filters_to_sg_filter_args_maps_orderbook_addresses() { - use rain_orderbook_subgraph_client::types::common::SgVaultsListFilterArgs; + fn get_vaults_filters_to_sg_filter_args_maps_raindex_addresses() { + use raindex_subgraph_client::types::common::SgVaultsListFilterArgs; let filters = GetVaultsFilters { owners: vec![], hide_zero_balance: false, tokens: None, - orderbook_addresses: Some(vec![ + raindex_addresses: Some(vec![ address!("0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), address!("0xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"), ]), @@ -3516,43 +3516,43 @@ mod tests { let sg_filter_args: SgVaultsListFilterArgs = filters.try_into().unwrap(); - assert_eq!(sg_filter_args.orderbooks.len(), 2); + assert_eq!(sg_filter_args.raindexes.len(), 2); assert_eq!( - sg_filter_args.orderbooks[0], + sg_filter_args.raindexes[0], "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ); assert_eq!( - sg_filter_args.orderbooks[1], + sg_filter_args.raindexes[1], "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" ); } #[test] - fn get_vaults_filters_to_sg_filter_args_empty_orderbook_addresses() { - use rain_orderbook_subgraph_client::types::common::SgVaultsListFilterArgs; + fn get_vaults_filters_to_sg_filter_args_empty_raindex_addresses() { + use raindex_subgraph_client::types::common::SgVaultsListFilterArgs; let filters = GetVaultsFilters { owners: vec![], hide_zero_balance: false, tokens: None, - orderbook_addresses: None, + raindex_addresses: None, only_active_orders: false, }; let sg_filter_args: SgVaultsListFilterArgs = filters.try_into().unwrap(); - assert!(sg_filter_args.orderbooks.is_empty()); + assert!(sg_filter_args.raindexes.is_empty()); } #[test] fn get_vaults_filters_to_sg_filter_args_lowercases_mixed_case_addresses() { - use rain_orderbook_subgraph_client::types::common::SgVaultsListFilterArgs; + use raindex_subgraph_client::types::common::SgVaultsListFilterArgs; let filters = GetVaultsFilters { owners: vec![], hide_zero_balance: false, tokens: None, - orderbook_addresses: Some(vec![address!( + raindex_addresses: Some(vec![address!( "0xDeaDbEEfDeaDbEEfDeaDbEEfDeaDbEEfDeaDbEEf" )]), only_active_orders: false, @@ -3560,9 +3560,9 @@ mod tests { let sg_filter_args: SgVaultsListFilterArgs = filters.try_into().unwrap(); - assert_eq!(sg_filter_args.orderbooks.len(), 1); + assert_eq!(sg_filter_args.raindexes.len(), 1); assert_eq!( - sg_filter_args.orderbooks[0], + sg_filter_args.raindexes[0], "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" ); } diff --git a/crates/common/src/raindex_client/vaults_list.rs b/crates/common/src/raindex_client/vaults_list.rs index 0a05339da8..07e7621eac 100644 --- a/crates/common/src/raindex_client/vaults_list.rs +++ b/crates/common/src/raindex_client/vaults_list.rs @@ -1,6 +1,6 @@ use alloy::{primitives::Bytes, sol_types::SolCall}; use rain_math_float::Float; -use rain_orderbook_bindings::OrderBook::multicallCall; +use raindex_bindings::Raindex::multicallCall; use serde::{Deserialize, Serialize}; use thiserror::Error; use wasm_bindgen_utils::prelude::*; @@ -51,11 +51,11 @@ impl RaindexVaultsList { if vaults_to_withdraw.is_empty() { return Err(VaultsListError::NoWithdrawableVaults); } - let mut orderbook_id_iter = vaults_to_withdraw.iter().map(|v| v.orderbook()); - let first_orderbook_id = orderbook_id_iter.next(); - if let Some(first_id) = first_orderbook_id { - if orderbook_id_iter.any(|id| id != first_id) { - return Err(VaultsListError::MultipleOrderbooksUsed); + let mut raindex_id_iter = vaults_to_withdraw.iter().map(|v| v.raindex()); + let first_raindex_id = raindex_id_iter.next(); + if let Some(first_id) = first_raindex_id { + if raindex_id_iter.any(|id| id != first_id) { + return Err(VaultsListError::MultipleRaindexesUsed); } } // Generate multicall calldata for all vaults @@ -210,8 +210,8 @@ pub enum VaultsListError { WithdrawMulticallError(String), #[error("No withdrawable vaults available")] NoWithdrawableVaults, - #[error("All vaults must share the same orderbook for batch withdrawal")] - MultipleOrderbooksUsed, + #[error("All vaults must share the same raindex for batch withdrawal")] + MultipleRaindexesUsed, } impl VaultsListError { @@ -221,8 +221,8 @@ impl VaultsListError { format!("Failed to generate withdraw multicall: {}", err) } VaultsListError::NoWithdrawableVaults => "No withdrawable vaults available".to_string(), - VaultsListError::MultipleOrderbooksUsed => { - "All vaults must share the same orderbook for batch withdrawal".to_string() + VaultsListError::MultipleRaindexesUsed => { + "All vaults must share the same raindex for batch withdrawal".to_string() } } } @@ -267,7 +267,7 @@ mod tests { "symbol": "TKN1", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "ordersAsOutput": [], @@ -289,7 +289,7 @@ mod tests { "symbol": "TKN2", "decimals": "18" }, - "orderbook": { + "raindex": { "id": "0x0000000000000000000000000000000000000000" }, "ordersAsOutput": [], diff --git a/crates/common/src/rainlang.rs b/crates/common/src/rainlang.rs index fec28b162c..b2a0fceb4d 100644 --- a/crates/common/src/rainlang.rs +++ b/crates/common/src/rainlang.rs @@ -27,7 +27,7 @@ pub fn compose_to_rainlang( mod tests { use dotrain::{error::ErrorCode, types::ast::Problem}; - use crate::add_order::ORDERBOOK_ORDER_ENTRYPOINTS; + use crate::add_order::RAINDEX_ORDER_ENTRYPOINTS; use super::*; @@ -82,7 +82,7 @@ _ _: 0 0; let actual = compose_to_rainlang( dotrain.to_string(), HashMap::new(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, ) .unwrap(); @@ -278,8 +278,8 @@ mod fork_parse { use std::collections::HashMap; use super::*; - use crate::add_order::ORDERBOOK_ORDER_ENTRYPOINTS; - use rain_orderbook_test_fixtures::LocalEvm; + use crate::add_order::RAINDEX_ORDER_ENTRYPOINTS; + use raindex_test_fixtures::LocalEvm; #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn test_parse_rainlang_on_fork_ok() { @@ -303,7 +303,7 @@ _ _: 1 2; let rainlang = super::super::compose_to_rainlang( dotrain.to_string(), HashMap::new(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, ) .unwrap(); @@ -372,7 +372,7 @@ _ _: 1 2; let rainlang = super::super::compose_to_rainlang( dotrain.to_string(), HashMap::new(), - &ORDERBOOK_ORDER_ENTRYPOINTS, + &RAINDEX_ORDER_ENTRYPOINTS, ) .unwrap(); diff --git a/crates/common/src/remove_order.rs b/crates/common/src/remove_order.rs index 55b5e914fb..12e334f318 100644 --- a/crates/common/src/remove_order.rs +++ b/crates/common/src/remove_order.rs @@ -6,10 +6,8 @@ use alloy::sol_types::SolCall; use alloy_ethers_typecast::WritableClientError; #[cfg(not(target_family = "wasm"))] use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; -use rain_orderbook_bindings::IRaindexV6::removeOrder3Call; -use rain_orderbook_subgraph_client::types::{ - common::SgOrder, order_detail_traits::OrderDetailError, -}; +use raindex_bindings::IRaindexV6::removeOrder3Call; +use raindex_subgraph_client::types::{common::SgOrder, order_detail_traits::OrderDetailError}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -59,7 +57,7 @@ impl RemoveOrderArgs { let remove_order_call: removeOrder3Call = self.try_into()?; let params = transaction_args.try_into_write_contract_parameters( remove_order_call, - transaction_args.orderbook_address, + transaction_args.raindex_address, )?; WriteTransaction::new(ledger_client, params, 4, transaction_status_changed) @@ -79,11 +77,9 @@ impl RemoveOrderArgs { mod tests { use super::*; use alloy::primitives::Address; - use rain_orderbook_bindings::IRaindexV6::removeOrder3Call; - use rain_orderbook_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault, - }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_bindings::IRaindexV6::removeOrder3Call; + use raindex_subgraph_client::types::common::{SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault}; + use raindex_subgraph_client::utils::float::*; fn get_order() -> SgOrder { SgOrder { @@ -110,7 +106,7 @@ mod tests { symbol: Some("WFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![], @@ -119,7 +115,7 @@ mod tests { }, ], inputs: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, active: true, @@ -154,7 +150,7 @@ mod tests { let args = TransactionArgs { rpcs: vec!["http://test.com".to_string()], - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: Some(0_usize), chain_id: Some(1), max_priority_fee_per_gas: Some(200), @@ -162,9 +158,9 @@ mod tests { }; let params = args - .try_into_write_contract_parameters(remove_order_call.clone(), args.orderbook_address) + .try_into_write_contract_parameters(remove_order_call.clone(), args.raindex_address) .unwrap(); - assert_eq!(params.address, args.orderbook_address); + assert_eq!(params.address, args.raindex_address); assert_eq!(params.call, remove_order_call); assert_eq!(params.max_priority_fee_per_gas, Some(200)); assert_eq!(params.max_fee_per_gas, Some(100)); diff --git a/crates/common/src/replays.rs b/crates/common/src/replays.rs index 729399fee9..a5c148f603 100644 --- a/crates/common/src/replays.rs +++ b/crates/common/src/replays.rs @@ -57,8 +57,8 @@ mod tests { sol_types::SolCall, }; use rain_math_float::Float; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_test_fixtures::{LocalEvm, Orderbook}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_test_fixtures::{LocalEvm, Raindex}; use std::str::FromStr; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] @@ -86,7 +86,7 @@ mod tests { token2_holder, ) .await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let dotrain = format!( r#" @@ -114,9 +114,9 @@ tokens: decimals: 18 label: Dai symbol: DAI -orderbook: +raindex: polygon: - address: {orderbook} + address: {raindex} orders: polygon: inputs: @@ -143,7 +143,7 @@ amount price: 2 1; :; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -165,14 +165,14 @@ amount price: 2 1; .abi_encode(); let tx = TransactionRequest::default() .with_input(calldata) - .with_to(*orderbook.address()) + .with_to(*raindex.address()) .with_from(token1_holder); local_evm .send_transaction(WithOtherFields::new(tx)) .await .unwrap(); - let filter = orderbook.AddOrderV3_filter(); + let filter = raindex.AddOrderV3_filter(); let logs = filter.query().await.unwrap(); let order = logs[0].0.order.clone(); @@ -180,14 +180,14 @@ amount price: 2 1; local_evm .send_transaction( token1 - .approve(*orderbook.address(), parse_ether("1000").unwrap()) + .approve(*raindex.address(), parse_ether("1000").unwrap()) .into_transaction_request(), ) .await .unwrap(); let amount = Float::parse("10".to_string()).unwrap().get_inner(); - let tx_req = orderbook + let tx_req = raindex .deposit4( *token1.address(), B256::from(U256::from(0x01)), @@ -197,9 +197,9 @@ amount price: 2 1; .into_transaction_request(); local_evm.send_transaction(tx_req).await.unwrap(); - // approve T2 spending for token2 holder for orderbook + // approve T2 spending for token2 holder for raindex let tx_req = token2 - .approve(*orderbook.address(), parse_ether("1000").unwrap()) + .approve(*raindex.address(), parse_ether("1000").unwrap()) .from(token2_holder) .into_transaction_request(); local_evm.send_transaction(tx_req).await.unwrap(); @@ -214,8 +214,8 @@ amount price: 2 1; .unwrap() .get_inner(); let one_float = Float::parse("1".to_string()).unwrap().get_inner(); - let config = Orderbook::TakeOrdersConfigV5 { - orders: vec![Orderbook::TakeOrderConfigV4 { + let config = Raindex::TakeOrdersConfigV5 { + orders: vec![Raindex::TakeOrderConfigV4 { order, inputIOIndex: U256::from(0), outputIOIndex: U256::from(0), @@ -228,7 +228,7 @@ amount price: 2 1; data: Bytes::new(), }; - let tx_req = orderbook + let tx_req = raindex .takeOrders4(config) .from(token2_holder) .into_transaction_request(); diff --git a/crates/common/src/rpc_client.rs b/crates/common/src/rpc_client.rs index 9f68886515..adb5e2e713 100644 --- a/crates/common/src/rpc_client.rs +++ b/crates/common/src/rpc_client.rs @@ -3,7 +3,7 @@ use alloy::providers::Provider; use alloy::rpc::json_rpc::{Id, RequestMeta}; use alloy::rpc::types::Filter; use alloy::transports::TransportError; -use rain_orderbook_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; +use raindex_bindings::provider::{mk_read_provider, ReadProvider, ReadProviderError}; use serde::{Deserialize, Serialize}; use serde_json::{Map, Value}; use std::sync::Arc; diff --git a/crates/common/src/subgraph.rs b/crates/common/src/subgraph.rs index 72f234d3b6..8cbb89f1db 100644 --- a/crates/common/src/subgraph.rs +++ b/crates/common/src/subgraph.rs @@ -1,4 +1,4 @@ -use rain_orderbook_subgraph_client::OrderbookSubgraphClient; +use raindex_subgraph_client::RaindexSubgraphClient; use serde::{Deserialize, Serialize}; use url::{ParseError, Url}; @@ -8,8 +8,8 @@ pub struct SubgraphArgs { } impl SubgraphArgs { - pub fn to_subgraph_client(&self) -> Result { - Ok(OrderbookSubgraphClient::new(Url::parse(self.url.as_str())?)) + pub fn to_subgraph_client(&self) -> Result { + Ok(RaindexSubgraphClient::new(Url::parse(self.url.as_str())?)) } } diff --git a/crates/common/src/take_orders/candidates.rs b/crates/common/src/take_orders/candidates.rs index 60d71b22b5..82cbf4e516 100644 --- a/crates/common/src/take_orders/candidates.rs +++ b/crates/common/src/take_orders/candidates.rs @@ -3,7 +3,7 @@ use crate::raindex_client::orders::RaindexOrder; use crate::raindex_client::RaindexError; use alloy::primitives::Address; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, SignedContextV1}; +use raindex_bindings::IRaindexV6::{OrderV4, SignedContextV1}; #[cfg(target_family = "wasm")] use std::str::FromStr; @@ -32,7 +32,7 @@ fn has_capacity( #[derive(Clone, Debug)] pub struct TakeOrderCandidate { - pub orderbook: Address, + pub raindex: Address, pub order: OrderV4, pub input_io_index: u32, pub output_io_index: u32, @@ -42,14 +42,14 @@ pub struct TakeOrderCandidate { pub signed_context: Vec, } -fn get_orderbook_address(order: &RaindexOrder) -> Result { +fn get_raindex_address(order: &RaindexOrder) -> Result { #[cfg(target_family = "wasm")] { - Ok(Address::from_str(&order.orderbook())?) + Ok(Address::from_str(&order.raindex())?) } #[cfg(not(target_family = "wasm"))] { - Ok(order.orderbook()) + Ok(order.raindex()) } } @@ -65,7 +65,7 @@ pub async fn build_take_order_candidates_for_pair( let mut all_candidates = vec![]; for (order, quotes) in orders.iter().zip(all_quotes) { let order_v4: OrderV4 = order.try_into()?; - let orderbook = get_orderbook_address(order)?; + let raindex = get_raindex_address(order)?; let oracle_url = order.oracle_url(); for quote in "es { @@ -88,7 +88,7 @@ pub async fn build_take_order_candidates_for_pair( }; if let Some(candidate) = try_build_candidate( - orderbook, + raindex, &order_v4, quote, input_token, @@ -123,7 +123,7 @@ async fn fetch_oracle_for_pair( } fn try_build_candidate( - orderbook: Address, + raindex: Address, order: &OrderV4, quote: &RaindexOrderQuote, input_token: Address, @@ -157,7 +157,7 @@ fn try_build_candidate( } Ok(Some(TakeOrderCandidate { - orderbook, + raindex, order: order.clone(), input_io_index, output_io_index, @@ -283,14 +283,14 @@ mod tests { fn test_try_build_candidate_wrong_direction() { let token_a = Address::from([4u8; 20]); let token_b = Address::from([5u8; 20]); - let orderbook = Address::from([0xAAu8; 20]); + let raindex = Address::from([0xAAu8; 20]); let order = make_basic_order(token_a, token_b); let f1 = Float::parse("1".to_string()).unwrap(); let quote = make_quote(0, 0, Some(make_quote_value(f1, f1, f1)), true); let result = - try_build_candidate(orderbook, &order, "e, token_b, token_a, vec![]).unwrap(); + try_build_candidate(raindex, &order, "e, token_b, token_a, vec![]).unwrap(); assert!(result.is_none()); } @@ -299,7 +299,7 @@ mod tests { fn test_try_build_candidate_zero_capacity() { let token_a = Address::from([4u8; 20]); let token_b = Address::from([5u8; 20]); - let orderbook = Address::from([0xAAu8; 20]); + let raindex = Address::from([0xAAu8; 20]); let order = make_basic_order(token_a, token_b); let zero = Float::zero().unwrap(); @@ -307,7 +307,7 @@ mod tests { let quote = make_quote(0, 0, Some(make_quote_value(zero, zero, f1)), true); let result = - try_build_candidate(orderbook, &order, "e, token_a, token_b, vec![]).unwrap(); + try_build_candidate(raindex, &order, "e, token_a, token_b, vec![]).unwrap(); assert!(result.is_none()); } @@ -316,7 +316,7 @@ mod tests { fn test_try_build_candidate_success() { let token_a = Address::from([4u8; 20]); let token_b = Address::from([5u8; 20]); - let orderbook = Address::from([0xAAu8; 20]); + let raindex = Address::from([0xAAu8; 20]); let order = make_basic_order(token_a, token_b); let f1 = Float::parse("1".to_string()).unwrap(); @@ -324,11 +324,11 @@ mod tests { let quote = make_quote(0, 0, Some(make_quote_value(f2, f1, f1)), true); let result = - try_build_candidate(orderbook, &order, "e, token_a, token_b, vec![]).unwrap(); + try_build_candidate(raindex, &order, "e, token_a, token_b, vec![]).unwrap(); assert!(result.is_some()); let candidate = result.unwrap(); - assert_eq!(candidate.orderbook, orderbook); + assert_eq!(candidate.raindex, raindex); assert_eq!(candidate.input_io_index, 0); assert_eq!(candidate.output_io_index, 0); assert!(candidate.max_output.eq(f2).unwrap()); @@ -338,12 +338,12 @@ mod tests { fn test_try_build_candidate_failed_quote() { let token_a = Address::from([4u8; 20]); let token_b = Address::from([5u8; 20]); - let orderbook = Address::from([0xAAu8; 20]); + let raindex = Address::from([0xAAu8; 20]); let order = make_basic_order(token_a, token_b); let quote = make_quote(0, 0, None, false); - let result = try_build_candidate(orderbook, &order, "e, token_a, token_b, vec![]); + let result = try_build_candidate(raindex, &order, "e, token_a, token_b, vec![]); assert!( result.is_ok(), @@ -360,14 +360,14 @@ mod tests { fn test_try_build_candidate_out_of_bounds_indices() { let token_a = Address::from([4u8; 20]); let token_b = Address::from([5u8; 20]); - let orderbook = Address::from([0xAAu8; 20]); + let raindex = Address::from([0xAAu8; 20]); let order = make_basic_order(token_a, token_b); let f1 = Float::parse("1".to_string()).unwrap(); let quote_bad_input_index = make_quote(99, 0, Some(make_quote_value(f1, f1, f1)), true); let result = try_build_candidate( - orderbook, + raindex, &order, "e_bad_input_index, token_a, @@ -385,7 +385,7 @@ mod tests { let quote_bad_output_index = make_quote(0, 99, Some(make_quote_value(f1, f1, f1)), true); let result = try_build_candidate( - orderbook, + raindex, &order, "e_bad_output_index, token_a, diff --git a/crates/common/src/take_orders/config.rs b/crates/common/src/take_orders/config.rs index 14c843cd85..c3667dbe66 100644 --- a/crates/common/src/take_orders/config.rs +++ b/crates/common/src/take_orders/config.rs @@ -2,7 +2,7 @@ use super::simulation::SimulationResult; use crate::raindex_client::RaindexError; use alloy::primitives::{Bytes, U256}; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{TakeOrderConfigV4, TakeOrdersConfigV5}; +use raindex_bindings::IRaindexV6::{TakeOrderConfigV4, TakeOrdersConfigV5}; use serde::{Deserialize, Serialize}; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; diff --git a/crates/common/src/take_orders/preflight.rs b/crates/common/src/take_orders/preflight.rs index 68863eda22..f5e72154bb 100644 --- a/crates/common/src/take_orders/preflight.rs +++ b/crates/common/src/take_orders/preflight.rs @@ -4,9 +4,9 @@ use alloy::providers::Provider; use alloy::rpc::types::TransactionRequest; use alloy::serde::WithOtherFields; use alloy::sol_types::SolCall; -use rain_orderbook_bindings::provider::ReadProvider; -use rain_orderbook_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; -use rain_orderbook_bindings::IERC20::approveCall; +use raindex_bindings::provider::ReadProvider; +use raindex_bindings::IRaindexV6::{takeOrders4Call, TakeOrdersConfigV5}; +use raindex_bindings::IERC20::approveCall; use thiserror::Error; use crate::erc20::ERC20; @@ -102,10 +102,10 @@ pub async fn check_taker_balance( pub async fn check_taker_allowance( erc20: &ERC20, taker: Address, - orderbook: Address, + raindex: Address, required: U256, ) -> Result { - let allowance = erc20.allowance(taker, orderbook).await?; + let allowance = erc20.allowance(taker, raindex).await?; if allowance >= required { Ok(AllowanceOnlyResult::sufficient(allowance, required)) } else { @@ -116,7 +116,7 @@ pub async fn check_taker_allowance( pub async fn check_taker_balance_and_allowance( erc20: &ERC20, taker: Address, - orderbook: Address, + raindex: Address, required: U256, ) -> Result { let balance = erc20.get_account_balance(taker).await?; @@ -127,7 +127,7 @@ pub async fn check_taker_balance_and_allowance( ))); } - let allowance = erc20.allowance(taker, orderbook).await?; + let allowance = erc20.allowance(taker, raindex).await?; if allowance >= required { Ok(BalanceAndAllowanceResult::sufficient( balance, allowance, required, @@ -146,7 +146,7 @@ pub fn build_approval_calldata(spender: Address, amount: U256) -> Bytes { pub async fn simulate_take_orders( provider: &ReadProvider, - orderbook: Address, + raindex: Address, taker: Address, config: &TakeOrdersConfigV5, block_number: Option, @@ -157,7 +157,7 @@ pub async fn simulate_take_orders( .abi_encode(); let tx = TransactionRequest::default() - .with_to(orderbook) + .with_to(raindex) .with_from(taker) .with_input(calldata); @@ -180,7 +180,7 @@ pub async fn simulate_take_orders( pub async fn find_failing_order_index( provider: &ReadProvider, - orderbook: Address, + raindex: Address, taker: Address, config: &TakeOrdersConfigV5, block_number: Option, @@ -190,7 +190,7 @@ pub async fn find_failing_order_index( } if config.orders.len() == 1 { - let result = simulate_take_orders(provider, orderbook, taker, config, block_number).await; + let result = simulate_take_orders(provider, raindex, taker, config, block_number).await; if result.is_err() { return Some(0); } @@ -207,14 +207,9 @@ pub async fn find_failing_order_index( data: config.data.clone(), }; - let result = simulate_take_orders( - provider, - orderbook, - taker, - &single_order_config, - block_number, - ) - .await; + let result = + simulate_take_orders(provider, raindex, taker, &single_order_config, block_number) + .await; if result.is_err() { return Some(idx); @@ -295,9 +290,9 @@ mod local_evm_tests { use super::*; use crate::erc20::ERC20; use alloy::primitives::B256; - use rain_orderbook_bindings::provider::mk_read_provider; - use rain_orderbook_bindings::IRaindexV6::TakeOrderConfigV4; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_bindings::provider::mk_read_provider; + use raindex_bindings::IRaindexV6::TakeOrderConfigV4; + use raindex_test_fixtures::LocalEvm; use url::Url; async fn setup_local_evm() -> (LocalEvm, Address, Address, Address) { @@ -306,8 +301,8 @@ mod local_evm_tests { let token = local_evm .deploy_new_token("TestToken", "TT", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); - (local_evm, owner, *token.address(), orderbook) + let raindex = *local_evm.raindex.address(); + (local_evm, owner, *token.address(), raindex) } fn create_erc20(local_evm: &LocalEvm, token: Address) -> ERC20 { @@ -317,7 +312,7 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_balance_sufficient() { - let (local_evm, owner, token, _orderbook) = setup_local_evm().await; + let (local_evm, owner, token, _raindex) = setup_local_evm().await; let erc20 = create_erc20(&local_evm, token); let result = check_taker_balance(&erc20, owner, U256::from(1000)).await; @@ -329,7 +324,7 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_balance_insufficient() { - let (local_evm, _owner, token, _orderbook) = setup_local_evm().await; + let (local_evm, _owner, token, _raindex) = setup_local_evm().await; let erc20 = create_erc20(&local_evm, token); let random_address = Address::repeat_byte(0x42); @@ -342,7 +337,7 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_allowance_sufficient() { - let (local_evm, owner, token, orderbook) = setup_local_evm().await; + let (local_evm, owner, token, raindex) = setup_local_evm().await; let token_contract = local_evm .tokens @@ -350,7 +345,7 @@ mod local_evm_tests { .find(|t| *t.address() == token) .unwrap(); token_contract - .approve(orderbook, U256::from(1000)) + .approve(raindex, U256::from(1000)) .from(owner) .send() .await @@ -360,7 +355,7 @@ mod local_evm_tests { .unwrap(); let erc20 = create_erc20(&local_evm, token); - let result = check_taker_allowance(&erc20, owner, orderbook, U256::from(500)).await; + let result = check_taker_allowance(&erc20, owner, raindex, U256::from(500)).await; assert!(result.is_ok()); let check_result = result.unwrap(); @@ -370,10 +365,10 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_allowance_insufficient() { - let (local_evm, owner, token, orderbook) = setup_local_evm().await; + let (local_evm, owner, token, raindex) = setup_local_evm().await; let erc20 = create_erc20(&local_evm, token); - let result = check_taker_allowance(&erc20, owner, orderbook, U256::from(1000)).await; + let result = check_taker_allowance(&erc20, owner, raindex, U256::from(1000)).await; assert!(result.is_ok()); let check_result = result.unwrap(); @@ -383,7 +378,7 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_balance_and_allowance_both_sufficient() { - let (local_evm, owner, token, orderbook) = setup_local_evm().await; + let (local_evm, owner, token, raindex) = setup_local_evm().await; let token_contract = local_evm .tokens @@ -391,7 +386,7 @@ mod local_evm_tests { .find(|t| *t.address() == token) .unwrap(); token_contract - .approve(orderbook, U256::from(1000)) + .approve(raindex, U256::from(1000)) .from(owner) .send() .await @@ -402,7 +397,7 @@ mod local_evm_tests { let erc20 = create_erc20(&local_evm, token); let result = - check_taker_balance_and_allowance(&erc20, owner, orderbook, U256::from(500)).await; + check_taker_balance_and_allowance(&erc20, owner, raindex, U256::from(500)).await; assert!(result.is_ok()); let check_result = result.unwrap(); @@ -413,12 +408,12 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_balance_and_allowance_insufficient_balance() { - let (local_evm, _owner, token, orderbook) = setup_local_evm().await; + let (local_evm, _owner, token, raindex) = setup_local_evm().await; let erc20 = create_erc20(&local_evm, token); let random_address = Address::repeat_byte(0x42); let result = - check_taker_balance_and_allowance(&erc20, random_address, orderbook, U256::from(1000)) + check_taker_balance_and_allowance(&erc20, random_address, raindex, U256::from(1000)) .await; assert!(result.is_err()); @@ -430,11 +425,11 @@ mod local_evm_tests { #[tokio::test] async fn test_check_taker_balance_and_allowance_insufficient_allowance() { - let (local_evm, owner, token, orderbook) = setup_local_evm().await; + let (local_evm, owner, token, raindex) = setup_local_evm().await; let erc20 = create_erc20(&local_evm, token); let result = - check_taker_balance_and_allowance(&erc20, owner, orderbook, U256::from(1000)).await; + check_taker_balance_and_allowance(&erc20, owner, raindex, U256::from(1000)).await; assert!(result.is_ok()); let check_result = result.unwrap(); @@ -445,7 +440,7 @@ mod local_evm_tests { #[tokio::test] async fn test_simulate_take_orders_empty_orders_fails_minimum_io() { - let (local_evm, owner, _token, orderbook) = setup_local_evm().await; + let (local_evm, owner, _token, raindex) = setup_local_evm().await; let rpc_url = Url::parse(&local_evm.url().to_string()).unwrap(); let provider = mk_read_provider(&[rpc_url]).unwrap(); @@ -459,7 +454,7 @@ mod local_evm_tests { data: Bytes::new(), }; - let result = simulate_take_orders(&provider, orderbook, owner, &config, None).await; + let result = simulate_take_orders(&provider, raindex, owner, &config, None).await; assert!( result.is_err(), "Empty orders config should fail simulation" @@ -468,15 +463,15 @@ mod local_evm_tests { #[tokio::test] async fn test_simulate_take_orders_invalid_order_fails() { - let (local_evm, owner, _token, orderbook) = setup_local_evm().await; + let (local_evm, owner, _token, raindex) = setup_local_evm().await; let rpc_url = Url::parse(&local_evm.url().to_string()).unwrap(); let provider = mk_read_provider(&[rpc_url]).unwrap(); let fake_order = TakeOrderConfigV4 { - order: rain_orderbook_bindings::IRaindexV6::OrderV4 { + order: raindex_bindings::IRaindexV6::OrderV4 { owner: Address::ZERO, - evaluable: rain_orderbook_bindings::IRaindexV6::EvaluableV4 { + evaluable: raindex_bindings::IRaindexV6::EvaluableV4 { interpreter: Address::ZERO, store: Address::ZERO, bytecode: Bytes::new(), @@ -499,13 +494,13 @@ mod local_evm_tests { data: Bytes::new(), }; - let result = simulate_take_orders(&provider, orderbook, owner, &config, None).await; + let result = simulate_take_orders(&provider, raindex, owner, &config, None).await; assert!(result.is_err()); } #[tokio::test] async fn test_find_failing_order_index_empty_orders() { - let (local_evm, owner, _token, orderbook) = setup_local_evm().await; + let (local_evm, owner, _token, raindex) = setup_local_evm().await; let rpc_url = Url::parse(&local_evm.url().to_string()).unwrap(); let provider = mk_read_provider(&[rpc_url]).unwrap(); @@ -519,21 +514,21 @@ mod local_evm_tests { data: Bytes::new(), }; - let result = find_failing_order_index(&provider, orderbook, owner, &config, None).await; + let result = find_failing_order_index(&provider, raindex, owner, &config, None).await; assert!(result.is_none()); } #[tokio::test] async fn test_find_failing_order_index_single_failing_order() { - let (local_evm, owner, _token, orderbook) = setup_local_evm().await; + let (local_evm, owner, _token, raindex) = setup_local_evm().await; let rpc_url = Url::parse(&local_evm.url().to_string()).unwrap(); let provider = mk_read_provider(&[rpc_url]).unwrap(); let fake_order = TakeOrderConfigV4 { - order: rain_orderbook_bindings::IRaindexV6::OrderV4 { + order: raindex_bindings::IRaindexV6::OrderV4 { owner: Address::ZERO, - evaluable: rain_orderbook_bindings::IRaindexV6::EvaluableV4 { + evaluable: raindex_bindings::IRaindexV6::EvaluableV4 { interpreter: Address::ZERO, store: Address::ZERO, bytecode: Bytes::new(), @@ -556,7 +551,7 @@ mod local_evm_tests { data: Bytes::new(), }; - let result = find_failing_order_index(&provider, orderbook, owner, &config, None).await; + let result = find_failing_order_index(&provider, raindex, owner, &config, None).await; assert_eq!(result, Some(0)); } } diff --git a/crates/common/src/test_helpers.rs b/crates/common/src/test_helpers.rs index 603823b62d..9b727ca9d5 100644 --- a/crates/common/src/test_helpers.rs +++ b/crates/common/src/test_helpers.rs @@ -1,4 +1,4 @@ -use rain_orderbook_app_settings::spec_version::SpecVersion; +use raindex_app_settings::spec_version::SpecVersion; pub fn test_dotrain() -> String { format!( @@ -19,7 +19,7 @@ subgraphs: metaboards: mainnet: https://mainnet-metaboard.com testnet: https://testnet-metaboard.com -orderbooks: +raindexes: mainnet: address: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 network: mainnet @@ -55,7 +55,7 @@ accounts: orders: order1: rainlang: scenario1 - orderbook: mainnet + raindex: mainnet inputs: - token: token1 vault-id: 1 @@ -178,10 +178,8 @@ _ _: 0 0; pub mod local_evm { use alloy::primitives::{Address, B256, U256}; use rain_math_float::Float; - use rain_orderbook_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault, - }; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_subgraph_client::types::common::{SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault}; + use raindex_test_fixtures::LocalEvm; pub struct TestSetup { pub local_evm: LocalEvm, @@ -190,7 +188,7 @@ pub mod local_evm { pub token2: Address, pub token1_sg: SgErc20, pub token2_sg: SgErc20, - pub orderbook: Address, + pub raindex: Address, } pub async fn setup_test() -> TestSetup { @@ -203,7 +201,7 @@ pub mod local_evm { let token2 = local_evm .deploy_new_token("Token2", "Token2", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); TestSetup { token1: *token1.address(), @@ -224,7 +222,7 @@ pub mod local_evm { }, local_evm, owner, - orderbook, + raindex, } } @@ -299,8 +297,8 @@ pub mod local_evm { approve_taker(setup, token, taker, spender, U256::MAX).await; } - pub async fn fund_and_approve_taker_multi_orderbook( - setup: &MultiOrderbookTestSetup, + pub async fn fund_and_approve_taker_multi_raindex( + setup: &MultiRaindexTestSetup, token: Address, taker: Address, spender: Address, @@ -334,19 +332,19 @@ pub mod local_evm { .unwrap(); } - pub struct MultiOrderbookTestSetup { + pub struct MultiRaindexTestSetup { pub local_evm: LocalEvm, pub owner: Address, pub token1: Address, pub token2: Address, pub token1_sg: SgErc20, pub token2_sg: SgErc20, - pub orderbook_a: Address, - pub orderbook_b: Address, + pub raindex_a: Address, + pub raindex_b: Address, } - pub async fn setup_multi_orderbook_test() -> MultiOrderbookTestSetup { - use rain_orderbook_test_fixtures::Orderbook; + pub async fn setup_multi_raindex_test() -> MultiRaindexTestSetup { + use raindex_test_fixtures::Raindex; let mut local_evm = LocalEvm::new().await; let owner = local_evm.signer_wallets[0].default_signer().address(); @@ -358,13 +356,13 @@ pub mod local_evm { .deploy_new_token("Token2", "Token2", 18, U256::MAX, owner) .await; - let orderbook_a = *local_evm.orderbook.address(); - let orderbook_b_instance = Orderbook::deploy(local_evm.provider.clone()) + let raindex_a = *local_evm.raindex.address(); + let raindex_b_instance = Raindex::deploy(local_evm.provider.clone()) .await - .expect("Should deploy second orderbook"); - let orderbook_b = *orderbook_b_instance.address(); + .expect("Should deploy second raindex"); + let raindex_b = *raindex_b_instance.address(); - MultiOrderbookTestSetup { + MultiRaindexTestSetup { token1: *token1.address(), token2: *token2.address(), token1_sg: SgErc20 { @@ -383,19 +381,19 @@ pub mod local_evm { }, local_evm, owner, - orderbook_a, - orderbook_b, + raindex_a, + raindex_b, } } - pub async fn deposit_to_orderbook( - setup: &MultiOrderbookTestSetup, - orderbook: Address, + pub async fn deposit_to_raindex( + setup: &MultiRaindexTestSetup, + raindex: Address, token: Address, amount: U256, vault_id: B256, ) { - use rain_orderbook_test_fixtures::Orderbook; + use raindex_test_fixtures::Raindex; let token_contract = setup .local_evm @@ -405,7 +403,7 @@ pub mod local_evm { .expect("Token should exist"); token_contract - .approve(orderbook, amount) + .approve(raindex, amount) .from(setup.owner) .send() .await @@ -414,10 +412,10 @@ pub mod local_evm { .await .unwrap(); - let orderbook_instance = Orderbook::new(orderbook, setup.local_evm.provider.clone()); + let raindex_instance = Raindex::new(raindex, setup.local_evm.provider.clone()); let raw_amount = Float::from_fixed_decimal(amount, 18).unwrap().get_inner(); - orderbook_instance + raindex_instance .deposit4(token, vault_id, raw_amount, vec![]) .from(setup.owner) .send() @@ -429,34 +427,34 @@ pub mod local_evm { } pub fn create_vault(vault_id: B256, setup: &TestSetup, token: &SgErc20) -> SgVault { - create_vault_with_balance_and_orderbook( + create_vault_with_balance_and_raindex( vault_id, &setup.local_evm.anvil.addresses()[0], - setup.orderbook, + setup.raindex, token, "6", ) } - pub fn create_vault_for_orderbook( + pub fn create_vault_for_raindex( vault_id: B256, - setup: &MultiOrderbookTestSetup, - orderbook: Address, + setup: &MultiRaindexTestSetup, + raindex: Address, token: &SgErc20, ) -> SgVault { - create_vault_with_balance_and_orderbook( + create_vault_with_balance_and_raindex( vault_id, &setup.local_evm.anvil.addresses()[0], - orderbook, + raindex, token, "1000", ) } - pub fn create_vault_with_balance_and_orderbook( + pub fn create_vault_with_balance_and_raindex( vault_id: B256, owner: &Address, - orderbook: Address, + raindex: Address, token: &SgErc20, balance: &str, ) -> SgVault { @@ -466,8 +464,8 @@ pub mod local_evm { balance: SgBytes(Float::parse(balance.to_string()).unwrap().as_hex()), vault_id: SgBytes(vault_id.to_string()), owner: SgBytes(owner.to_string()), - orderbook: SgOrderbook { - id: SgBytes(orderbook.to_string()), + raindex: SgRaindex { + id: SgBytes(raindex.to_string()), }, orders_as_input: vec![], orders_as_output: vec![], @@ -478,7 +476,7 @@ pub mod local_evm { pub mod orders { use alloy::primitives::{Address, U256}; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; pub fn make_basic_order(input_token: Address, output_token: Address) -> OrderV4 { OrderV4 { @@ -530,18 +528,18 @@ pub mod orders { (order_bytes, order_hash) } - use super::super::local_evm::MultiOrderbookTestSetup; - use rain_orderbook_bindings::IRaindexV6::OrderV4; + use super::super::local_evm::MultiRaindexTestSetup; + use raindex_bindings::IRaindexV6::OrderV4; - pub async fn deploy_order_to_orderbook( - setup: &MultiOrderbookTestSetup, - orderbook: Address, + pub async fn deploy_order_to_raindex( + setup: &MultiRaindexTestSetup, + raindex: Address, dotrain: String, ) -> (String, B256, OrderV4) { use alloy::network::TransactionBuilder; use alloy::rpc::types::TransactionRequest; use alloy::serde::WithOtherFields; - use rain_orderbook_test_fixtures::Orderbook; + use raindex_test_fixtures::Raindex; let dotrain_order = DotrainOrder::create(dotrain.clone(), None).await.unwrap(); let deployment = dotrain_order @@ -559,7 +557,7 @@ pub mod orders { let tx_req = WithOtherFields::new( TransactionRequest::default() .with_input(calldata.to_vec()) - .with_to(orderbook) + .with_to(raindex) .with_from(setup.owner), ); @@ -574,7 +572,7 @@ pub mod orders { .inner .logs() .iter() - .find_map(|v| v.log_decode::().ok()) + .find_map(|v| v.log_decode::().ok()) .expect("Should have AddOrderV3 event") .inner .data; @@ -596,13 +594,9 @@ pub mod candidates { use super::orders::make_basic_order; - pub fn make_candidate( - orderbook: Address, - max_output: Float, - ratio: Float, - ) -> TakeOrderCandidate { + pub fn make_candidate(raindex: Address, max_output: Float, ratio: Float) -> TakeOrderCandidate { TakeOrderCandidate { - orderbook, + raindex, order: make_basic_order(Address::from([4u8; 20]), Address::from([5u8; 20])), input_io_index: 0, output_io_index: 0, @@ -620,7 +614,7 @@ pub mod candidates { pub mod quotes { use crate::raindex_client::order_quotes::{RaindexOrderQuote, RaindexOrderQuoteValue}; use rain_math_float::Float; - use rain_orderbook_quote::Pair; + use raindex_quote::Pair; pub fn make_quote_value( max_output: Float, @@ -666,14 +660,14 @@ pub mod quotes { #[cfg(not(target_family = "wasm"))] pub mod dotrain { use alloy::primitives::Address; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; - use super::local_evm::{MultiOrderbookTestSetup, TestSetup}; + use super::local_evm::{MultiRaindexTestSetup, TestSetup}; pub struct DotrainBuilder { rpc_url: String, rainlang: Address, - orderbook: Address, + raindex: Address, token1: Address, token2: Address, vault_id: String, @@ -688,7 +682,7 @@ pub mod dotrain { Self { rpc_url: setup.local_evm.url(), rainlang: setup.local_evm.rainlang, - orderbook: setup.orderbook, + raindex: setup.raindex, token1: setup.token1, token2: setup.token2, vault_id: "0x01".to_string(), @@ -702,11 +696,11 @@ pub mod dotrain { } } - pub fn from_multi_orderbook_setup(setup: &MultiOrderbookTestSetup) -> Self { + pub fn from_multi_raindex_setup(setup: &MultiRaindexTestSetup) -> Self { Self { rpc_url: setup.local_evm.url(), rainlang: setup.local_evm.rainlang, - orderbook: setup.orderbook_a, + raindex: setup.raindex_a, token1: setup.token1, token2: setup.token2, vault_id: "0x01".to_string(), @@ -735,8 +729,8 @@ pub mod dotrain { self } - pub fn with_orderbook(mut self, orderbook: Address) -> Self { - self.orderbook = orderbook; + pub fn with_raindex(mut self, raindex: Address) -> Self { + self.raindex = raindex; self } @@ -816,9 +810,9 @@ tokens: decimals: 18 label: Token2 symbol: Token2 -orderbook: - test-orderbook: - address: {orderbook} +raindex: + test-raindex: + address: {raindex} orders: test-order: inputs: @@ -844,7 +838,7 @@ amount price: {max_output} {ratio}; :; "#, rpc_url = self.rpc_url, - orderbook = self.orderbook, + raindex = self.raindex, rainlang = self.rainlang, token1 = self.token1, token2 = self.token2, @@ -889,15 +883,15 @@ amount price: {max_output} {ratio}; .build() } - pub fn create_dotrain_config_for_orderbook( - setup: &MultiOrderbookTestSetup, - orderbook: Address, + pub fn create_dotrain_config_for_raindex( + setup: &MultiRaindexTestSetup, + raindex: Address, vault_id: &str, max_output: &str, ratio: &str, ) -> String { - DotrainBuilder::from_multi_orderbook_setup(setup) - .with_orderbook(orderbook) + DotrainBuilder::from_multi_raindex_setup(setup) + .with_raindex(raindex) .with_single_io(vault_id) .with_max_output(max_output) .with_ratio(ratio) @@ -908,13 +902,11 @@ amount price: {max_output} {ratio}; #[cfg(not(target_family = "wasm"))] pub mod subgraph { use alloy::primitives::{Address, B256}; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgOrder, SgOrderbook, SgVault, - }; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_subgraph_client::types::common::{SgBigInt, SgBytes, SgOrder, SgRaindex, SgVault}; use serde_json::json; - use super::local_evm::{MultiOrderbookTestSetup, TestSetup}; + use super::local_evm::{MultiRaindexTestSetup, TestSetup}; pub fn create_sg_order( setup: &TestSetup, @@ -925,8 +917,8 @@ pub mod subgraph { ) -> SgOrder { SgOrder { id: SgBytes(order_hash.to_string()), - orderbook: SgOrderbook { - id: SgBytes(setup.orderbook.to_string()), + raindex: SgRaindex { + id: SgBytes(setup.raindex.to_string()), }, order_bytes: SgBytes(order_bytes), order_hash: SgBytes(order_hash.to_string()), @@ -942,7 +934,7 @@ pub mod subgraph { } } - fn vaults_to_json(vaults: &[SgVault], orderbook: Address) -> Vec { + fn vaults_to_json(vaults: &[SgVault], raindex: Address) -> Vec { vaults .iter() .map(|v| { @@ -958,7 +950,7 @@ pub mod subgraph { "symbol": v.token.symbol.clone().unwrap_or_default(), "decimals": v.token.decimals.clone().map(|d| d.0).unwrap_or_default() }, - "orderbook": { "id": orderbook.to_string() }, + "raindex": { "id": raindex.to_string() }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -974,8 +966,8 @@ pub mod subgraph { inputs: Vec, outputs: Vec, ) -> serde_json::Value { - create_sg_order_json_with_orderbook_and_owner( - setup.orderbook, + create_sg_order_json_with_raindex_and_owner( + setup.raindex, setup.owner, order_bytes, order_hash, @@ -984,16 +976,16 @@ pub mod subgraph { ) } - pub fn create_sg_order_json_with_orderbook( - setup: &MultiOrderbookTestSetup, - orderbook: Address, + pub fn create_sg_order_json_with_raindex( + setup: &MultiRaindexTestSetup, + raindex: Address, order_bytes: &str, order_hash: B256, inputs: Vec, outputs: Vec, ) -> serde_json::Value { - create_sg_order_json_with_orderbook_and_owner( - orderbook, + create_sg_order_json_with_raindex_and_owner( + raindex, setup.owner, order_bytes, order_hash, @@ -1002,16 +994,16 @@ pub mod subgraph { ) } - fn create_sg_order_json_with_orderbook_and_owner( - orderbook: Address, + fn create_sg_order_json_with_raindex_and_owner( + raindex: Address, owner: Address, order_bytes: &str, order_hash: B256, inputs: Vec, outputs: Vec, ) -> serde_json::Value { - let inputs_json = vaults_to_json(&inputs, orderbook); - let outputs_json = vaults_to_json(&outputs, orderbook); + let inputs_json = vaults_to_json(&inputs, raindex); + let outputs_json = vaults_to_json(&outputs, raindex); json!({ "id": order_hash.to_string(), @@ -1020,7 +1012,7 @@ pub mod subgraph { "owner": owner.to_string(), "outputs": outputs_json, "inputs": inputs_json, - "orderbook": { "id": orderbook.to_string() }, + "raindex": { "id": raindex.to_string() }, "active": true, "timestampAdded": "1739448802", "meta": null, @@ -1041,7 +1033,7 @@ pub mod subgraph { chain_id: u32, rpc_url: &str, sg_url: &str, - orderbook_address: &str, + raindex_address: &str, ) -> String { format!( r#" @@ -1057,9 +1049,9 @@ subgraphs: test-sg: {sg_url} metaboards: test-mb: http://localhost:0/notused -orderbooks: - test-orderbook: - address: {orderbook_address} +raindexes: + test-raindex: + address: {raindex_address} network: test-network subgraph: test-sg local-db-remote: remote @@ -1080,16 +1072,16 @@ tokens: chain_id = chain_id, rpc_url = rpc_url, sg_url = sg_url, - orderbook_address = orderbook_address, + raindex_address = raindex_address, ) } - pub fn get_multi_orderbook_yaml( + pub fn get_multi_raindex_yaml( chain_id: u32, rpc_url: &str, sg_url: &str, - orderbook_a: &str, - orderbook_b: &str, + raindex_a: &str, + raindex_b: &str, ) -> String { format!( r#" @@ -1105,15 +1097,15 @@ subgraphs: test-sg: {sg_url} metaboards: test-mb: http://localhost:0/notused -orderbooks: - orderbook-a: - address: {orderbook_a} +raindexes: + raindex-a: + address: {raindex_a} network: test-network subgraph: test-sg local-db-remote: remote deployment-block: 0 - orderbook-b: - address: {orderbook_b} + raindex-b: + address: {raindex_b} network: test-network subgraph: test-sg local-db-remote: remote @@ -1134,8 +1126,8 @@ tokens: chain_id = chain_id, rpc_url = rpc_url, sg_url = sg_url, - orderbook_a = orderbook_a, - orderbook_b = orderbook_b, + raindex_a = raindex_a, + raindex_b = raindex_b, ) } } diff --git a/crates/common/src/transaction.rs b/crates/common/src/transaction.rs index 8a9f6ed265..b28b95933a 100644 --- a/crates/common/src/transaction.rs +++ b/crates/common/src/transaction.rs @@ -52,7 +52,7 @@ pub enum TransactionArgsError { #[derive(Clone, Serialize, Deserialize, Default)] pub struct TransactionArgs { - pub orderbook_address: Address, + pub raindex_address: Address, pub derivation_index: Option, pub chain_id: Option, pub rpcs: Vec, @@ -139,12 +139,12 @@ mod tests { use httpmock::MockServer; use super::*; - use rain_orderbook_bindings::IRaindexV6::vaultBalance2Call; + use raindex_bindings::IRaindexV6::vaultBalance2Call; #[test] fn test_try_into_write_contract_parameters_ok() { let args = TransactionArgs { - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: None, chain_id: None, rpcs: vec!["https://mainnet.infura.io/v3/your-api-key".to_string()], @@ -168,7 +168,7 @@ mod tests { assert_eq!(params.max_fee_per_gas, None); let args = TransactionArgs { - orderbook_address: address!("123abcdef24Ca5003905aA834De7156C68b2E1d0"), + raindex_address: address!("123abcdef24Ca5003905aA834De7156C68b2E1d0"), derivation_index: Some(0), chain_id: Some(1), rpcs: vec!["https://mainnet.infura.io/v3/your-api-key".to_string()], @@ -211,7 +211,7 @@ mod tests { }); let mut args = TransactionArgs { - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: None, chain_id: None, rpcs: vec![server.url("/rpc")], @@ -238,7 +238,7 @@ mod tests { }); let mut args = TransactionArgs { - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: None, chain_id: None, rpcs: vec![server.url("/rpc")], @@ -272,7 +272,7 @@ mod tests { }); let args = TransactionArgs { - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: None, chain_id: None, rpcs: vec![server.url("/rpc")], diff --git a/crates/common/src/types/order_detail_extended.rs b/crates/common/src/types/order_detail_extended.rs index 98fa2d5b3d..a182feaebe 100644 --- a/crates/common/src/types/order_detail_extended.rs +++ b/crates/common/src/types/order_detail_extended.rs @@ -1,5 +1,5 @@ use crate::meta::{TryDecodeRainlangSource, TryDecodeRainlangSourceError}; -use rain_orderbook_subgraph_client::types::common::SgOrder; +use raindex_subgraph_client::types::common::SgOrder; use serde::{Deserialize, Serialize}; #[cfg(target_family = "wasm")] use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; @@ -36,8 +36,8 @@ impl TryFrom for OrderDetailExtended { mod tests { use super::*; use crate::meta::TryDecodeRainlangSourceError; - use rain_orderbook_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgOrderbook, + use raindex_subgraph_client::types::common::{ + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgRaindex, SgRemoveOrder, SgTransaction, SgVault, }; use std::convert::TryInto; @@ -46,7 +46,7 @@ mod tests { let default_sg_bytes = SgBytes(format!("default_{}", id_str)); let default_big_int = SgBigInt("0".to_string()); - let orderbook = SgOrderbook { + let raindex = SgRaindex { id: default_sg_bytes.clone(), }; @@ -64,7 +64,7 @@ mod tests { vault_id: default_sg_bytes.clone(), balance: default_sg_bytes.clone(), token: token.clone(), - orderbook: orderbook.clone(), + raindex: raindex.clone(), orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], @@ -84,7 +84,7 @@ mod tests { owner: default_sg_bytes.clone(), outputs: vec![vault.clone()], inputs: vec![vault.clone()], - orderbook, + raindex, active: true, timestamp_added: default_big_int.clone(), meta: meta_option, diff --git a/crates/common/src/types/order_takes_list_flattened.rs b/crates/common/src/types/order_takes_list_flattened.rs index 411febea20..76a7b0d01e 100644 --- a/crates/common/src/types/order_takes_list_flattened.rs +++ b/crates/common/src/types/order_takes_list_flattened.rs @@ -1,6 +1,6 @@ use crate::{csv::TryIntoCsv, utils::timestamp::format_bigint_timestamp_display}; use rain_math_float::Float; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -59,11 +59,11 @@ impl TryIntoCsv for Vec {} mod tests { use super::*; use rain_math_float::FloatError; - use rain_orderbook_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTrade, SgTradeEvent, SgTradeStructPartialOrder, + use raindex_subgraph_client::types::common::{ + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTrade, SgTradeEvent, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; // Helper to build a default, valid SgTrade instance fn mock_sg_trade_default() -> SgTrade { @@ -107,8 +107,8 @@ mod tests { block_number: SgBigInt("1000".to_string()), timestamp: SgBigInt("1678886400".to_string()), }, - orderbook: SgOrderbook { - id: SgBytes("orderbookVBCIn001".to_string()), + raindex: SgRaindex { + id: SgBytes("raindexVBCIn001".to_string()), }, trade: SgTradeRef { trade_event: SgTradeEventTypename { @@ -140,8 +140,8 @@ mod tests { block_number: SgBigInt("1000".to_string()), timestamp: SgBigInt("1678886400".to_string()), }, - orderbook: SgOrderbook { - id: SgBytes("orderbookVBCOut001".to_string()), + raindex: SgRaindex { + id: SgBytes("raindexVBCOut001".to_string()), }, trade: SgTradeRef { trade_event: SgTradeEventTypename { @@ -149,8 +149,8 @@ mod tests { }, }, }, - orderbook: SgOrderbook { - id: SgBytes("mainOrderbook001".to_string()), + raindex: SgRaindex { + id: SgBytes("mainRaindex001".to_string()), }, } } diff --git a/crates/common/src/types/orders_list_flattened.rs b/crates/common/src/types/orders_list_flattened.rs index af0e24237c..4b96749810 100644 --- a/crates/common/src/types/orders_list_flattened.rs +++ b/crates/common/src/types/orders_list_flattened.rs @@ -2,8 +2,8 @@ use crate::types::vault::NO_SYMBOL; use crate::{csv::TryIntoCsv, utils::timestamp::format_bigint_timestamp_display}; use alloy::dyn_abi::SolType; use alloy::primitives::hex::{decode, encode}; -use rain_orderbook_bindings::IRaindexV6::OrderV4; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_bindings::IRaindexV6::OrderV4; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -90,9 +90,9 @@ mod tests { primitives::{Address, Bytes, FixedBytes, B256, U256}, sol_types::SolValue, }; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; - use rain_orderbook_subgraph_client::types::common::{ - SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgOrderbook, + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; + use raindex_subgraph_client::types::common::{ + SgAddOrder, SgBigInt, SgBytes, SgErc20, SgOrderStructPartialTrade, SgRaindex, SgTransaction, SgVault, }; use std::str::FromStr; @@ -144,8 +144,8 @@ mod tests { symbol: Some("TOUT".into()), decimals: Some(SgBigInt("18".into())), }, - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -163,15 +163,15 @@ mod tests { symbol: Some("TIN".into()), decimals: Some(SgBigInt("18".into())), }, - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], }], - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, active: true, timestamp_added: SgBigInt("1678886400".into()), @@ -241,8 +241,8 @@ mod tests { id: SgBytes("vault-in-id-2".into()), owner: SgBytes("vault-owner-2".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -260,8 +260,8 @@ mod tests { id: SgBytes("vault-out-id-2".into()), owner: SgBytes("vault-owner-2".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -352,8 +352,8 @@ mod tests { id: SgBytes("vault-in-id".into()), owner: SgBytes("vault-owner".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -371,8 +371,8 @@ mod tests { id: SgBytes("vault-out-id".into()), owner: SgBytes("vault-owner".into()), balance: SgBytes("1000".into()), - orderbook: SgOrderbook { - id: SgBytes("ob-id".into()), + raindex: SgRaindex { + id: SgBytes("raindex-id".into()), }, vault_id: SgBytes("222".into()), token: SgErc20 { diff --git a/crates/common/src/types/token_vault_flattened.rs b/crates/common/src/types/token_vault_flattened.rs index d6399fb36b..add614c8c2 100644 --- a/crates/common/src/types/token_vault_flattened.rs +++ b/crates/common/src/types/token_vault_flattened.rs @@ -1,6 +1,6 @@ use crate::csv::TryIntoCsv; use rain_math_float::Float; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -44,10 +44,10 @@ impl TryIntoCsv for Vec {} #[cfg(test)] mod tests { use super::*; - use rain_orderbook_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgVault, SgVaultBalanceChangeType, + use raindex_subgraph_client::types::common::{ + SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgVault, SgVaultBalanceChangeType, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; #[allow(clippy::too_many_arguments)] fn create_sg_vault( @@ -73,8 +73,8 @@ mod tests { symbol: token_symbol.map(String::from), decimals: token_decimals_str.map(|s| SgBigInt(s.into())), }, - orderbook: SgOrderbook { - id: SgBytes("default_orderbook_id".into()), + raindex: SgRaindex { + id: SgBytes("default_raindex_id".into()), }, orders_as_output: Vec::::new(), orders_as_input: Vec::::new(), diff --git a/crates/common/src/types/vault_balance_change_flattened.rs b/crates/common/src/types/vault_balance_change_flattened.rs index 87c4eda76e..7fe14203a3 100644 --- a/crates/common/src/types/vault_balance_change_flattened.rs +++ b/crates/common/src/types/vault_balance_change_flattened.rs @@ -1,6 +1,6 @@ use crate::{csv::TryIntoCsv, utils::timestamp::format_bigint_timestamp_display}; use rain_math_float::Float; -use rain_orderbook_subgraph_client::types::common::*; +use raindex_subgraph_client::types::common::*; use serde::{Deserialize, Serialize}; use super::FlattenError; @@ -77,11 +77,11 @@ mod tests { use super::*; use crate::utils::timestamp::format_bigint_timestamp_display; use rain_math_float::FloatError; - use rain_orderbook_subgraph_client::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTransaction, SgVaultBalanceChangeUnwrapped, + use raindex_subgraph_client::types::common::{ + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTransaction, SgVaultBalanceChangeUnwrapped, SgVaultBalanceChangeVault, }; - use rain_orderbook_subgraph_client::utils::float::*; + use raindex_subgraph_client::utils::float::*; fn mock_sg_vault_balance_change_unwrapped( timestamp_val: &str, @@ -114,8 +114,8 @@ mod tests { decimals: decimals_val.map(|s| SgBigInt(s.to_string())), }, }, - orderbook: SgOrderbook { - id: SgBytes("0xorderbookid".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindexid".to_string()), }, } } diff --git a/crates/common/src/unit_tests.rs b/crates/common/src/unit_tests.rs index ef0aa9046b..22d54e14bc 100644 --- a/crates/common/src/unit_tests.rs +++ b/crates/common/src/unit_tests.rs @@ -13,12 +13,12 @@ use rain_interpreter_eval::{ fork::{Forker, NewForkedEvm}, trace::{RainEvalResultFromRawCallResultError, RainEvalResults}, }; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ blocks::BlockError, rainlang::RainlangCfg, unit_test::TestConfig, yaml::{ - orderbook::{OrderbookYaml, OrderbookYamlValidation}, + raindex::{RaindexYaml, RaindexYamlValidation}, YamlError, YamlParsable, }, }; @@ -29,7 +29,7 @@ use thiserror::Error; pub struct TestRunner { pub forker: Forker, pub dotrains: Dotrains, - pub orderbook_yamls: OrderbookYamls, + pub raindex_yamls: RaindexYamls, pub rng: TestRng, pub test_setup: TestSetup, pub test_config: TestConfig, @@ -49,9 +49,9 @@ pub struct Dotrains { } #[derive(Clone)] -pub struct OrderbookYamls { - pub main: OrderbookYaml, - pub test: OrderbookYaml, +pub struct RaindexYamls { + pub main: RaindexYaml, + pub test: RaindexYaml, } #[derive(Error, Debug)] @@ -89,17 +89,17 @@ impl TestRunner { test_config: &TestConfig, seed: Option<[u8; 32]>, ) -> Result { - let main_orderbook_yaml = OrderbookYaml::new( + let main_raindex_yaml = RaindexYaml::new( vec![RainDocument::get_front_matter(dotrain) .unwrap_or("") .to_string()], - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), )?; - let test_orderbook_yaml = OrderbookYaml::new( + let test_raindex_yaml = RaindexYaml::new( vec![RainDocument::get_front_matter(test_dotrain) .unwrap_or("") .to_string()], - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), )?; Ok(Self { @@ -108,9 +108,9 @@ impl TestRunner { main_dotrain: dotrain.into(), test_dotrain: test_dotrain.into(), }, - orderbook_yamls: OrderbookYamls { - main: main_orderbook_yaml, - test: test_orderbook_yaml, + raindex_yamls: RaindexYamls { + main: main_raindex_yaml, + test: test_raindex_yaml, }, rng: TestRng::from_seed(RngAlgorithm::ChaCha, &seed.unwrap_or([0; 32])), test_setup: TestSetup { @@ -393,7 +393,7 @@ impl TestRunner { pub async fn run_unit_test(&mut self) -> Result { self.test_setup.rainlang = Arc::new( - self.orderbook_yamls + self.raindex_yamls .main .get_rainlang(&self.test_config.scenario_name)?, ); @@ -437,8 +437,8 @@ impl TestRunner { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::{spec_version::SpecVersion, unit_test::UnitTestConfigSource}; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::{spec_version::SpecVersion, unit_test::UnitTestConfigSource}; + use raindex_test_fixtures::LocalEvm; fn get_test_config(test_dotrain: &str) -> TestConfig { let frontmatter = RainDocument::get_front_matter(test_dotrain).unwrap(); @@ -458,10 +458,10 @@ test: scenario-name: some-key scenario: bindings: - orderbook-subparser: {orderbook_subparser} + raindex-subparser: {raindex_subparser} second-binding: 999 --- -#orderbook-subparser ! +#raindex-subparser ! #second-binding ! #pre @@ -470,7 +470,7 @@ output-token: 0x02, output-cap: 10; #post -using-words-from orderbook-subparser +using-words-from raindex-subparser /* calculate io stack */ :ensure(equal-to(calculated-io-ratio() 999) "io ratio should be 999"), @@ -481,7 +481,7 @@ using-words-from orderbook-subparser /* handle io stack */ :ensure(equal-to(output-vault-decrease() 10) "output cap should be 10"); "#, - orderbook_subparser = local_evm.orderbook_subparser.address(), + raindex_subparser = local_evm.raindex_subparser.address(), spec_version = SpecVersion::current() ); let dotrain = format!( @@ -498,27 +498,27 @@ networks: scenarios: some-key: bindings: - orderbook-subparser: {orderbook_subparser} + raindex-subparser: {raindex_subparser} second-binding: 20 --- -#orderbook-subparser ! +#raindex-subparser ! #second-binding ! #calculate-io -using-words-from orderbook-subparser +using-words-from raindex-subparser _: input-token(), _: output-token(), a: 10, b: second-binding; #handle-io -using-words-from orderbook-subparser +using-words-from raindex-subparser _: output-vault-decrease(); "#, rpc_url = local_evm.url(), rainlang_address = local_evm.rainlang, - orderbook_subparser = local_evm.orderbook_subparser.address(), + raindex_subparser = local_evm.raindex_subparser.address(), spec_version = SpecVersion::current() ); diff --git a/crates/common/src/withdraw.rs b/crates/common/src/withdraw.rs index dbc1129eee..8fe61c9c0f 100644 --- a/crates/common/src/withdraw.rs +++ b/crates/common/src/withdraw.rs @@ -8,7 +8,7 @@ use alloy_ethers_typecast::{WriteTransaction, WriteTransactionStatus}; use serde::{Deserialize, Serialize}; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::withdraw4Call; +use raindex_bindings::IRaindexV6::withdraw4Call; #[derive(Clone, Deserialize, Serialize, Debug)] pub struct WithdrawArgs { @@ -29,7 +29,7 @@ impl From for withdraw4Call { } impl WithdrawArgs { - /// Execute OrderbookV3 withdraw call + /// Execute Raindex withdraw call #[cfg(not(target_family = "wasm"))] pub async fn execute)>( &self, @@ -39,10 +39,8 @@ impl WithdrawArgs { let (ledger_client, _) = transaction_args.clone().try_into_ledger_client().await?; let withdraw_call: withdraw4Call = self.clone().into(); - let params = transaction_args.try_into_write_contract_parameters( - withdraw_call, - transaction_args.orderbook_address, - )?; + let params = transaction_args + .try_into_write_contract_parameters(withdraw_call, transaction_args.raindex_address)?; WriteTransaction::new(ledger_client, params, 4, transaction_status_changed) .execute() @@ -109,7 +107,7 @@ mod tests { fn test_withdraw_call_try_into_write_contract_parameters() { let args = TransactionArgs { rpcs: vec!["http://test.com".to_string()], - orderbook_address: Address::ZERO, + raindex_address: Address::ZERO, derivation_index: Some(0_usize), chain_id: Some(1), max_priority_fee_per_gas: Some(200), diff --git a/crates/integration_tests/Cargo.toml b/crates/integration_tests/Cargo.toml index 8babd28d72..7c48631957 100644 --- a/crates/integration_tests/Cargo.toml +++ b/crates/integration_tests/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rain_orderbook_integration_tests" +name = "raindex_integration_tests" version.workspace = true edition.workspace = true license.workspace = true @@ -10,9 +10,9 @@ publish = false [dev-dependencies] tokio = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_test_fixtures = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_test_fixtures = { workspace = true } alloy = { workspace = true, features = ["full", "node-bindings"] } -rain_orderbook_common = { workspace = true } +raindex_common = { workspace = true } serde_json = { workspace = true } rain-math-float.workspace = true diff --git a/crates/integration_tests/src/lib.rs b/crates/integration_tests/src/lib.rs index f16a0ed43e..ddbd55da36 100644 --- a/crates/integration_tests/src/lib.rs +++ b/crates/integration_tests/src/lib.rs @@ -9,15 +9,15 @@ mod tests { rpc::types::TransactionRequest, }; use rain_math_float::Float; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; - use rain_orderbook_test_fixtures::{LocalEvm, Orderbook::QuoteV2}; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; + use raindex_test_fixtures::{LocalEvm, Raindex::QuoteV2}; #[tokio::test] async fn test_post_task_set() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); @@ -50,9 +50,9 @@ tokens: decimals: 18 label: Dai symbol: DAI -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -72,7 +72,7 @@ deployments: --- #key1 !Test binding #calculate-io -using-words-from {orderbook_subparser} +using-words-from {raindex_subparser} amount price: get("amount") 52; #handle-add-order :set("amount" 100); @@ -80,8 +80,8 @@ amount price: get("amount") 52; :; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), - orderbook_subparser = local_evm.orderbook_subparser.address(), + raindex = raindex.address(), + raindex_subparser = local_evm.raindex_subparser.address(), rainlang_address = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -115,7 +115,7 @@ amount price: get("amount") 52; .order; let quote = local_evm - .call_contract(orderbook.quote2(QuoteV2 { + .call_contract(raindex.quote2(QuoteV2 { order, inputIOIndex: U256::from(0), outputIOIndex: U256::from(0), @@ -138,7 +138,7 @@ amount price: get("amount") 52; #[tokio::test] async fn test_post_task_revert() { let local_evm = LocalEvm::new().await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let dotrain = format!( r#" @@ -166,9 +166,9 @@ tokens: decimals: 18 label: Dai symbol: DAI -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -195,7 +195,7 @@ amount price: get("amount") 52; :ensure(0 "should fail"); "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang_address = local_evm.rainlang, spec_version = SpecVersion::current(), ); @@ -214,7 +214,7 @@ amount price: get("amount") 52; .abi_encode(); let tx = TransactionRequest::default() .with_input(calldata) - .with_to(*orderbook.address()); + .with_to(*raindex.address()); let res = local_evm .send_transaction(WithOtherFields::new(tx)) diff --git a/crates/js_api/ARCHITECTURE.md b/crates/js_api/ARCHITECTURE.md index 9ff1ed82d6..a04cfb121e 100644 --- a/crates/js_api/ARCHITECTURE.md +++ b/crates/js_api/ARCHITECTURE.md @@ -1,17 +1,17 @@ **Overview** -- Purpose: `rain_orderbook_js_api` exposes a single, browser-friendly WebAssembly surface for the Rain Orderbook application. It bridges YAML-based “dotrain” order configuration, on-chain ERC‑20/token metadata, and contract call generation into a typed JavaScript/TypeScript API. +- Purpose: `raindex_js_api` exposes a single, browser-friendly WebAssembly surface for the Raindex application. It bridges YAML-based “dotrain” order configuration, on-chain ERC‑20/token metadata, and contract call generation into a typed JavaScript/TypeScript API. - Target: Compiles as a `cdylib` for wasm and is designed to be consumed from JS environments (webapps). All public APIs are exported via `wasm_bindgen_utils` macros and return ergonomic results with rich, user‑readable errors. - Scope: Includes high-level GUI helpers for interactive order building, a fetchable registry of orders, and low-level helpers for hashing and ABI calldata generation. It re-exports certain sibling crates so their wasm bindings are reachable from a single import. **Build & Targets** - Crate type: `cdylib` (WASM output). Most modules are `#[cfg(target_family = "wasm")]` as they are JS/GUI facing. -- Key dependencies: `wasm-bindgen-utils`, `alloy` (ABI/primitives), `rain_orderbook_*` crates for app models + on-chain helpers, `tokio` (async), `reqwest` (HTTP, registry), `flate2`/`base64`/`bincode`/`sha2` (state serialization), `strict-yaml-rust` (YAML AST). +- Key dependencies: `wasm-bindgen-utils`, `alloy` (ABI/primitives), `raindex_*` crates for app models + on-chain helpers, `tokio` (async), `reqwest` (HTTP, registry), `flate2`/`base64`/`bincode`/`sha2` (state serialization), `strict-yaml-rust` (YAML AST). - TypeScript support: Adds TS definitions for `Address` and `Hex` template literal types and uses `tsify` to describe return/param types of exported structs. **Top-Level Layout** - `src/lib.rs` - Exposes modules only when targeting wasm: `bindings`, `gui`, `registry`, `yaml`. - - Re-exports crates so their wasm bindings are available from this single module: `rain_orderbook_app_settings`, `rain_orderbook_common`, `rain_orderbook_subgraph_client`. + - Re-exports crates so their wasm bindings are available from this single module: `raindex_app_settings`, `raindex_common`, `raindex_subgraph_client`. - Appends a small TS section defining `Address` and `Hex` template literal types for better typing on the JS side. **FFI & Error Conventions** @@ -28,7 +28,7 @@ - Key types and exports: - `TakeOrdersCalldata(Bytes)` as an opaque JS type for encoded calldata. - `getOrderHash(order: OrderV4) -> string`: ABI-encodes `OrderV4` and returns `keccak256` with `0x` prefix. - - `getTakeOrders4Calldata(config: TakeOrdersConfigV5) -> TakeOrdersCalldata`: ABI-encodes a `takeOrders4` call for the on-chain OrderBook. + - `getTakeOrders4Calldata(config: TakeOrdersConfigV5) -> TakeOrdersCalldata`: ABI-encodes a `takeOrders4` call for the on-chain Raindex. - `keccak256(bytes: Uint8Array) -> string` and `keccak256HexString(hex: string) -> string`. - Errors: `Error::FromHexError` mapped to JS with human-readable message. @@ -85,10 +85,10 @@ - Generates all calldata required to deploy orders and related flows. - Internal preparation: - `prepare_calldata_generation` validates select-tokens, ensures field values exist as needed, populates vault IDs, and updates scenario bindings before generating any calldata. - - `get_orderbook()` and `get_transaction_args()` collect the orderbook address and RPCs for downstream calls. + - `get_raindex()` and `get_transaction_args()` collect the raindex address and RPCs for downstream calls. - `get_deposits_as_map()` and `get_vaults_and_deposits()` resolve deposit amounts by token/address and match them to order outputs + vaults. - Allowance/approvals: - - `checkAllowances(owner) -> AllowancesResult`: queries current allowances for each deposit token against the orderbook. + - `checkAllowances(owner) -> AllowancesResult`: queries current allowances for each deposit token against the raindex. - `generateApprovalCalldatas(owner) -> ApprovalCalldataResult`: compares allowances to desired deposit amounts and, when they differ, emits ERC‑20 `approve` calldatas that set the allowance to the exact target value. - Deposits: - `generateDepositCalldatas() -> DepositCalldataResult`: builds `deposit3` calldatas for non-zero deposits using vault IDs (fetches decimals on-chain if missing in YAML). @@ -96,7 +96,7 @@ - `generateAddOrderCalldata() -> AddOrderCalldataResult`: composes Rainlang, builds an `AddOrderArgs` from the deployment, and returns the ABI-encoded call. - Combined deployment: - `generateDepositAndAddOrderCalldatas() -> DepositAndAddOrderCalldataResult`: constructs a `multicall` that first performs `addOrder`, then all deposits. - - `getDeploymentTransactionArgs(owner) -> DeploymentTransactionArgs`: packages approval calldatas (with token symbol for UX), multicall calldata, orderbook address, and chain ID for a one-shot deployment flow. + - `getDeploymentTransactionArgs(owner) -> DeploymentTransactionArgs`: packages approval calldatas (with token symbol for UX), multicall calldata, raindex address, and chain ID for a one-shot deployment flow. - Vault IDs: - `setVaultId(type: 'input'|'output', tokenKey, vaultId?: string)`, `getVaultIds() -> IOVaultIds`, and `hasAnyVaultId() -> boolean`. - Types exposed for JS: `AllowancesResult`, `ApprovalCalldataResult|DepositCalldataResult|AddOrderCalldataResult|DepositAndAddOrderCalldataResult`, `ExtendedApprovalCalldata`, `DeploymentTransactionArgs`, `IOVaultIds`. A `WithdrawCalldataResult` type exists but no public generator yet. @@ -130,22 +130,22 @@ - `getAllOrderDetails()` → parse order-level metadata for every merged dotrain, returning both valid and invalid entries (with errors) keyed by order. - `getOrderKeys()` → keys from `order_urls`. - `getDeploymentDetails(orderKey)` → deployment name/description map for a specific order. - - `getOrderbookYaml() -> OrderbookYaml` → returns an `OrderbookYaml` instance from the registry's shared settings YAML for querying tokens, networks, orderbooks, etc. + - `getRaindexYaml() -> RaindexYaml` → returns a `RaindexYaml` instance from the registry's shared settings YAML for querying tokens, networks, raindexes, etc. - `getGui(orderKey, deploymentKey, serializedState?, stateCallback?)` → merge `settings + order`, optionally restore serialized state, and produce a `DotrainOrderGui` instance. - Errors: `DotrainRegistryError` covers fetch/parse/HTTP/URL issues and wraps `GuiError`. Also returns human-readable messages. - `yaml` (src/yaml/mod.rs) - - Purpose: Wasm-friendly wrapper around orderbook YAML parsing to retrieve configuration objects by address or query token metadata. + - Purpose: Wasm-friendly wrapper around raindex YAML parsing to retrieve configuration objects by address or query token metadata. - Exports: - - `OrderbookYaml.new([yamlSources], validate?) -> OrderbookYaml`: parse/merge/optionally validate sources. - - `OrderbookYaml.getOrderbookByAddress(address) -> OrderbookCfg`. - - `OrderbookYaml.getTokens() -> TokenInfo[]` (async): returns all tokens from YAML with `chain_id`, `address`, `decimals`, `symbol`, and `name`. Automatically fetches remote tokens from `using-tokens-from` URLs. - - Errors: `OrderbookYamlError` with readable messaging, converted to JS. + - `RaindexYaml.new([yamlSources], validate?) -> RaindexYaml`: parse/merge/optionally validate sources. + - `RaindexYaml.getRaindexByAddress(address) -> RaindexCfg`. + - `RaindexYaml.getTokens() -> TokenInfo[]` (async): returns all tokens from YAML with `chain_id`, `address`, `decimals`, `symbol`, and `name`. Automatically fetches remote tokens from `using-tokens-from` URLs. + - Errors: `RaindexYamlError` with readable messaging, converted to JS. **External Crates & Interactions** -- `rain_orderbook_app_settings`: typed config model + YAML parsing helpers for GUI sections, deployments, networks, orders, select-tokens, and validation rules. -- `rain_orderbook_common`: higher-level order manipulation (compose Rainlang, add order args), ERC‑20 RPC client, transaction helpers, and formatting utilities. -- `rain_orderbook_bindings`: generated Solidity bindings for `IOrderBookV5` (e.g., `deposit3`, `multicall`, `takeOrders3`). +- `raindex_app_settings`: typed config model + YAML parsing helpers for GUI sections, deployments, networks, orders, select-tokens, and validation rules. +- `raindex_common`: higher-level order manipulation (compose Rainlang, add order args), ERC‑20 RPC client, transaction helpers, and formatting utilities. +- `raindex_bindings`: generated Solidity bindings for `IRaindexV5` (e.g., `deposit3`, `multicall`, `takeOrders3`). - `alloy`: ABI encoding/decoding, primitives (`Address`, `Bytes`, `U256`, keccak256), and Solidity type utilities. - `wasm-bindgen-utils`: export macro, JS bridging, `WasmEncodedError` packaging. @@ -154,7 +154,7 @@ - Parse dotrain (frontmatter YAML + Rainlang body) with `DotrainOrder::create`. - Initialize GUI with a deployment key. - Optional: select tokens via on-chain metadata, set field values (with validation), set deposit amounts (with validation), and set vault IDs. - - Generate approvals if needed, deposits, add order calldata, or a combined multicall. Transaction args include orderbook address and chain ID. + - Generate approvals if needed, deposits, add order calldata, or a combined multicall. Transaction args include raindex address and chain ID. - State persistence: - Any setter triggers `executeStateUpdateCallback()` with a gzipped/base64 state snapshot that includes a dotrain content hash. `newFromState` restores and protects against mismatched content. - Token metadata: @@ -191,4 +191,4 @@ - `const registry = await DotrainRegistry.new(registryUrl)` → inspect orders/deployments → `await registry.getGui(orderKey, deploymentKey, serializedState?, onStateChanged?)`. **Summary** -- `rain_orderbook_js_api` is the JS/WASM gateway for building, validating, and deploying Rain Orderbook orders from YAML+Rainlang definitions. It centralizes: YAML parsing and validation, user input state, token selection and metadata, field and deposit validation, vault ID management, transaction calldata generation (approvals, deposits, add order, multicall), registry-driven content fetching, and robust error handling—exposed as a typed, ergonomic TypeScript surface. +- `raindex_js_api` is the JS/WASM gateway for building, validating, and deploying Raindex orders from YAML+Rainlang definitions. It centralizes: YAML parsing and validation, user input state, token selection and metadata, field and deposit validation, vault ID management, transaction calldata generation (approvals, deposits, add order, multicall), registry-driven content fetching, and robust error handling—exposed as a typed, ergonomic TypeScript surface. diff --git a/crates/js_api/Cargo.toml b/crates/js_api/Cargo.toml index 9d7d0f2004..eee4356a65 100644 --- a/crates/js_api/Cargo.toml +++ b/crates/js_api/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rain_orderbook_js_api" +name = "raindex_js_api" description = "Javascript bindings for common functions accross the app." version.workspace = true edition.workspace = true @@ -16,11 +16,11 @@ cynic = { workspace = true } reqwest = { workspace = true } thiserror = { workspace = true } futures = { workspace = true } -rain_orderbook_common = { workspace = true } -rain_orderbook_app_settings = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_quote = { workspace = true } +raindex_common = { workspace = true } +raindex_app_settings = { workspace = true } +raindex_subgraph_client = { workspace = true } +raindex_bindings = { workspace = true } +raindex_quote = { workspace = true } alloy-ethers-typecast = { workspace = true } wasm-bindgen-utils = { workspace = true } tokio = { workspace = true, features = [ diff --git a/crates/js_api/src/bindings/mod.rs b/crates/js_api/src/bindings/mod.rs index ca116f6bf4..4a4f7d0c3b 100644 --- a/crates/js_api/src/bindings/mod.rs +++ b/crates/js_api/src/bindings/mod.rs @@ -8,7 +8,7 @@ use alloy::{ }, sol_types::SolCall, }; -use rain_orderbook_bindings::IRaindexV6::{takeOrders4Call, OrderV4, TakeOrdersConfigV5}; +use raindex_bindings::IRaindexV6::{takeOrders4Call, OrderV4, TakeOrdersConfigV5}; use serde::{Deserialize, Serialize}; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; @@ -43,7 +43,7 @@ pub fn get_order_hash( Ok(encode_prefixed(main_keccak256(order.abi_encode()))) } -/// Generates ABI-encoded calldata for the `takeOrders3()` function on the OrderBook smart contract. +/// Generates ABI-encoded calldata for the `takeOrders3()` function on the Raindex smart contract. /// /// ## Examples /// diff --git a/crates/js_api/src/gui/deposits.rs b/crates/js_api/src/gui/deposits.rs index e44fcd60a7..0789b4efce 100644 --- a/crates/js_api/src/gui/deposits.rs +++ b/crates/js_api/src/gui/deposits.rs @@ -1,5 +1,5 @@ use super::*; -use rain_orderbook_app_settings::gui::GuiDepositCfg; +use raindex_app_settings::gui::GuiDepositCfg; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Tsify)] pub struct TokenDeposit { diff --git a/crates/js_api/src/gui/mod.rs b/crates/js_api/src/gui/mod.rs index 24a1531e69..bbf4e2ca8b 100644 --- a/crates/js_api/src/gui/mod.rs +++ b/crates/js_api/src/gui/mod.rs @@ -4,7 +4,7 @@ use base64::{engine::general_purpose::URL_SAFE, Engine}; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; use rain_math_float::FloatError; use rain_metaboard_subgraph::metaboard_client::MetaboardSubgraphClientError; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ deployment::DeploymentCfg, gui::{ GuiCfg, GuiDeploymentCfg, GuiFieldDefinitionCfg, GuiPresetCfg, NameAndDescriptionCfg, @@ -17,8 +17,8 @@ use rain_orderbook_app_settings::{ emitter, YamlError, YamlParsable, }, }; -pub use rain_orderbook_common::erc20::ExtendedTokenInfo; -use rain_orderbook_common::{ +pub use raindex_common::erc20::ExtendedTokenInfo; +use raindex_common::{ dotrain::{types::patterns::FRONTMATTER_SEPARATOR, RainDocument}, dotrain_order::{DotrainOrder, DotrainOrderError}, erc20::ERC20, @@ -298,7 +298,7 @@ impl DotrainOrderGui { #[wasm_export(param_description = "Token identifier from the YAML tokens section")] key: String, ) -> Result { - let token = self.dotrain_order.orderbook_yaml().get_token(&key)?; + let token = self.dotrain_order.raindex_yaml().get_token(&key)?; Ok(ExtendedTokenInfo::from_token_cfg(&token).await?) } @@ -627,8 +627,8 @@ pub enum GuiError { MissingDepositToken(String), #[error("Deposit amount cannot be an empty string")] DepositAmountCannotBeEmpty, - #[error("Orderbook not found")] - OrderbookNotFound, + #[error("Raindex not found")] + RaindexNotFound, #[error("Order not found: {0}")] OrderNotFound(String), #[error("Deserialized dotrain mismatch")] @@ -668,7 +668,7 @@ pub enum GuiError { #[error(transparent)] ReadableClientError(#[from] ReadableClientError), #[error(transparent)] - DepositError(#[from] rain_orderbook_common::deposit::DepositError), + DepositError(#[from] raindex_common::deposit::DepositError), #[error(transparent)] ParseError(#[from] alloy::primitives::ruint::ParseError), #[error(transparent)] @@ -679,12 +679,12 @@ pub enum GuiError { UnitsError(#[from] alloy::primitives::utils::UnitsError), #[error(transparent)] WritableTransactionExecuteError( - #[from] rain_orderbook_common::transaction::WritableTransactionExecuteError, + #[from] raindex_common::transaction::WritableTransactionExecuteError, ), #[error(transparent)] - AddOrderArgsError(#[from] rain_orderbook_common::add_order::AddOrderArgsError), + AddOrderArgsError(#[from] raindex_common::add_order::AddOrderArgsError), #[error(transparent)] - ERC20Error(#[from] rain_orderbook_common::erc20::Error), + ERC20Error(#[from] raindex_common::erc20::Error), #[error(transparent)] SolTypesError(#[from] alloy::sol_types::Error), #[error(transparent)] @@ -726,8 +726,8 @@ impl GuiError { format!("A deposit for token is required but has not been set for deployment '{}'.", deployment), GuiError::DepositAmountCannotBeEmpty => "The deposit amount cannot be an empty string. Please set a valid amount.".to_string(), - GuiError::OrderbookNotFound => - "The orderbook configuration could not be found. Please check your YAML configuration.".to_string(), + GuiError::RaindexNotFound => + "The raindex configuration could not be found. Please check your YAML configuration.".to_string(), GuiError::OrderNotFound(order) => format!("The order '{}' could not be found in the YAML configuration.", order), GuiError::DotrainMismatch => @@ -820,8 +820,8 @@ impl From for WasmEncodedError { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_app_settings::yaml::FieldErrorKind; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_app_settings::yaml::FieldErrorKind; use wasm_bindgen_test::wasm_bindgen_test; pub fn get_yaml() -> String { @@ -936,8 +936,8 @@ rainlangs: some-rainlang: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -974,14 +974,14 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex other-order: inputs: - token: token1 outputs: - token: token1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: scenario: some-scenario @@ -1165,8 +1165,8 @@ rainlangs: test-rainlang: network: test-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - test-orderbook: +raindexes: + test-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: test-network subgraph: test-sg @@ -1223,7 +1223,7 @@ orders: - token: token1 vault-id: 1 rainlang: test-rainlang - orderbook: test-orderbook + raindex: test-raindex deployments: validation-deployment: scenario: test-scenario @@ -1998,8 +1998,8 @@ rainlangs: some-rainlang: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg diff --git a/crates/js_api/src/gui/order_operations.rs b/crates/js_api/src/gui/order_operations.rs index 147b327965..209f3021ce 100644 --- a/crates/js_api/src/gui/order_operations.rs +++ b/crates/js_api/src/gui/order_operations.rs @@ -9,14 +9,12 @@ use rain_metaboard_subgraph::metaboard_client::{ }; use rain_metaboard_subgraph::types::metas::BigInt as MetaBigInt; use rain_metadata::RainMetaDocumentV1Item; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ order::{OrderIOCfg, VaultType}, - orderbook::OrderbookCfg, + raindex::RaindexCfg, }; -use rain_orderbook_bindings::{ - IRaindexV6::deposit4Call, OrderBook::multicallCall, IERC20::approveCall, -}; -use rain_orderbook_common::{ +use raindex_bindings::{IRaindexV6::deposit4Call, Raindex::multicallCall, IERC20::approveCall}; +use raindex_common::{ add_order::AddOrderArgs, deposit::DepositArgs, erc20::ERC20, transaction::TransactionArgs, }; use std::{collections::HashMap, str::FromStr, sync::Arc}; @@ -101,7 +99,7 @@ pub struct DeploymentTransactionArgs { #[tsify(type = "string")] deployment_calldata: Bytes, #[tsify(type = "string")] - orderbook_address: Address, + raindex_address: Address, chain_id: u32, #[tsify(type = "ExternalCall | undefined")] emit_meta_call: Option, @@ -128,24 +126,24 @@ pub struct VaultAndDeposit { #[wasm_export] impl DotrainOrderGui { - fn get_orderbook(&self) -> Result, GuiError> { + fn get_raindex(&self) -> Result, GuiError> { let deployment = self.get_current_deployment()?; deployment .deployment .as_ref() .order .as_ref() - .orderbook + .raindex .as_ref() - .ok_or(GuiError::OrderbookNotFound) + .ok_or(GuiError::RaindexNotFound) .cloned() } fn get_transaction_args(&self) -> Result { - let orderbook = self.get_orderbook()?; + let raindex = self.get_raindex()?; Ok(TransactionArgs { - orderbook_address: orderbook.address, - rpcs: orderbook + raindex_address: raindex.address, + rpcs: raindex .network .rpcs .clone() @@ -227,7 +225,7 @@ impl DotrainOrderGui { self.get_current_deployment() } - /// Checks token allowances for all deposits against the orderbook contract. + /// Checks token allowances for all deposits against the raindex contract. /// /// Queries the blockchain to determine current allowances for each output token that /// will be deposited. This helps determine which tokens need approval before @@ -285,7 +283,7 @@ impl DotrainOrderGui { .address; let erc20 = ERC20::new(rpcs, token); - let allowance = erc20.allowance(owner, tx_args.orderbook_address).await?; + let allowance = erc20.allowance(owner, tx_args.raindex_address).await?; results.push(TokenAllowance { token, allowance }); } @@ -356,7 +354,7 @@ impl DotrainOrderGui { if !allowance_float.eq(*deposit_amount)? { let calldata = approveCall { - spender: tx_args.orderbook_address, + spender: tx_args.raindex_address, amount: deposit_amount.to_fixed_decimal(decimals)?, } .abi_encode(); @@ -414,7 +412,7 @@ impl DotrainOrderGui { Ok(add_order_args) } - /// Generates calldata for depositing tokens into orderbook vaults. + /// Generates calldata for depositing tokens into raindex vaults. /// /// Creates deposit calldatas for all configured deposits, automatically /// skipping zero amounts and ensuring vault IDs are properly assigned. @@ -487,7 +485,7 @@ impl DotrainOrderGui { decimals, }; let calldata = deposit4Call::try_from(deposit_args) - .map_err(rain_orderbook_common::deposit::DepositError::from)? + .map_err(raindex_common::deposit::DepositError::from)? .abi_encode(); calldatas.push(Bytes::copy_from_slice(&calldata)); } @@ -495,7 +493,7 @@ impl DotrainOrderGui { Ok(DepositCalldataResult::Calldatas(calldatas)) } - /// Generates calldata for adding the order to the orderbook. + /// Generates calldata for adding the order to the raindex. /// /// Creates the addOrder calldata with all field values applied to the /// Rainlang code and proper vault configurations. @@ -738,7 +736,7 @@ impl DotrainOrderGui { /// /// - `approvals` - Token approval calldatas with symbols for UI /// - `deploymentCalldata` - Main order deployment calldata - /// - `orderbookAddress` - Target contract address + /// - `raindexAddress` - Target contract address /// - `chainId` - Network identifier /// /// # Examples @@ -756,8 +754,8 @@ impl DotrainOrderGui { /// approvals, /// // deploymentCalldata is the multicall calldata for the order /// deploymentCalldata, - /// // orderbookAddress is the address of the orderbook - /// orderbookAddress, + /// // raindexAddress is the address of the raindex + /// raindexAddress, /// // chainId is the chain ID of the network /// chainId, /// } = result.value; @@ -840,12 +838,12 @@ impl DotrainOrderGui { Ok(DeploymentTransactionArgs { approvals, deployment_calldata, - orderbook_address: deployment + raindex_address: deployment .deployment .order - .orderbook + .raindex .as_ref() - .ok_or(GuiError::OrderbookNotFound)? + .ok_or(GuiError::RaindexNotFound)? .address, chain_id: deployment.deployment.order.network.chain_id, emit_meta_call, @@ -854,9 +852,8 @@ impl DotrainOrderGui { fn get_metaboard_client(&self) -> Result { let deployment = self.get_current_deployment()?; - let orderbook_yaml = self.dotrain_order.orderbook_yaml(); - let metaboard_cfg = - orderbook_yaml.get_metaboard(&deployment.deployment.order.network.key)?; + let raindex_yaml = self.dotrain_order.raindex_yaml(); + let metaboard_cfg = raindex_yaml.get_metaboard(&deployment.deployment.order.network.key)?; Ok(MetaboardSubgraphClient::new(metaboard_cfg.url.clone())) } diff --git a/crates/js_api/src/gui/select_tokens.rs b/crates/js_api/src/gui/select_tokens.rs index 705be8e644..667042becd 100644 --- a/crates/js_api/src/gui/select_tokens.rs +++ b/crates/js_api/src/gui/select_tokens.rs @@ -1,11 +1,11 @@ use super::*; use futures::StreamExt; use rain_math_float::Float; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ deployment::DeploymentCfg, gui::GuiSelectTokensCfg, network::NetworkCfg, order::OrderCfg, token::TokenCfg, yaml::YamlParsableHash, }; -use rain_orderbook_common::raindex_client::vaults::AccountBalance; +use raindex_common::raindex_client::vaults::AccountBalance; use std::str::FromStr; const MAX_CONCURRENT_FETCHES: usize = 5; @@ -70,7 +70,7 @@ impl DotrainOrderGui { #[wasm_export(param_description = "Token key from select-tokens configuration")] key: String, ) -> Result { - Ok(self.dotrain_order.orderbook_yaml().get_token(&key).is_ok()) + Ok(self.dotrain_order.raindex_yaml().get_token(&key).is_ok()) } /// Validates that all required tokens have been selected. @@ -102,7 +102,7 @@ impl DotrainOrderGui { for select_token in select_tokens { if self .dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_token(&select_token.key) .is_err() { @@ -159,7 +159,7 @@ impl DotrainOrderGui { if TokenCfg::parse_from_yaml(self.dotrain_order.dotrain_yaml().documents, &key, None) .is_ok() { - TokenCfg::remove_record_from_yaml(self.dotrain_order.orderbook_yaml().documents, &key)?; + TokenCfg::remove_record_from_yaml(self.dotrain_order.raindex_yaml().documents, &key)?; } let address = Address::from_str(&address)?; @@ -177,7 +177,7 @@ impl DotrainOrderGui { let token_info = erc20.token_info(None).await?; TokenCfg::add_record_to_yaml( - self.dotrain_order.orderbook_yaml().documents, + self.dotrain_order.raindex_yaml().documents, &key, &network_key, &address.to_string(), @@ -219,7 +219,7 @@ impl DotrainOrderGui { return Err(GuiError::TokenNotFound(key.clone())); } - TokenCfg::remove_record_from_yaml(self.dotrain_order.orderbook_yaml().documents, &key)?; + TokenCfg::remove_record_from_yaml(self.dotrain_order.raindex_yaml().documents, &key)?; self.execute_state_update_callback()?; Ok(()) @@ -292,7 +292,7 @@ impl DotrainOrderGui { )?; let network_key = OrderCfg::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?; - let tokens = self.dotrain_order.orderbook_yaml().get_tokens()?; + let tokens = self.dotrain_order.raindex_yaml().get_tokens()?; let mut fetch_futures = Vec::new(); @@ -377,7 +377,7 @@ impl DotrainOrderGui { OrderCfg::parse_network_key(self.dotrain_order.dotrain_yaml().documents, &order_key)?; let network = self .dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_network(&network_key)?; let erc20 = ERC20::new(network.rpcs, Address::from_str(&token_address)?); @@ -403,7 +403,7 @@ impl DotrainOrderGui { symbol: String, ) { TokenCfg::add_record_to_yaml( - self.dotrain_order.orderbook_yaml().documents, + self.dotrain_order.raindex_yaml().documents, &key, &network_key, &address, @@ -415,7 +415,7 @@ impl DotrainOrderGui { } pub fn remove_record_from_yaml(&self, key: String) { - TokenCfg::remove_record_from_yaml(self.dotrain_order.orderbook_yaml().documents, &key) + TokenCfg::remove_record_from_yaml(self.dotrain_order.raindex_yaml().documents, &key) .unwrap(); } } @@ -799,7 +799,7 @@ mod tests { use crate::gui::{DotrainOrderGui, GuiError}; use alloy::primitives::Address; use httpmock::MockServer; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use serde_json::json; use std::str::FromStr; @@ -859,8 +859,8 @@ rainlangs: some-rainlang: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg diff --git a/crates/js_api/src/gui/state_management.rs b/crates/js_api/src/gui/state_management.rs index 6a57c32100..c90c936de9 100644 --- a/crates/js_api/src/gui/state_management.rs +++ b/crates/js_api/src/gui/state_management.rs @@ -3,7 +3,7 @@ use rain_metadata::types::dotrain::{ gui_state_v1::{DotrainGuiStateV1, ShortenedTokenCfg, ValueCfg}, source_v1::DotrainSourceV1, }; -use rain_orderbook_app_settings::{ +use raindex_app_settings::{ gui::GuiDepositCfg, order::{OrderIOCfg, VaultType}, token::TokenCfg, @@ -261,7 +261,7 @@ impl DotrainOrderGui { for select_token in st { if let Ok(token) = self .dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_token(&select_token.key) { select_tokens.insert(select_token.key, token); @@ -394,12 +394,12 @@ impl DotrainOrderGui { } if dotrain_order_gui.is_select_token_set(key.clone())? { TokenCfg::remove_record_from_yaml( - dotrain_order_gui.dotrain_order.orderbook_yaml().documents, + dotrain_order_gui.dotrain_order.raindex_yaml().documents, &key, )?; } TokenCfg::add_record_to_yaml( - dotrain_order_gui.dotrain_order.orderbook_yaml().documents, + dotrain_order_gui.dotrain_order.raindex_yaml().documents, &key, &token.network.key, &token.address.to_string(), @@ -547,15 +547,13 @@ mod tests { }; use alloy::primitives::{Address, U256}; use js_sys::{eval, Reflect}; - use rain_orderbook_app_settings::{ - network::NetworkCfg, order::VaultType, yaml::YamlParsableHash, - }; - use rain_orderbook_common::dotrain::RainDocument; - use rain_orderbook_common::dotrain_order::DotrainOrder; + use raindex_app_settings::{network::NetworkCfg, order::VaultType, yaml::YamlParsableHash}; + use raindex_common::dotrain::RainDocument; + use raindex_common::dotrain_order::DotrainOrder; use std::str::FromStr; use wasm_bindgen_test::wasm_bindgen_test; - const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_21QXWvCMBRt3NgY7EkGexrsByy0aXWzwh4Ev4qgKH6AL6JttNKY1Bqx4p_wJ2v1pmLxPtxzbs7JvTfJadd4A5wtubfkC0w0FU-AxDCyJhPBgaGlTJEXQCkCyq1H3R4776t3qDZiRTGncieiQN37AvSlDMu6zoQ7Zb7YyHLJKBX1KHTxNmKHxIGSjNToWr_5ATRfGMbHTEJ59ApyP9nh20LPqm61zy_Jabe425akI4hto6xqpqpp2z9A4-pv2Cn8tQbxvLGddTvDRX3tBGMyao6Z4xV7vus4k8iq9Oq7_0_1F5RRV-JLU-zRkIn9inJ5AjfkymPKAQAA"; + const SERIALIZED_STATE: &str = "H4sIAAAAAAAA_21Qy27CMBCMadWqUk-oUk-V-gG1EoeiJki9tEK8BFwgAi4oBEOiGDsE84j4CT4ZAusgIvawM-sZ765d0C7xAjgJ-DTgc0w0FQ-AxDDyJhPBgaFlTJEnQClCykv3ut133lavUK3EgmJO5VbEobr3AehLGVV0nQnPZb5YyYplWGU9jjy8jtk-daA0IzW62qu_AS1-O7tDLqEiega5l-7wWUKPqm51Ti8paNe42ZZkI4hto7xqZqpp219AcU3MfjbjRpgktbbc-oMlHzl_5dANOoTM3Xbc7f9bTlTFzeHvu_oLyqgn8bkpntKIiWRBuTwC_jr8_soBAAA="; fn encode_state(state: &SerializedGuiState) -> String { let bytes = bincode::serialize(state).unwrap(); @@ -698,7 +696,7 @@ mod tests { #[wasm_bindgen_test] async fn test_new_from_state_invalid_dotrain() { let dotrain = r#" - version: 5 + version: 6 networks: test: rpcs: @@ -714,7 +712,7 @@ mod tests { test: network: test address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba - orderbooks: + raindexes: test: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: test @@ -730,7 +728,7 @@ mod tests { outputs: - token: token1 rainlang: test - orderbook: test + raindex: test deployments: select-token-deployment: order: test @@ -851,7 +849,7 @@ mod tests { let restored_token = gui .dotrain_order - .orderbook_yaml() + .raindex_yaml() .get_token("token3") .unwrap(); assert_eq!(restored_token.address, replacement_token.address); diff --git a/crates/js_api/src/gui/validation.rs b/crates/js_api/src/gui/validation.rs index e02c4f4a25..ed3c43a0de 100644 --- a/crates/js_api/src/gui/validation.rs +++ b/crates/js_api/src/gui/validation.rs @@ -1,5 +1,5 @@ use rain_math_float::{Float, FloatError}; -use rain_orderbook_app_settings::gui::{DepositValidationCfg, FieldValueValidationCfg}; +use raindex_app_settings::gui::{DepositValidationCfg, FieldValueValidationCfg}; use thiserror::Error; #[derive(Error, Debug)] @@ -222,7 +222,7 @@ fn validate_boolean(name: &str, value: &str) -> Result<(), GuiValidationError> { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::gui::FieldValueValidationCfg; + use raindex_app_settings::gui::FieldValueValidationCfg; use wasm_bindgen_test::wasm_bindgen_test; #[wasm_bindgen_test] diff --git a/crates/js_api/src/lib.rs b/crates/js_api/src/lib.rs index 2877031e6f..63babaab76 100644 --- a/crates/js_api/src/lib.rs +++ b/crates/js_api/src/lib.rs @@ -6,11 +6,11 @@ pub mod yaml; // re-export other crates to include their wasm bindings as single export point #[cfg(target_family = "wasm")] -pub use rain_orderbook_app_settings; +pub use raindex_app_settings; #[cfg(target_family = "wasm")] -pub use rain_orderbook_common; +pub use raindex_common; #[cfg(target_family = "wasm")] -pub use rain_orderbook_subgraph_client; +pub use raindex_subgraph_client; use wasm_bindgen_utils::prelude::wasm_bindgen; diff --git a/crates/js_api/src/rainlang.rs b/crates/js_api/src/rainlang.rs index 7f0c52fcd3..a85bcc33da 100644 --- a/crates/js_api/src/rainlang.rs +++ b/crates/js_api/src/rainlang.rs @@ -1,7 +1,7 @@ use crate::gui::{DotrainOrderGui, GuiError}; -use crate::yaml::{OrderbookYaml, OrderbookYamlError}; -use rain_orderbook_app_settings::gui::NameAndDescriptionCfg; -use rain_orderbook_common::raindex_client::{RaindexClient, RaindexError as RaindexClientError}; +use crate::yaml::{RaindexYaml, RaindexYamlError}; +use raindex_app_settings::gui::NameAndDescriptionCfg; +use raindex_common::raindex_client::{RaindexClient, RaindexError as RaindexClientError}; use reqwest; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; @@ -83,7 +83,7 @@ pub struct DotrainRainlang { /// This URL points to a YAML file containing shared configuration such as: /// - Network configurations (RPCs, chain IDs) /// - Subgraph endpoints - /// - Orderbook contract addresses + /// - Raindex contract addresses /// - Token definitions /// - Other common settings used across multiple strategies settings_url: Url, @@ -147,7 +147,7 @@ pub enum DotrainRainlangError { #[error(transparent)] GuiError(#[from] GuiError), #[error(transparent)] - OrderbookYamlError(#[from] OrderbookYamlError), + RaindexYamlError(#[from] RaindexYamlError), #[error(transparent)] RaindexClientError(#[from] RaindexClientError), } @@ -180,7 +180,7 @@ impl DotrainRainlangError { format!("Invalid URL format: {}. Please ensure the URL is properly formatted.", err) } DotrainRainlangError::GuiError(err) => err.to_readable_msg(), - DotrainRainlangError::OrderbookYamlError(err) => err.to_readable_msg(), + DotrainRainlangError::RaindexYamlError(err) => err.to_readable_msg(), DotrainRainlangError::RaindexClientError(err) => err.to_readable_msg(), } } @@ -521,29 +521,29 @@ impl DotrainRainlang { Ok(gui) } - /// Creates an OrderbookYaml instance from the registry's shared settings. + /// Creates a RaindexYaml instance from the registry's shared settings. /// - /// This method provides access to the OrderbookYaml SDK, allowing you to query tokens, - /// networks, orderbooks, and other configuration from the shared settings YAML. + /// This method provides access to the RaindexYaml SDK, allowing you to query tokens, + /// networks, raindexes, and other configuration from the shared settings YAML. /// /// ## Examples /// /// ```javascript - /// const yamlResult = registry.getOrderbookYaml(); + /// const yamlResult = registry.getRaindexYaml(); /// if (yamlResult.error) { - /// console.error("Failed to get OrderbookYaml:", yamlResult.error.readableMsg); + /// console.error("Failed to get RaindexYaml:", yamlResult.error.readableMsg); /// return; /// } - /// const orderbookYaml = yamlResult.value; + /// const raindexYaml = yamlResult.value; /// ``` #[wasm_export( - js_name = "getOrderbookYaml", + js_name = "getRaindexYaml", preserve_js_class, - unchecked_return_type = "OrderbookYaml", - return_description = "OrderbookYaml instance from registry settings" + unchecked_return_type = "RaindexYaml", + return_description = "RaindexYaml instance from registry settings" )] - pub fn get_orderbook_yaml(&self) -> Result { - let yaml = OrderbookYaml::new(vec![self.settings.clone()], None)?; + pub fn get_raindex_yaml(&self) -> Result { + let yaml = RaindexYaml::new(vec![self.settings.clone()], None)?; Ok(yaml) } } @@ -732,7 +732,7 @@ impl DotrainRainlang { #[cfg(test)] mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use std::collections::HashMap; const MOCK_REGISTRY_CONTENT: &str = r#"https://example.com/settings.yaml @@ -759,7 +759,7 @@ subgraphs: metaboards: flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-base-0x59401C93/0.1/gn -orderbooks: +raindexes: flare: address: 0xCEe8Cd002F151A536394E564b84076c41bBBcD4d network: flare @@ -839,13 +839,13 @@ scenarios: runs: 1 orders: flare: - orderbook: flare + raindex: flare inputs: - token: token1 outputs: - token: token1 base: - orderbook: base + raindex: base inputs: - token: token2 outputs: @@ -1559,7 +1559,7 @@ tokens: decimals: 6 label: USD Coin symbol: USDC -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -1594,7 +1594,7 @@ scenarios: runs: 1 orders: mainnet: - orderbook: mainnet + raindex: mainnet inputs: - token: weth outputs: @@ -1611,7 +1611,7 @@ _ _: 0 0; "#; #[tokio::test] - async fn test_get_orderbook_yaml_returns_valid_instance() { + async fn test_get_raindex_yaml_returns_valid_instance() { let server = MockServer::start_async().await; let test_registry_content = format!( @@ -1639,8 +1639,8 @@ _ _: 0 0; .await .unwrap(); - let orderbook_yaml = registry.get_orderbook_yaml(); - assert!(orderbook_yaml.is_ok()); + let raindex_yaml = registry.get_raindex_yaml(); + assert!(raindex_yaml.is_ok()); } #[tokio::test] diff --git a/crates/js_api/src/yaml/mod.rs b/crates/js_api/src/yaml/mod.rs index 0533a6f60a..596e2ea335 100644 --- a/crates/js_api/src/yaml/mod.rs +++ b/crates/js_api/src/yaml/mod.rs @@ -1,59 +1,59 @@ use std::str::FromStr; use alloy::{hex::FromHexError, primitives::Address}; -use rain_orderbook_app_settings::{ - orderbook::OrderbookCfg, +use raindex_app_settings::{ + raindex::RaindexCfg, remote_tokens::{ParseRemoteTokensError, RemoteTokensCfg}, spec_version::CURRENT_SPEC_VERSION, yaml::{ - orderbook::{OrderbookYaml as OrderbookYamlCfg, OrderbookYamlValidation}, + raindex::{RaindexYaml as RaindexYamlCfg, RaindexYamlValidation}, YamlError, YamlParsable, }, }; -use rain_orderbook_common::erc20::ExtendedTokenInfo; +use raindex_common::erc20::ExtendedTokenInfo; use serde::{Deserialize, Serialize}; use thiserror::Error; use wasm_bindgen_utils::prelude::*; #[derive(Serialize, Deserialize, Debug, Clone)] #[wasm_bindgen] -pub struct OrderbookYaml { - yaml: OrderbookYamlCfg, +pub struct RaindexYaml { + yaml: RaindexYamlCfg, } #[wasm_export] -impl OrderbookYaml { - /// Creates a new OrderbookYaml instance from YAML configuration sources. +impl RaindexYaml { + /// Creates a new RaindexYaml instance from YAML configuration sources. /// - /// This constructor parses one or more YAML configuration strings to create an OrderbookYaml - /// instance that provides access to orderbook configurations, network settings, tokens, and + /// This constructor parses one or more YAML configuration strings to create an RaindexYaml + /// instance that provides access to raindex configurations, network settings, tokens, and /// other deployment metadata. The YAML sources are merged and validated according to the - /// [orderbook specification](https://github.com/rainlanguage/specs/blob/main/ob-yaml.md). + /// [raindex specification](https://github.com/rainlanguage/specs/blob/main/raindex-yaml.md). /// /// ## Examples /// /// ```javascript /// // Basic usage with single YAML source /// const yamlConfig = ` - /// version: "5" + /// version: "6" /// networks: /// mainnet: /// rpc: https://mainnet.infura.io /// chain-id: 1 - /// orderbooks: - /// my-orderbook: + /// raindexes: + /// my-raindex: /// address: 0x1234567890abcdef1234567890abcdef12345678 /// network: mainnet /// ... /// `; /// - /// const result = OrderbookYaml.new([yamlConfig], false); + /// const result = RaindexYaml.new([yamlConfig], false); /// if (result.error) { /// console.error("Configuration error:", result.error.readableMsg); /// return; /// } - /// const orderbookYaml = result.value; - /// // Do something with the orderbookYaml + /// const raindexYaml = result.value; + /// // Do something with the raindexYaml /// ``` #[wasm_export( js_name = "new", @@ -69,12 +69,12 @@ impl OrderbookYaml { param_description = "Optional boolean to enable strict validation (defaults to false)" )] validate: Option, - ) -> Result { - let yaml = OrderbookYamlCfg::new( + ) -> Result { + let yaml = RaindexYamlCfg::new( sources, match validate { - Some(true) => OrderbookYamlValidation::full(), - _ => OrderbookYamlValidation::default(), + Some(true) => RaindexYamlValidation::full(), + _ => RaindexYamlValidation::default(), }, )?; Ok(Self { yaml }) @@ -84,41 +84,40 @@ impl OrderbookYaml { js_name = "getCurrentSpecVersion", return_description = "Current spec version" )] - pub fn get_current_spec_version() -> Result { + pub fn get_current_spec_version() -> Result { Ok(CURRENT_SPEC_VERSION.to_string()) } - /// Retrieves orderbook configuration by its contract address from a parsed YAML configuration. + /// Retrieves raindex configuration by its contract address from a parsed YAML configuration. /// - /// This function looks up a specific orderbook configuration within a YAML configuration file - /// using the orderbook's blockchain address. It's essential for accessing orderbook metadata + /// This function looks up a specific raindex configuration within a YAML configuration file + /// using the raindex's blockchain address. It's essential for accessing raindex metadata /// including network configuration, subgraph endpoints, and other deployment details. /// /// ## Examples /// /// ```javascript /// // Basic usage - /// const result = orderbookYaml.getOrderbookByAddress("0x1234567890abcdef1234567890abcdef12345678"); + /// const result = raindexYaml.getRaindexByAddress("0x1234567890abcdef1234567890abcdef12345678"); /// if (result.error) { /// console.error("Error:", result.error.readableMsg); /// return; /// } - /// const orderbook = result.value; - /// // Do something with the orderbook + /// const raindex = result.value; + /// // Do something with the raindex /// ``` #[wasm_export( - js_name = "getOrderbookByAddress", - unchecked_return_type = "OrderbookCfg", - return_description = "Complete orderbook configuration" + js_name = "getRaindexByAddress", + unchecked_return_type = "RaindexCfg", + return_description = "Complete raindex configuration" )] - pub fn get_orderbook_by_address( + pub fn get_raindex_by_address( &self, - #[wasm_export(param_description = "The hexadecimal address of the orderbook contract")] - orderbook_address: &str, - ) -> Result { - let address = - Address::from_str(orderbook_address).map_err(OrderbookYamlError::FromHexError)?; - Ok(self.yaml.get_orderbook_by_address(address)?) + #[wasm_export(param_description = "The hexadecimal address of the raindex contract")] + raindex_address: &str, + ) -> Result { + let address = Address::from_str(raindex_address).map_err(RaindexYamlError::FromHexError)?; + Ok(self.yaml.get_raindex_by_address(address)?) } /// Retrieves all tokens from the YAML configuration, including remote tokens. @@ -130,7 +129,7 @@ impl OrderbookYaml { /// ## Examples /// /// ```javascript - /// const result = await orderbookYaml.getTokens(); + /// const result = await raindexYaml.getTokens(); /// if (result.error) { /// console.error("Error:", result.error.readableMsg); /// return; @@ -146,7 +145,7 @@ impl OrderbookYaml { unchecked_return_type = "ExtendedTokenInfo[]", return_description = "Array of token information" )] - pub async fn get_tokens(&mut self) -> Result, OrderbookYamlError> { + pub async fn get_tokens(&mut self) -> Result, RaindexYamlError> { if let Some(remote_tokens_cfg) = self.yaml.get_remote_tokens()? { let networks = self.yaml.get_networks()?; let remote_tokens = RemoteTokensCfg::fetch_tokens(&networks, remote_tokens_cfg).await?; @@ -165,8 +164,8 @@ impl OrderbookYaml { } #[derive(Error, Debug)] -pub enum OrderbookYamlError { - #[error("Orderbook yaml error: {0}")] +pub enum RaindexYamlError { + #[error("Raindex yaml error: {0}")] YamlError(#[from] YamlError), #[error("Invalid address: {0}")] FromHexError(#[from] FromHexError), @@ -175,33 +174,33 @@ pub enum OrderbookYamlError { #[error(transparent)] ParseRemoteTokensError(#[from] ParseRemoteTokensError), #[error(transparent)] - ERC20Error(#[from] rain_orderbook_common::erc20::Error), + ERC20Error(#[from] raindex_common::erc20::Error), } -impl OrderbookYamlError { +impl RaindexYamlError { pub fn to_readable_msg(&self) -> String { match self { - OrderbookYamlError::YamlError(err) => + RaindexYamlError::YamlError(err) => format!("There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: \"{}\"", err), - OrderbookYamlError::FromHexError(err) => + RaindexYamlError::FromHexError(err) => format!("The provided address is invalid. Please ensure the address is in the correct hexadecimal format. Error: \"{}\"", err), - OrderbookYamlError::MissingField(field) => + RaindexYamlError::MissingField(field) => format!("A required field is missing from the token configuration: \"{}\". Please ensure all tokens have decimals, label, and symbol defined.", field), - OrderbookYamlError::ParseRemoteTokensError(err) => + RaindexYamlError::ParseRemoteTokensError(err) => format!("Failed to fetch or parse remote tokens. Please check the using-tokens-from URLs are accessible and return valid token data. Error: \"{}\"", err), - OrderbookYamlError::ERC20Error(err) => + RaindexYamlError::ERC20Error(err) => format!("Failed to fetch token information from the blockchain. Please check your network connection and RPC settings. Error: \"{}\"", err), } } } -impl From for JsValue { - fn from(value: OrderbookYamlError) -> Self { +impl From for JsValue { + fn from(value: RaindexYamlError) -> Self { JsError::new(&value.to_string()).into() } } -impl From for WasmEncodedError { - fn from(value: OrderbookYamlError) -> Self { +impl From for WasmEncodedError { + fn from(value: RaindexYamlError) -> Self { WasmEncodedError { msg: value.to_string(), readable_msg: value.to_readable_msg(), @@ -212,7 +211,7 @@ impl From for WasmEncodedError { #[cfg(test)] pub(crate) mod tests { use super::*; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use wasm_bindgen_test::wasm_bindgen_test; pub fn get_yaml() -> String { @@ -233,13 +232,13 @@ pub(crate) mod tests { metaboards: board1: https://meta.example.com/board1 board2: https://meta.example.com/board2 - orderbooks: - orderbook1: + raindexes: + raindex1: address: 0x0000000000000000000000000000000000000002 network: mainnet subgraph: mainnet local-db-remote: remote - label: Primary Orderbook + label: Primary Raindex deployment-block: 12345 tokens: token1: @@ -263,52 +262,52 @@ pub(crate) mod tests { #[wasm_bindgen_test] fn test_get_current_spec_version() { - let version = OrderbookYaml::get_current_spec_version().unwrap(); + let version = RaindexYaml::get_current_spec_version().unwrap(); assert_eq!(version, SpecVersion::current().to_string()); } #[wasm_bindgen_test] - fn test_orderbook_yaml() { - let orderbook_yaml = OrderbookYaml::new(vec![get_yaml()], None).unwrap(); - let orderbook = orderbook_yaml - .get_orderbook_by_address("0x0000000000000000000000000000000000000002") + fn test_raindex_yaml() { + let raindex_yaml = RaindexYaml::new(vec![get_yaml()], None).unwrap(); + let raindex = raindex_yaml + .get_raindex_by_address("0x0000000000000000000000000000000000000002") .unwrap(); assert_eq!( - orderbook.address, + raindex.address, Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); - assert_eq!(orderbook.key, "orderbook1"); - assert_eq!(orderbook.network.key, "mainnet"); - assert_eq!(orderbook.subgraph.key, "mainnet"); - assert_eq!(orderbook.label, Some("Primary Orderbook".to_string())); + assert_eq!(raindex.key, "raindex1"); + assert_eq!(raindex.network.key, "mainnet"); + assert_eq!(raindex.subgraph.key, "mainnet"); + assert_eq!(raindex.label, Some("Primary Raindex".to_string())); } #[wasm_bindgen_test] - fn test_orderbook_yaml_error() { - let orderbook_yaml = OrderbookYaml::new(vec![get_yaml()], None).unwrap(); - let orderbook = orderbook_yaml.get_orderbook_by_address("invalid-address"); + fn test_raindex_yaml_error() { + let raindex_yaml = RaindexYaml::new(vec![get_yaml()], None).unwrap(); + let raindex = raindex_yaml.get_raindex_by_address("invalid-address"); - assert!(orderbook.is_err()); + assert!(raindex.is_err()); assert_eq!( - orderbook.as_ref().err().unwrap().to_string(), + raindex.as_ref().err().unwrap().to_string(), "Invalid address: odd number of digits" ); assert_eq!( - orderbook.as_ref().err().unwrap().to_readable_msg(), + raindex.as_ref().err().unwrap().to_readable_msg(), "The provided address is invalid. Please ensure the address is in the correct hexadecimal format. Error: \"odd number of digits\"" ); - let orderbook = - orderbook_yaml.get_orderbook_by_address("0x0000000000000000000000000000000000000000"); - assert!(orderbook.is_err()); + let raindex = + raindex_yaml.get_raindex_by_address("0x0000000000000000000000000000000000000000"); + assert!(raindex.is_err()); assert_eq!( - orderbook.as_ref().err().unwrap().to_string(), - "Orderbook yaml error: orderbook with address: 0x0000000000000000000000000000000000000000 not found" + raindex.as_ref().err().unwrap().to_string(), + "Raindex yaml error: raindex with address: 0x0000000000000000000000000000000000000000 not found" ); assert_eq!( - orderbook.as_ref().err().unwrap().to_readable_msg(), - "There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: \"orderbook with address: 0x0000000000000000000000000000000000000000 not found\"" + raindex.as_ref().err().unwrap().to_readable_msg(), + "There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: \"raindex with address: 0x0000000000000000000000000000000000000000 not found\"" ); } @@ -323,12 +322,12 @@ pub(crate) mod tests { label: Ethereum Mainnet network-id: 1 currency: ETH - orderbooks: - orderbook1: + raindexes: + raindex1: address: 0x0000000000000000000000000000000000000002 network: nonexistent-network subgraph: nonexistent-subgraph - label: Primary Orderbook + label: Primary Raindex deployment-block: 12345 "#, spec_version = SpecVersion::current() @@ -336,12 +335,12 @@ pub(crate) mod tests { } #[wasm_bindgen_test] - fn test_orderbook_yaml_invalid_with_validation_enabled() { - let result = OrderbookYaml::new(vec![get_invalid_yaml()], Some(true)); + fn test_raindex_yaml_invalid_with_validation_enabled() { + let result = RaindexYaml::new(vec![get_invalid_yaml()], Some(true)); match result { Ok(_) => panic!("Expected validation error with invalid YAML"), Err(err) => { - assert!(err.to_string().contains("Orderbook yaml error")); + assert!(err.to_string().contains("Raindex yaml error")); assert!(err .to_readable_msg() .contains("There was an error processing the YAML configuration")); @@ -351,8 +350,8 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_local_only() { - let mut orderbook_yaml = OrderbookYaml::new(vec![get_yaml()], None).unwrap(); - let tokens = orderbook_yaml.get_tokens().await.unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![get_yaml()], None).unwrap(); + let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].key, "token1"); @@ -405,9 +404,8 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_multiple_networks() { - let mut orderbook_yaml = - OrderbookYaml::new(vec![get_yaml_multiple_networks()], None).unwrap(); - let tokens = orderbook_yaml.get_tokens().await.unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![get_yaml_multiple_networks()], None).unwrap(); + let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); @@ -444,13 +442,13 @@ pub(crate) mod tests { #[wasm_bindgen_test] async fn test_get_tokens_missing_fields_tries_rpc() { - let mut orderbook_yaml = OrderbookYaml::new(vec![get_yaml_missing_fields()], None).unwrap(); - let result = orderbook_yaml.get_tokens().await; + let mut raindex_yaml = RaindexYaml::new(vec![get_yaml_missing_fields()], None).unwrap(); + let result = raindex_yaml.get_tokens().await; assert!(result.is_err()); let err = result.unwrap_err(); assert!( - matches!(err, OrderbookYamlError::ERC20Error(_)), + matches!(err, RaindexYamlError::ERC20Error(_)), "Expected ERC20Error when trying to fetch missing token info from RPC, got: {:?}", err ); @@ -464,7 +462,7 @@ pub(crate) mod tests { mod non_wasm_tests { use super::*; use httpmock::MockServer; - use rain_orderbook_app_settings::spec_version::SpecVersion; + use raindex_app_settings::spec_version::SpecVersion; use serde_json::json; #[tokio::test] @@ -510,8 +508,8 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); - let tokens = orderbook_yaml.get_tokens().await.unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); + let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 1); assert_eq!(tokens[0].symbol, "USDC"); @@ -570,8 +568,8 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); - let tokens = orderbook_yaml.get_tokens().await.unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); + let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); assert!(tokens.iter().any(|t| t.symbol == "WETH")); @@ -620,8 +618,8 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); - let tokens = orderbook_yaml.get_tokens().await.unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); + let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); assert!(tokens.iter().any(|t| t.chain_id == 1)); @@ -652,8 +650,8 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); - let result = orderbook_yaml.get_tokens().await; + let mut raindex_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); + let result = raindex_yaml.get_tokens().await; assert!(result.is_err()); } @@ -712,8 +710,8 @@ mod non_wasm_tests { url = server.base_url() ); - let mut orderbook_yaml = OrderbookYaml::new(vec![yaml], None).unwrap(); - let tokens = orderbook_yaml.get_tokens().await.unwrap(); + let mut raindex_yaml = RaindexYaml::new(vec![yaml], None).unwrap(); + let tokens = raindex_yaml.get_tokens().await.unwrap(); assert_eq!(tokens.len(), 2); assert!(tokens.iter().any(|t| t.symbol == "USDC")); diff --git a/crates/math/ARCHITECTURE.md b/crates/math/ARCHITECTURE.md index 551e9047a2..f00a152d6a 100644 --- a/crates/math/ARCHITECTURE.md +++ b/crates/math/ARCHITECTURE.md @@ -1,6 +1,6 @@ -# rain_orderbook_math — Architecture & Design Notes +# raindex_math — Architecture & Design Notes -This crate provides small, focused, and overflow‑safe helpers for 256‑bit integer math used across the Rain Orderbook codebase. It standardizes two things: +This crate provides small, focused, and overflow‑safe helpers for 256‑bit integer math used across the Rain Raindex codebase. It standardizes two things: - Fixed‑point arithmetic in 18‑decimals (a.k.a. “wad” math). - Safe scaling between token native decimals and 18‑decimals. @@ -161,7 +161,7 @@ Assume `amount` is a token balance in its native decimals. - Normalize to 18 decimals: ```rust use alloy::primitives::U256; - use rain_orderbook_math::BigUintMath; + use raindex_math::BigUintMath; let usdc_amount = U256::from(1_500_000u64); // 1.5 USDC with 6 decimals let wad = usdc_amount.scale_18(6)?; // 1.5 * 1e18 as U256 @@ -190,8 +190,8 @@ Assume `amount` is a token balance in its native decimals. ## File Map - `src/lib.rs` — All implementations and tests. -- `Cargo.toml` — Declares crate as `rain_orderbook_math`; depends on `alloy`, `thiserror` (and `once_cell` via workspace, unused here). +- `Cargo.toml` — Declares crate as `raindex_math`; depends on `alloy`, `thiserror` (and `once_cell` via workspace, unused here). ## Summary -`rain_orderbook_math` supplies the minimal, safe building blocks needed for consistent 18‑dec fixed‑point math on `U256`, with careful overflow handling and 512‑bit intermediates for the common mul‑then‑div pattern. Other Rain Orderbook crates rely on these helpers to normalize magnitudes and compute rates without duplicating math or risking undefined overflow behavior. +`raindex_math` supplies the minimal, safe building blocks needed for consistent 18‑dec fixed‑point math on `U256`, with careful overflow handling and 512‑bit intermediates for the common mul‑then‑div pattern. Other Rain Raindex crates rely on these helpers to normalize magnitudes and compute rates without duplicating math or risking undefined overflow behavior. diff --git a/crates/math/Cargo.toml b/crates/math/Cargo.toml index 3308b9c814..dcf890d25b 100644 --- a/crates/math/Cargo.toml +++ b/crates/math/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_math" -description = "Math toolings for Rain Orderbooks crates" +name = "raindex_math" +description = "Math toolings for Raindex crates" version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/quote/ARCHITECTURE.md b/crates/quote/ARCHITECTURE.md index 93d2068615..69c53f5983 100644 --- a/crates/quote/ARCHITECTURE.md +++ b/crates/quote/ARCHITECTURE.md @@ -1,9 +1,9 @@ -# rain_orderbook_quote — Architecture & Design +# raindex_quote — Architecture & Design -This crate provides all functionality to quote Rain Orderbook orders from Rust, expose the API to WASM/TypeScript, and ship a small CLI for ad‑hoc quoting and debugging. It stitches together three external systems: +This crate provides all functionality to quote Rain Raindex orders from Rust, expose the API to WASM/TypeScript, and ship a small CLI for ad‑hoc quoting and debugging. It stitches together three external systems: -- On‑chain Orderbook V5 contracts (`IOrderBookV5`) via JSON‑RPC -- The Orderbook subgraph for fetching order details by id +- On‑chain Raindex V6 contracts (`IRaindexV6`) via JSON‑RPC +- The Raindex subgraph for fetching order details by id - Rain error decoding to turn revert data into human readable errors It also includes a debugger that can fork an EVM and trace a `quote2` call for step‑by‑step analysis of interpreter execution. @@ -11,7 +11,7 @@ It also includes a debugger that can fork an EVM and trace a `quote2` call for s ## Targets and Build Modes -- Library: `rain_orderbook_quote` (default). Always built. +- Library: `raindex_quote` (default). Always built. - Binary: uses `src/main.rs` which calls the crate CLI entry `cli::main()`. - WASM: many types derive `Tsify` and use `wasm-bindgen-utils` helpers. The `cli` and `quote_debug` modules are disabled for wasm via `#[cfg(not(target_family = "wasm"))]`. @@ -38,10 +38,10 @@ Key gating: - Used by both native and wasm; serializes to camelCase. - `QuoteTarget` - - A fully specified quote request with the exact `QuoteV2` (includes the `OrderV4` bytes, input/output indices, and optional signed context) and the `orderbook` address. + - A fully specified quote request with the exact `QuoteV2` (includes the `OrderV4` bytes, input/output indices, and optional signed context) and the `raindex` address. - Helpers: - `get_order_hash()`: `keccak256(order.abi_encode())` - - `get_id()`: subgraph order id = `keccak256(orderbook || order_hash)` + - `get_id()`: subgraph order id = `keccak256(raindex || order_hash)` - `validate()`: verifies the input/output indices are in bounds for the given order. - `do_quote(rpcs, block_number, gas, multicall_address)`: calls `rpc::batch_quote` with just this target and returns its `QuoteResult`. @@ -49,8 +49,8 @@ Key gating: - Adds `do_quote(...) -> Result, Error>` and is the standard input to RPC batch quoting. - `QuoteSpec` - - A quote specification that references an order by `order_hash` and `orderbook` without embedding the order bytes. Includes `input_io_index`, `output_io_index`, and optional `signed_context`. - - `get_id()`: same subgraph id as above using `orderbook || order_hash`. + - A quote specification that references an order by `order_hash` and `raindex` without embedding the order bytes. Includes `input_io_index`, `output_io_index`, and optional `signed_context`. + - `get_id()`: same subgraph id as above using `raindex || order_hash`. - `get_quote_target_from_subgraph(subgraph_url)`: queries the subgraph to fetch `orderBytes` and builds a `QuoteTarget`. - `do_quote(subgraph_url, rpcs, block_number, gas, multicall_address)`: fetches order bytes first, then quotes once. @@ -86,10 +86,10 @@ Key gating: Purpose: execute `quote2` for many `QuoteTarget`s in one multicall. Flow: -1. Parse RPC URLs into `Url` and build a `ReadProvider` via `mk_read_provider(&rpcs)` from `rain_orderbook_bindings`. +1. Parse RPC URLs into `Url` and build a `ReadProvider` via `mk_read_provider(&rpcs)` from `raindex_bindings`. 2. Create a dynamic `multicall` builder; override its address if `multicall_address` is provided. 3. Optionally pin to `block_number` via `BlockId::Number(block)`. -4. For each target, push `IOrderBookV5::quote2(QuoteV2)` into the multicall. +4. For each target, push `IRaindexV6::quote2(QuoteV2)` into the multicall. 5. Await `aggregate3()`: - If the entire multicall returns `Err(MulticallError::CallFailed(bytes))`, decode the bytes via the Rain error selector registry and return a vector with the same per‑target error for each element (so callers still receive a `Vec` of the right length). - If other transport‑level errors occur, bubble them up as `Error::MulticallError` and do not return per‑target results. @@ -105,8 +105,8 @@ Notes: ## Subgraph Integration -- `OrderbookSubgraphClient` is used to fetch `orderBytes` either single (`order_detail`) or batch (`batch_order_detail`). -- `QuoteSpec` and `BatchQuoteSpec` use the helper `make_order_id(orderbook, order_hash)` to query the subgraph. +- `RaindexSubgraphClient` is used to fetch `orderBytes` either single (`order_detail`) or batch (`batch_order_detail`). +- `QuoteSpec` and `BatchQuoteSpec` use the helper `make_order_id(raindex, order_hash)` to query the subgraph. - ABI decoding of `orderBytes` constructs `OrderV4`, which is then embedded into `QuoteV2`. @@ -130,7 +130,7 @@ Result: a flat `Vec` that UIs can render per pair. ## CLI: `cli` module and `src/main.rs` Entrypoint: -- `src/main.rs` calls `rain_orderbook_quote::cli::main()` which initializes tracing, parses args, and delegates to `Quoter::run()`. +- `src/main.rs` calls `raindex_quote::cli::main()` which initializes tracing, parses args, and delegates to `Quoter::run()`. Arguments (selected): - `--rpc ` (required): JSON‑RPC endpoint. @@ -142,9 +142,9 @@ Arguments (selected): - `--pretty`: pretty‑print JSON. Input formats (mutually exclusive via `Input` group): -- `-i|--input `: Packed bytes representing one or more `QuoteSpec`s. Each spec is exactly 54 bytes: `[20 bytes orderbook][1 byte inputIO][1 byte outputIO][32 bytes order_hash]`. Length must be a non‑zero multiple of 54. -- `--target `: One or more fully specified targets (can repeat `--target`). -- `--spec `: One or more specs (requires `--subgraph`). +- `-i|--input `: Packed bytes representing one or more `QuoteSpec`s. Each spec is exactly 54 bytes: `[20 bytes raindex][1 byte inputIO][1 byte outputIO][32 bytes order_hash]`. Length must be a non‑zero multiple of 54. +- `--target `: One or more fully specified targets (can repeat `--target`). +- `--spec `: One or more specs (requires `--subgraph`). Output format: - Always JSON array (`QuoterResult`). For each element: @@ -190,8 +190,8 @@ Purpose: Help users debug a `quote2` call by forking a chain, executing the call ## External Dependencies of Note - `alloy` primitives and `sol_types`: ABI encode/decode, EVM types, and contract call modeling. -- `rain_orderbook_bindings`: contract bindings (`IOrderBookV5`, provider helpers like `mk_read_provider`). -- `rain_orderbook_subgraph_client`: GraphQL client and types; provides `order_detail` and `batch_order_detail`. +- `raindex_bindings`: contract bindings (`IRaindexV6`, provider helpers like `mk_read_provider`). +- `raindex_subgraph_client`: GraphQL client and types; provides `order_detail` and `batch_order_detail`. - `rain-error-decoding`: decodes revert selectors (known/unknown) into structured errors. - `alloy-ethers-typecast::ReadableClient`: convenience for fetching block number across multiple HTTP RPCs. - `rain_math_float::Float`: canonical numeric type used in quotes; serializes to hex strings and provides safe equality/formatting. @@ -209,7 +209,7 @@ The crate has extensive unit tests across modules, including: Tests use: - `httpmock` for simulating JSON‑RPC and subgraph HTTP responses. -- `rain_orderbook_test_fixtures::LocalEvm` to spawn a local chain with tokens and an orderbook. +- `raindex_test_fixtures::LocalEvm` to spawn a local chain with tokens and a raindex. ## Invariants and Edge Cases @@ -231,8 +231,8 @@ Tests use: - Or build `QuoteSpec`s and call `BatchQuoteSpec::do_quote(subgraph_url, rpcs, block, None, None)`. - CLI: - - Direct targets: `cargo run -p rain_orderbook_quote -- --rpc --target ` - - Specs via subgraph: `--spec --sg ` + - Direct targets: `cargo run -p raindex_quote -- --rpc --target ` + - Specs via subgraph: `--spec --sg ` - Packed bytes: `-i --sg ` where `` is repeated 54‑byte chunks. - Debugging (native only): diff --git a/crates/quote/Cargo.toml b/crates/quote/Cargo.toml index 0ebe4fa4dd..cf52b8d65f 100644 --- a/crates/quote/Cargo.toml +++ b/crates/quote/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_quote" -description = "Quote Rain Orderbook Orders" +name = "raindex_quote" +description = "Quote Raindex Orders" version.workspace = true edition.workspace = true license.workspace = true @@ -14,8 +14,8 @@ crate-type = ["rlib"] [dependencies] rain-math-float.workspace = true rain-metadata = { workspace = true } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_subgraph_client = { workspace = true } +raindex_bindings = { workspace = true } +raindex_subgraph_client = { workspace = true } futures = { workspace = true } rain-error-decoding = { workspace = true } alloy = { workspace = true, features = ["sol-types"] } @@ -50,9 +50,9 @@ getrandom = { workspace = true } httpmock = "0.7.0" [dev-dependencies] -rain_orderbook_test_fixtures = { workspace = true } -rain_orderbook_common = { workspace = true } +raindex_test_fixtures = { workspace = true } +raindex_common = { workspace = true } wasm-bindgen-test = "0.3" -rain_orderbook_app_settings = { workspace = true } +raindex_app_settings = { workspace = true } tempfile.workspace = true async-trait = "0.1" diff --git a/crates/quote/src/cli/input.rs b/crates/quote/src/cli/input.rs index 6fad13752c..e116bc1f22 100644 --- a/crates/quote/src/cli/input.rs +++ b/crates/quote/src/cli/input.rs @@ -5,7 +5,7 @@ use alloy::primitives::{ }; use alloy::sol_types::SolType; use clap::Args; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, QuoteV2}; +use raindex_bindings::IRaindexV6::{OrderV4, QuoteV2}; use std::str::FromStr; /// Group of valid input formats @@ -30,7 +30,7 @@ pub struct Input { long, num_args = 4, value_names = [ - "ORDERBOOK_ADDRESS", + "RAINDEX_ADDRESS", "INPUT_IO_INDEX", "OUTPUT_IO_INDEX", "ORDER_BYTES" @@ -43,7 +43,7 @@ pub struct Input { long, num_args = 4, value_names = [ - "ORDERBOOK_ADDRESS", + "RAINDEX_ADDRESS", "INPUT_IO_INDEX", "OUTPUT_IO_INDEX", "ORDER_HASH" @@ -100,10 +100,10 @@ pub fn parse_input(value: &str) -> anyhow::Result { while let Some(bytes_piece) = bytes.get(start_index..end_index) { batch_quote_sepcs.0.push(QuoteSpec { signed_context: vec![], - orderbook: bytes_piece + raindex: bytes_piece .get(..20) .map(Address::from_slice) - .ok_or(anyhow::anyhow!("missing orderbook address"))?, + .ok_or(anyhow::anyhow!("missing raindex address"))?, input_io_index: bytes_piece .get(20..21) .map(|v| v[0]) @@ -130,7 +130,7 @@ impl TryFrom<&Vec> for BatchQuoteTarget { let mut batch_quote_target = BatchQuoteTarget::default(); let mut iter = value.iter(); - while let Some(orderbook_str) = iter.next() { + while let Some(raindex_str) = iter.next() { let input_io_index_str = match iter.next() { Some(s) => s, None => return Err(anyhow::anyhow!("missing input IO index")), @@ -145,7 +145,7 @@ impl TryFrom<&Vec> for BatchQuoteTarget { }; batch_quote_target.0.push(QuoteTarget { - orderbook: Address::from_hex(orderbook_str)?, + raindex: Address::from_hex(raindex_str)?, quote_config: QuoteV2 { signedContext: vec![], inputIOIndex: U256::from_str(input_io_index_str)?, @@ -168,7 +168,7 @@ impl TryFrom<&Vec> for BatchQuoteSpec { fn try_from(value: &Vec) -> Result { let mut batch_quote_specs = BatchQuoteSpec::default(); let mut iter = value.iter(); - while let Some(orderbook_str) = iter.next() { + while let Some(raindex_str) = iter.next() { let input_io_index_str = match iter.next() { Some(s) => s, None => return Err(anyhow::anyhow!("missing input IO index")), @@ -184,7 +184,7 @@ impl TryFrom<&Vec> for BatchQuoteSpec { batch_quote_specs.0.push(QuoteSpec { signed_context: vec![], - orderbook: Address::from_hex(orderbook_str)?, + raindex: Address::from_hex(raindex_str)?, order_hash: U256::from_str(order_hash_str)?, input_io_index: input_io_index_str.parse()?, output_io_index: output_io_index_str.parse()?, @@ -202,26 +202,26 @@ mod tests { use super::*; use alloy::primitives::hex::encode_prefixed; use alloy::sol_types::SolValue; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4}; + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4}; #[test] fn test_parse_input() { - let orderbook_address1 = Address::random(); + let raindex_address1 = Address::random(); let input_io_index1 = 10u8; let output_io_index1 = 8u8; let order_hash1 = [5u8; 32]; - let orderbook_address2 = Address::random(); + let raindex_address2 = Address::random(); let input_io_index2 = 1u8; let output_io_index2 = 2u8; let order_hash2 = [2u8; 32]; let mut bytes = vec![]; - bytes.extend(orderbook_address1.0 .0); + bytes.extend(raindex_address1.0 .0); bytes.push(input_io_index1); bytes.push(output_io_index1); bytes.extend(order_hash1); - bytes.extend(orderbook_address2.0 .0); + bytes.extend(raindex_address2.0 .0); bytes.push(input_io_index2); bytes.push(output_io_index2); bytes.extend(order_hash2); @@ -235,14 +235,14 @@ mod tests { input_io_index: input_io_index1, output_io_index: output_io_index1, signed_context: vec![], - orderbook: orderbook_address1, + raindex: raindex_address1, }, QuoteSpec { order_hash: U256::from_be_bytes(order_hash2), input_io_index: input_io_index2, output_io_index: output_io_index2, signed_context: vec![], - orderbook: orderbook_address2, + raindex: raindex_address2, }, ]); assert_eq!(result, expected); @@ -261,8 +261,8 @@ mod tests { // valid targets let input_index = 8u8; let output_index = 9u8; - let orderbook1 = Address::random(); - let orderbook2 = Address::random(); + let raindex1 = Address::random(); + let raindex2 = Address::random(); let order1 = OrderV4 { evaluable: EvaluableV4 { bytecode: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 0].into(), @@ -281,11 +281,11 @@ mod tests { let order_bytes2 = order2.abi_encode(); let targets_str = vec![ - encode_prefixed(orderbook1.0), + encode_prefixed(raindex1.0), input_index.to_string(), output_index.to_string(), encode_prefixed(order_bytes1.clone()), - encode_prefixed(orderbook2.0), + encode_prefixed(raindex2.0), input_index.to_string(), output_index.to_string(), encode_prefixed(order_bytes2), @@ -294,7 +294,7 @@ mod tests { let result: BatchQuoteTarget = (&targets_str).try_into().unwrap(); let expected = BatchQuoteTarget(vec![ QuoteTarget { - orderbook: orderbook1, + raindex: raindex1, quote_config: QuoteV2 { inputIOIndex: U256::from(input_index), outputIOIndex: U256::from(output_index), @@ -303,7 +303,7 @@ mod tests { }, }, QuoteTarget { - orderbook: orderbook2, + raindex: raindex2, quote_config: QuoteV2 { inputIOIndex: U256::from(input_index), outputIOIndex: U256::from(output_index), @@ -316,11 +316,11 @@ mod tests { // invalid targets let targets_str = vec![ - encode_prefixed(orderbook1.0), + encode_prefixed(raindex1.0), input_index.to_string(), output_index.to_string(), encode_prefixed(order_bytes1), - encode_prefixed(orderbook2.0), + encode_prefixed(raindex2.0), input_index.to_string(), output_index.to_string(), ]; @@ -329,7 +329,7 @@ mod tests { .to_string(); assert_eq!(result, "missing order bytes"); - let targets_str = vec![encode_prefixed(orderbook1.0), input_index.to_string()]; + let targets_str = vec![encode_prefixed(raindex1.0), input_index.to_string()]; let result = std::convert::TryInto::::try_into(&targets_str) .expect_err("expected error") .to_string(); @@ -341,17 +341,17 @@ mod tests { // valid targets let input_index = 8u8; let output_index = 9u8; - let orderbook1 = Address::random(); - let orderbook2 = Address::random(); + let raindex1 = Address::random(); + let raindex2 = Address::random(); let order_hash1 = [1u8; 32]; let order_hash2 = [2u8; 32]; let specs_str = vec![ - encode_prefixed(orderbook1.0), + encode_prefixed(raindex1.0), input_index.to_string(), output_index.to_string(), encode_prefixed(order_hash1), - encode_prefixed(orderbook2.0), + encode_prefixed(raindex2.0), input_index.to_string(), output_index.to_string(), encode_prefixed(order_hash2), @@ -360,14 +360,14 @@ mod tests { let result: BatchQuoteSpec = (&specs_str).try_into().unwrap(); let expected = BatchQuoteSpec(vec![ QuoteSpec { - orderbook: orderbook1, + raindex: raindex1, input_io_index: input_index, output_io_index: output_index, signed_context: vec![], order_hash: U256::from_be_bytes(order_hash1), }, QuoteSpec { - orderbook: orderbook2, + raindex: raindex2, input_io_index: input_index, output_io_index: output_index, signed_context: vec![], @@ -378,11 +378,11 @@ mod tests { // invalid targets let specs_str = vec![ - encode_prefixed(orderbook1.0), + encode_prefixed(raindex1.0), input_index.to_string(), output_index.to_string(), encode_prefixed([1u8; 32]), - encode_prefixed(orderbook2.0), + encode_prefixed(raindex2.0), input_index.to_string(), output_index.to_string(), ]; @@ -391,7 +391,7 @@ mod tests { .to_string(); assert_eq!(result, "missing order hash"); - let specs_str = vec![encode_prefixed(orderbook1.0), input_index.to_string()]; + let specs_str = vec![encode_prefixed(raindex1.0), input_index.to_string()]; let result = std::convert::TryInto::::try_into(&specs_str) .expect_err("expected error") .to_string(); @@ -400,7 +400,7 @@ mod tests { #[test] fn test_read_content() { - let orderbook = Address::random(); + let raindex = Address::random(); let input_io_index = 10u8; let output_io_index = 8u8; let order_hash = [5u8; 32]; @@ -410,7 +410,7 @@ mod tests { input_io_index, output_io_index, signed_context: vec![], - orderbook, + raindex, }]); let input = Input { input: Some(specs.clone()), @@ -420,7 +420,7 @@ mod tests { matches!(input.read_content().unwrap(), InputContentType::Spec(_)); let targets_str = vec![ - encode_prefixed(orderbook.0), + encode_prefixed(raindex.0), input_io_index.to_string(), output_io_index.to_string(), encode_prefixed(OrderV4::default().abi_encode()), @@ -433,7 +433,7 @@ mod tests { matches!(input.read_content().unwrap(), InputContentType::Target(_)); let specs_str = vec![ - encode_prefixed(orderbook.0), + encode_prefixed(raindex.0), input_io_index.to_string(), output_io_index.to_string(), encode_prefixed([1u8; 32]), diff --git a/crates/quote/src/cli/mod.rs b/crates/quote/src/cli/mod.rs index 0083583a3d..819bd67b5d 100644 --- a/crates/quote/src/cli/mod.rs +++ b/crates/quote/src/cli/mod.rs @@ -8,9 +8,9 @@ use url::Url; mod input; pub use input::*; -/// Rain orderbook Quoter CLI app entrypoint sruct +/// Rain raindex Quoter CLI app entrypoint sruct #[derive(Parser, Debug, Clone)] -#[command(author, version, about = "Rain Orderbook Quote CLI", long_about = None)] +#[command(author, version, about = "Rain Raindex Quote CLI", long_about = None)] pub struct Quoter { // input group, only one of which can be specified at a time #[command(flatten)] @@ -153,7 +153,7 @@ mod tests { use clap::CommandFactory; use httpmock::{Method::POST, MockServer}; use rain_math_float::Float; - use rain_orderbook_bindings::IRaindexV6::{quote2Call, quote2Return, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{quote2Call, quote2Return, OrderV4, IOV2}; use serde_json::json; use std::{fs::read_to_string, str::FromStr}; use tempfile::NamedTempFile; @@ -170,14 +170,14 @@ mod tests { let output = PathBuf::from_str("./a/b").unwrap(); let batch_quote_specs = BatchQuoteSpec(vec![QuoteSpec { - orderbook: Address::random(), + raindex: Address::random(), input_io_index: 0, output_io_index: 0, order_hash: U256::from(1), signed_context: vec![], }]); let mut bytes = vec![]; - bytes.extend(batch_quote_specs.0[0].orderbook.0); + bytes.extend(batch_quote_specs.0[0].raindex.0); bytes.push(batch_quote_specs.0[0].input_io_index); bytes.push(batch_quote_specs.0[0].output_io_index); bytes.extend(batch_quote_specs.0[0].order_hash.to_be_bytes_vec()); @@ -204,8 +204,8 @@ mod tests { Some(&batch_quote_specs) ); - let orderbook1 = encode_prefixed(Address::random().0); - let orderbook2 = encode_prefixed(Address::random().0); + let raindex1 = encode_prefixed(Address::random().0); + let raindex2 = encode_prefixed(Address::random().0); let order_bytes1 = encode_prefixed(OrderV4::default().abi_encode()); let order_bytes2 = encode_prefixed(OrderV4::default().abi_encode()); let input_index = U256::from(8).to_string(); @@ -218,12 +218,12 @@ mod tests { "--rpc", rpc.as_str(), "--target", - &orderbook1, + &raindex1, &input_index, &output_index, &order_bytes1, "--target", - &orderbook2, + &raindex2, &input_index, &output_index, &order_bytes2, @@ -237,8 +237,8 @@ mod tests { .map(Iterator::collect) .collect::>>(), vec![ - vec![&orderbook1, &input_index, &output_index, &order_bytes1], - vec![&orderbook2, &input_index, &output_index, &order_bytes2] + vec![&raindex1, &input_index, &output_index, &order_bytes1], + vec![&raindex2, &input_index, &output_index, &order_bytes2] ] ); @@ -249,7 +249,7 @@ mod tests { "--output", output.clone().to_str().unwrap(), "--target", - &orderbook1, + &raindex1, &input_index, &output_index, &order_bytes1, @@ -323,7 +323,7 @@ mod tests { }); // mock subgraph - let orderbook = Address::random(); + let raindex = Address::random(); let order = OrderV4 { validInputs: vec![IOV2::default()], validOutputs: vec![IOV2::default()], @@ -333,7 +333,7 @@ mod tests { let order_hash_u256 = U256::from_be_bytes(order_hash_bytes); let order_hash = encode_prefixed(order_hash_bytes); let mut order_id = vec![]; - order_id.extend_from_slice(orderbook.as_ref()); + order_id.extend_from_slice(raindex.as_ref()); order_id.extend_from_slice(&order_hash_bytes); let order_id = encode_prefixed(keccak256(order_id)); let retrun_sg_data = serde_json::json!({ @@ -355,7 +355,7 @@ mod tests { }, "balance": "0", "vaultId": order.validOutputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] @@ -372,12 +372,12 @@ mod tests { }, "balance": "0", "vaultId": order.validInputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [], "ordersAsInput": [], "balanceChanges": [] }], - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "active": true, "addEvents": [{ "transaction": { @@ -406,7 +406,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }, QuoteSpec::default(), ]); @@ -438,11 +438,11 @@ mod tests { // specs input let specs_str = vec![ - encode_prefixed(orderbook.0), + encode_prefixed(raindex.0), 0.to_string(), 0.to_string(), encode_prefixed(order_hash_bytes), - encode_prefixed(orderbook.0), + encode_prefixed(raindex.0), 0.to_string(), 0.to_string(), encode_prefixed([0u8; 32]), @@ -481,11 +481,11 @@ mod tests { let test_file = NamedTempFile::new().unwrap(); let test_path = test_file.path().to_path_buf(); - let orderbook = Address::random(); + let raindex = Address::random(); let input_io_index = 0u8; let output_io_index = 0u8; let targets_str = vec![ - encode_prefixed(orderbook.0), + encode_prefixed(raindex.0), input_io_index.to_string(), output_io_index.to_string(), encode_prefixed(OrderV4::default().abi_encode()), diff --git a/crates/quote/src/error.rs b/crates/quote/src/error.rs index 70b17ef295..00942c4056 100644 --- a/crates/quote/src/error.rs +++ b/crates/quote/src/error.rs @@ -4,9 +4,9 @@ use alloy::{ }; use alloy_ethers_typecast::ReadableClientError; use rain_error_decoding::{AbiDecodeFailedErrors, AbiDecodedErrorType}; -use rain_orderbook_bindings::provider::ReadProviderError; -use rain_orderbook_subgraph_client::{ - types::order_detail_traits::OrderDetailError, OrderbookSubgraphClientError, +use raindex_bindings::provider::ReadProviderError; +use raindex_subgraph_client::{ + types::order_detail_traits::OrderDetailError, RaindexSubgraphClientError, }; use thiserror::Error; use url::ParseError; @@ -35,7 +35,7 @@ pub enum Error { #[error(transparent)] UrlParseError(#[from] ParseError), #[error(transparent)] - SubgraphClientError(#[from] OrderbookSubgraphClientError), + SubgraphClientError(#[from] RaindexSubgraphClientError), #[error(transparent)] FromHexError(#[from] FromHexError), #[error(transparent)] diff --git a/crates/quote/src/main.rs b/crates/quote/src/main.rs index 44c8ec3294..7877aa69ac 100644 --- a/crates/quote/src/main.rs +++ b/crates/quote/src/main.rs @@ -1,5 +1,5 @@ #[cfg(not(target_family = "wasm"))] #[tokio::main] async fn main() -> anyhow::Result<()> { - rain_orderbook_quote::cli::main().await + raindex_quote::cli::main().await } diff --git a/crates/quote/src/oracle.rs b/crates/quote/src/oracle.rs index 41eeda574b..3b0b563041 100644 --- a/crates/quote/src/oracle.rs +++ b/crates/quote/src/oracle.rs @@ -1,7 +1,7 @@ use alloy::primitives::{Address, Bytes, FixedBytes, U256}; use alloy::sol_types::SolValue; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, SignedContextV1}; -use rain_orderbook_subgraph_client::types::common::SgOrder; +use raindex_bindings::IRaindexV6::{OrderV4, SignedContextV1}; +use raindex_subgraph_client::types::common::SgOrder; use reqwest::Client; use serde::{Deserialize, Serialize}; use url::Url; @@ -33,7 +33,7 @@ pub enum OracleError { } /// JSON response format from an oracle endpoint. -/// Maps directly to `SignedContextV1` in the orderbook contract. +/// Maps directly to `SignedContextV1` in the raindex contract. #[derive(Debug, Clone, Serialize, Deserialize)] pub struct OracleResponse { /// The signer address (EIP-191 signer of the context data) @@ -187,7 +187,7 @@ pub fn extract_oracle_url(order: &SgOrder) -> Option { mod tests { use super::*; use alloy::primitives::{address, FixedBytes}; - use rain_orderbook_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; + use raindex_bindings::IRaindexV6::{EvaluableV4, OrderV4, IOV2}; #[test] fn test_oracle_response_to_signed_context() { diff --git a/crates/quote/src/order_quotes.rs b/crates/quote/src/order_quotes.rs index 9a0b5f350c..034cd4a24b 100644 --- a/crates/quote/src/order_quotes.rs +++ b/crates/quote/src/order_quotes.rs @@ -5,8 +5,8 @@ use crate::{ }; use alloy::primitives::{Address, U256}; use alloy_ethers_typecast::ReadableClient; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, QuoteV2}; -use rain_orderbook_subgraph_client::types::common::SgOrder; +use raindex_bindings::IRaindexV6::{OrderV4, QuoteV2}; +use raindex_subgraph_client::types::common::SgOrder; use serde::{Deserialize, Serialize}; use std::str::FromStr; #[cfg(target_family = "wasm")] @@ -63,7 +63,7 @@ pub async fn get_order_quotes( for order in &orders { let order_struct: OrderV4 = order.clone().try_into()?; - let orderbook = Address::from_str(&order.orderbook.id.0)?; + let raindex = Address::from_str(&order.raindex.id.0)?; let oracle_url = crate::oracle::extract_oracle_url(order); for (input_index, input) in order_struct.validInputs.iter().enumerate() { @@ -131,7 +131,7 @@ pub async fn get_order_quotes( Ok(ctx) => { all_pairs.push(pair); all_quote_targets.push(QuoteTarget { - orderbook, + raindex, quote_config: QuoteV2 { order: order_struct.clone(), inputIOIndex: U256::from(input_index), @@ -209,21 +209,21 @@ mod tests { }; use alloy_ethers_typecast::ReadableClientError; use rain_math_float::Float; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; - use rain_orderbook_subgraph_client::types::{ - common::{SgBigInt, SgBytes, SgErc20, SgOrderbook, SgVault}, + use raindex_app_settings::spec_version::SpecVersion; + use raindex_common::{add_order::AddOrderArgs, dotrain_order::DotrainOrder}; + use raindex_subgraph_client::types::{ + common::{SgBigInt, SgBytes, SgErc20, SgRaindex, SgVault}, order_detail_traits::OrderDetailError, }; - use rain_orderbook_subgraph_client::utils::float::*; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_subgraph_client::utils::float::*; + use raindex_test_fixtures::LocalEvm; struct TestSetup { local_evm: LocalEvm, owner: Address, token1: SgErc20, token2: SgErc20, - orderbook: Address, + raindex: Address, } async fn setup_test() -> TestSetup { @@ -236,7 +236,7 @@ mod tests { let token2 = local_evm .deploy_new_token("Token2", "Token2", 18, U256::MAX, owner) .await; - let orderbook = *local_evm.orderbook.address(); + let raindex = *local_evm.raindex.address(); TestSetup { local_evm, @@ -255,7 +255,7 @@ mod tests { symbol: Some("Token2".to_string()), decimals: Some(SgBigInt(18.to_string())), }, - orderbook, + raindex, } } @@ -286,9 +286,9 @@ tokens: decimals: 18 label: Token1 symbol: token1 -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -318,7 +318,7 @@ amount price: 2 3; :; "#, rpc_url = setup.local_evm.url(), - orderbook = setup.orderbook, + raindex = setup.raindex, rainlang_address = setup.local_evm.rainlang, token1 = setup.token1.address.0, token2 = setup.token2.address.0, @@ -358,8 +358,8 @@ amount price: 2 3; balance: SgBytes(F6.as_hex()), vault_id: SgBytes(vault_id.to_string()), owner: SgBytes(setup.local_evm.anvil.addresses()[0].to_string()), - orderbook: SgOrderbook { - id: SgBytes(setup.orderbook.to_string()), + raindex: SgRaindex { + id: SgBytes(setup.raindex.to_string()), }, orders_as_input: vec![], orders_as_output: vec![], @@ -375,8 +375,8 @@ amount price: 2 3; ) -> SgOrder { SgOrder { id: SgBytes(B256::random().to_string()), - orderbook: SgOrderbook { - id: SgBytes(setup.orderbook.to_string()), + raindex: SgRaindex { + id: SgBytes(setup.raindex.to_string()), }, order_bytes: SgBytes(order_bytes), order_hash: SgBytes(B256::random().to_string()), @@ -505,9 +505,9 @@ amount price: 2 3; let dotrain = create_dotrain_config(&setup); let order = create_order(&setup, dotrain).await; - // Test invalid orderbook address + // Test invalid raindex address let mut invalid_order = create_sg_order(&setup, order.clone(), vec![], vec![]); - invalid_order.orderbook.id = SgBytes("invalid_address".to_string()); + invalid_order.raindex.id = SgBytes("invalid_address".to_string()); let err = get_order_quotes(vec![invalid_order], None, vec![setup.local_evm.url()], None) .await diff --git a/crates/quote/src/quote.rs b/crates/quote/src/quote.rs index ea3d97769d..c78e211068 100644 --- a/crates/quote/src/quote.rs +++ b/crates/quote/src/quote.rs @@ -13,11 +13,11 @@ use url::Url; use wasm_bindgen_utils::{add_ts_content, impl_wasm_traits, prelude::*}; use rain_math_float::Float; -use rain_orderbook_bindings::IRaindexV6::{quote2Return, OrderV4, QuoteV2, SignedContextV1}; -use rain_orderbook_subgraph_client::{ +use raindex_bindings::IRaindexV6::{quote2Return, OrderV4, QuoteV2, SignedContextV1}; +use raindex_subgraph_client::{ types::{common::SgBytes, Id}, utils::make_order_id, - OrderbookSubgraphClient, + RaindexSubgraphClient, }; pub type QuoteResult = Result; @@ -52,7 +52,7 @@ impl From for OrderQuoteValue { pub struct QuoteTarget { pub quote_config: QuoteV2, #[cfg_attr(target_family = "wasm", tsify(type = "string"))] - pub orderbook: Address, + pub raindex: Address, } #[cfg(target_family = "wasm")] impl_wasm_traits!(QuoteTarget); @@ -64,9 +64,9 @@ impl QuoteTarget { } /// Get subgraph represented "order_id" of self - /// which is keccak256 of orderbook address concated with order hash + /// which is keccak256 of raindex address concated with order hash pub fn get_id(&self) -> B256 { - make_order_id(self.orderbook, self.get_order_hash().into()) + make_order_id(self.raindex, self.get_order_hash().into()) } /// Quotes the target on the given rpc urls @@ -147,16 +147,16 @@ pub struct QuoteSpec { pub output_io_index: u8, pub signed_context: Vec, #[cfg_attr(target_family = "wasm", tsify(type = "string"))] - pub orderbook: Address, + pub raindex: Address, } #[cfg(target_family = "wasm")] impl_wasm_traits!(QuoteSpec); impl QuoteSpec { /// Get subgraph represented "order_id" of self - /// which is keccak256 of orderbook address concated with order hash + /// which is keccak256 of raindex address concated with order hash pub fn get_id(&self) -> B256 { - make_order_id(self.orderbook, self.order_hash) + make_order_id(self.raindex, self.order_hash) } /// Given a subgraph will fetch the order details and returns the @@ -166,13 +166,13 @@ impl QuoteSpec { subgraph_url: &str, ) -> Result { let url = Url::from_str(subgraph_url)?; - let sg_client = OrderbookSubgraphClient::new(url); + let sg_client = RaindexSubgraphClient::new(url); let order_detail = sg_client .order_detail(&Id::new(encode_prefixed(self.get_id()))) .await?; Ok(QuoteTarget { - orderbook: self.orderbook, + raindex: self.raindex, quote_config: QuoteV2 { inputIOIndex: U256::from(self.input_io_index), outputIOIndex: U256::from(self.output_io_index), @@ -226,7 +226,7 @@ impl BatchQuoteSpec { subgraph_url: &str, ) -> Result>, Error> { let url = Url::from_str(subgraph_url)?; - let sg_client = OrderbookSubgraphClient::new(url); + let sg_client = RaindexSubgraphClient::new(url); let orders_details = sg_client .batch_order_detail( self.0 @@ -245,7 +245,7 @@ impl BatchQuoteSpec { .find(|order_detail| order_detail.id.0 == encode_prefixed(target.get_id())) .and_then(|order_detail| { Some(QuoteTarget { - orderbook: target.orderbook, + raindex: target.raindex, quote_config: QuoteV2 { inputIOIndex: U256::from(target.input_io_index), outputIOIndex: U256::from(target.output_io_index), @@ -327,13 +327,13 @@ mod tests { use alloy::transports::TransportError; use httpmock::{Method::POST, MockServer}; use rain_error_decoding::AbiDecodedErrorType; - use rain_orderbook_bindings::IRaindexV6::{quote2Call, QuoteV2, IOV2}; - use rain_orderbook_subgraph_client::OrderbookSubgraphClientError; + use raindex_bindings::IRaindexV6::{quote2Call, QuoteV2, IOV2}; + use raindex_subgraph_client::RaindexSubgraphClientError; use serde_json::{json, Value}; // helper fn to build some test data fn get_test_data(batch: bool) -> (Address, OrderV4, U256, Value) { - let orderbook = Address::random(); + let raindex = Address::random(); let order = OrderV4 { validInputs: vec![IOV2::default()], validOutputs: vec![IOV2::default()], @@ -343,7 +343,7 @@ mod tests { let order_hash_u256 = U256::from_be_bytes(order_hash_bytes); let order_hash = encode_prefixed(order_hash_bytes); let mut id = vec![]; - id.extend_from_slice(orderbook.as_ref()); + id.extend_from_slice(raindex.as_ref()); id.extend_from_slice(&order_hash_bytes); let order_id = encode_prefixed(keccak256(id)); let order_json = json!({ @@ -363,7 +363,7 @@ mod tests { }, "balance": "0", "vaultId": order.validOutputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [{ "id": encode_prefixed(B256::random()), "orderHash": encode_prefixed(B256::random()), @@ -398,7 +398,7 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { "id": encode_prefixed(B256::random()) } + "raindex": { "id": encode_prefixed(B256::random()) } }], }], "inputs": [{ @@ -413,7 +413,7 @@ mod tests { }, "balance": "0", "vaultId": order.validInputs[0].vaultId.to_string(), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "ordersAsOutput": [{ "id": encode_prefixed(B256::random()), "orderHash": encode_prefixed(B256::random()), @@ -448,10 +448,10 @@ mod tests { "timestamp": "0", "from": encode_prefixed(Address::random()) }, - "orderbook": { "id": encode_prefixed(B256::random()) } + "raindex": { "id": encode_prefixed(B256::random()) } }], }], - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "active": true, "addEvents": [{ "transaction": { @@ -479,18 +479,18 @@ mod tests { } }) }; - (orderbook, order, order_hash_u256, retrun_sg_data) + (raindex, order, order_hash_u256, retrun_sg_data) } #[test] fn test_quote_target_get_order_hash() { - let (orderbook, order, _, _) = get_test_data(false); + let (raindex, order, _, _) = get_test_data(false); let quote_target = QuoteTarget { quote_config: QuoteV2 { order, ..Default::default() }, - orderbook, + raindex, }; let actual = quote_target.get_order_hash().encode_hex(); let expected = @@ -502,7 +502,7 @@ mod tests { fn test_quote_target_get_id() { let quote_target = QuoteTarget { quote_config: Default::default(), - orderbook: Address::ZERO, + raindex: Address::ZERO, }; let actual = quote_target.get_id().encode_hex(); let expected = @@ -517,7 +517,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: Vec::new(), - orderbook: Address::ZERO, + raindex: Address::ZERO, }; let actual = quote_spec.get_id().encode_hex(); let expected = @@ -527,13 +527,13 @@ mod tests { #[test] fn test_validate_ok() { - let (orderbook, order, _, _) = get_test_data(false); + let (raindex, order, _, _) = get_test_data(false); let quote_target = QuoteTarget { quote_config: QuoteV2 { order, ..Default::default() }, - orderbook, + raindex, }; assert!(quote_target.validate().is_ok()); } @@ -546,7 +546,7 @@ mod tests { outputIOIndex: U256::from(1_u16), ..Default::default() }, - orderbook: Address::ZERO, + raindex: Address::ZERO, }; assert!(quote_target.validate().is_err()); @@ -556,7 +556,7 @@ mod tests { inputIOIndex: U256::from(1_u16), ..Default::default() }, - orderbook: Address::ZERO, + raindex: Address::ZERO, }; assert!(quote_target.validate().is_err()); } @@ -565,7 +565,7 @@ mod tests { async fn test_get_quote_spec_from_subgraph_ok() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, order_id_u256, retrun_sg_data) = get_test_data(false); + let (raindex, order, order_id_u256, retrun_sg_data) = get_test_data(false); // mock subgraph rpc_server.mock(|when, then| { @@ -578,7 +578,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }; let result = quote_target_specifier .get_quote_target_from_subgraph(rpc_server.url("/").as_str()) @@ -586,7 +586,7 @@ mod tests { .unwrap(); let expected = QuoteTarget { - orderbook, + raindex, quote_config: QuoteV2 { order, inputIOIndex: U256::from(quote_target_specifier.input_io_index), @@ -600,14 +600,14 @@ mod tests { #[tokio::test] async fn test_get_quote_spec_from_subgraph_err() { - let (orderbook, _, order_id_u256, _) = get_test_data(false); + let (raindex, _, order_id_u256, _) = get_test_data(false); let quote_target_specifier = QuoteSpec { order_hash: order_id_u256, input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }; let err = quote_target_specifier @@ -634,7 +634,7 @@ mod tests { assert!(matches!( err, - Error::SubgraphClientError(OrderbookSubgraphClientError::CynicClientError(_)) + Error::SubgraphClientError(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -642,7 +642,7 @@ mod tests { async fn test_get_batch_quote_spec_from_subgraph_ok() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, order_id_u256, retrun_sg_data) = get_test_data(true); + let (raindex, order, order_id_u256, retrun_sg_data) = get_test_data(true); // mock subgraph rpc_server.mock(|when, then| { @@ -655,7 +655,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }]); let result = batch_quote_targets_specifiers .get_batch_quote_target_from_subgraph(rpc_server.url("/").as_str()) @@ -663,7 +663,7 @@ mod tests { .unwrap(); let expected = vec![Some(QuoteTarget { - orderbook, + raindex, quote_config: QuoteV2 { order, inputIOIndex: U256::from(batch_quote_targets_specifiers.0[0].input_io_index), @@ -679,7 +679,7 @@ mod tests { async fn test_get_batch_quote_spec_from_subgraph_err() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, order_id_u256, _) = get_test_data(true); + let (raindex, order, order_id_u256, _) = get_test_data(true); rpc_server.mock(|when, then| { when.method(POST).path("/sg"); @@ -689,7 +689,7 @@ mod tests { "orderBytes": encode_prefixed(order.abi_encode()), "orderHash": encode_prefixed(B256::random()), "owner": encode_prefixed(order.owner), - "orderbook": { "id": encode_prefixed(B256::random()) }, + "raindex": { "id": encode_prefixed(B256::random()) }, "active": true, "addEvents": [], "meta": null, @@ -710,7 +710,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }]); let err = batch_quote_targets_specifiers @@ -720,7 +720,7 @@ mod tests { assert!(matches!( err, - Error::SubgraphClientError(OrderbookSubgraphClientError::CynicClientError(cynic_err)) + Error::SubgraphClientError(RaindexSubgraphClientError::CynicClientError(cynic_err)) if cynic_err.to_string().contains("error decoding response body") )); } @@ -729,7 +729,7 @@ mod tests { async fn test_quote_spec_do_quote_ok() { let rpc_server = MockServer::start_async().await; - let (orderbook, _, order_id_u256, retrun_sg_data) = get_test_data(false); + let (raindex, _, order_id_u256, retrun_sg_data) = get_test_data(false); let one = Float::parse("1".to_string()).unwrap(); let two = Float::parse("2".to_string()).unwrap(); @@ -767,7 +767,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }; let result = quote_target_specifier @@ -794,7 +794,7 @@ mod tests { async fn test_quote_spec_do_quote_err() { let server = MockServer::start_async().await; - let (orderbook, _, order_id_u256, retrun_sg_data) = get_test_data(false); + let (raindex, _, order_id_u256, retrun_sg_data) = get_test_data(false); let one = Float::parse("1".to_string()).unwrap(); let two = Float::parse("2".to_string()).unwrap(); @@ -843,7 +843,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }; let err = quote_target_specifier @@ -881,7 +881,7 @@ mod tests { assert!(matches!( err, - Error::SubgraphClientError(OrderbookSubgraphClientError::CynicClientError( + Error::SubgraphClientError(RaindexSubgraphClientError::CynicClientError( cynic_err, )) if cynic_err.to_string().contains("error decoding response body") )); @@ -891,7 +891,7 @@ mod tests { async fn test_quote_batch_spec_do_quote_err() { let rpc_server = MockServer::start_async().await; - let (orderbook, _, order_id_u256, retrun_sg_data) = get_test_data(true); + let (raindex, _, order_id_u256, retrun_sg_data) = get_test_data(true); // build response data let one = Float::parse("1".to_string()).unwrap(); @@ -930,7 +930,7 @@ mod tests { input_io_index: 0, output_io_index: 0, signed_context: vec![], - orderbook, + raindex, }, // should be Err in final result QuoteSpec::default(), @@ -986,13 +986,13 @@ mod tests { async fn test_quote_target_do_quote_ok() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, _, _) = get_test_data(false); + let (raindex, order, _, _) = get_test_data(false); let quote_target = QuoteTarget { quote_config: QuoteV2 { order, ..Default::default() }, - orderbook, + raindex, }; // build response data @@ -1034,13 +1034,13 @@ mod tests { async fn test_quote_target_do_quote_err() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, _, _) = get_test_data(false); + let (raindex, order, _, _) = get_test_data(false); let quote_target = QuoteTarget { quote_config: QuoteV2 { order, ..Default::default() }, - orderbook, + raindex, }; let response_data = vec![MulticallResult { @@ -1074,13 +1074,13 @@ mod tests { async fn test_batch_quote_target_do_quote_ok() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, _, _) = get_test_data(true); + let (raindex, order, _, _) = get_test_data(true); let quote_targets = BatchQuoteTarget(vec![QuoteTarget { quote_config: QuoteV2 { order, ..Default::default() }, - orderbook, + raindex, }]); // build response data @@ -1128,13 +1128,13 @@ mod tests { async fn test_batch_quote_target_do_quote_err() { let rpc_server = MockServer::start_async().await; - let (orderbook, order, _, _) = get_test_data(true); + let (raindex, order, _, _) = get_test_data(true); let quote_targets = BatchQuoteTarget(vec![QuoteTarget { quote_config: QuoteV2 { order, ..Default::default() }, - orderbook, + raindex, }]); rpc_server.mock(|when, then| { diff --git a/crates/quote/src/quote_debug.rs b/crates/quote/src/quote_debug.rs index 665e676e5b..e4e3fbd99e 100644 --- a/crates/quote/src/quote_debug.rs +++ b/crates/quote/src/quote_debug.rs @@ -7,7 +7,7 @@ use rain_interpreter_eval::{ fork::{Forker, NewForkedEvm}, trace::{RainEvalResult, RainEvalResultFromRawCallResultError}, }; -use rain_orderbook_bindings::IRaindexV6::quote2Call; +use raindex_bindings::IRaindexV6::quote2Call; use url::Url; pub struct NewQuoteDebugger { @@ -67,7 +67,7 @@ impl QuoteDebugger { let res = self.forker.call( Address::default().as_slice(), - quote_target.orderbook.as_slice(), + quote_target.raindex.as_slice(), "e_call.abi_encode(), )?; @@ -88,18 +88,18 @@ mod tests { use alloy::primitives::{fixed_bytes, U256}; use alloy::sol_types::{SolCall, SolValue}; use httpmock::MockServer; - use rain_orderbook_app_settings::spec_version::SpecVersion; - use rain_orderbook_bindings::IRaindexV6::{OrderV4, QuoteV2}; - use rain_orderbook_common::add_order::AddOrderArgs; - use rain_orderbook_common::dotrain_order::DotrainOrder; - use rain_orderbook_test_fixtures::LocalEvm; + use raindex_app_settings::spec_version::SpecVersion; + use raindex_bindings::IRaindexV6::{OrderV4, QuoteV2}; + use raindex_common::add_order::AddOrderArgs; + use raindex_common::dotrain_order::DotrainOrder; + use raindex_test_fixtures::LocalEvm; use std::str::FromStr; #[tokio::test(flavor = "multi_thread", worker_threads = 10)] async fn test_quote_debugger() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -130,9 +130,9 @@ tokens: decimals: 18 label: Token1 symbol: token1 -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -159,7 +159,7 @@ amount price: 16 52; :; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang_address = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -205,7 +205,7 @@ amount price: 16 52; let order = OrderV4::abi_decode(&order.abi_encode()).unwrap(); let quote_target = QuoteTarget { - orderbook: *orderbook.address(), + raindex: *raindex.address(), quote_config: QuoteV2 { order, inputIOIndex: U256::from(0), @@ -224,7 +224,7 @@ amount price: 16 52; async fn test_quote_debugger_partial() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -255,9 +255,9 @@ tokens: decimals: 18 label: Token1 symbol: token1 -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -289,7 +289,7 @@ _ _: amount price; _: 1; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang_address = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -335,7 +335,7 @@ _: 1; let order = OrderV4::abi_decode(&order.abi_encode()).unwrap(); let quote_target = QuoteTarget { - orderbook: *orderbook.address(), + raindex: *raindex.address(), quote_config: QuoteV2 { order, inputIOIndex: U256::from(0), @@ -361,7 +361,7 @@ _: 1; async fn test_quote_debugger_debug_err() { let local_evm = LocalEvm::new_with_tokens(2).await; - let orderbook = &local_evm.orderbook; + let raindex = &local_evm.raindex; let token1_holder = local_evm.signer_wallets[0].default_signer().address(); let token1 = local_evm.tokens[0].clone(); let token2 = local_evm.tokens[1].clone(); @@ -392,9 +392,9 @@ tokens: decimals: 18 label: Token1 symbol: token1 -orderbook: +raindex: some-key: - address: {orderbook} + address: {raindex} orders: some-key: inputs: @@ -426,7 +426,7 @@ _ _: amount price; _: 1; "#, rpc_url = local_evm.url(), - orderbook = orderbook.address(), + raindex = raindex.address(), rainlang_address = local_evm.rainlang, token1 = token1.address(), token2 = token2.address(), @@ -472,7 +472,7 @@ _: 1; let order = OrderV4::abi_decode(&order.abi_encode()).unwrap(); let quote_target = QuoteTarget { - orderbook: *orderbook.address(), + raindex: *raindex.address(), quote_config: QuoteV2 { order, inputIOIndex: U256::from(1), diff --git a/crates/quote/src/rpc.rs b/crates/quote/src/rpc.rs index ad565ce49d..2e12e329d9 100644 --- a/crates/quote/src/rpc.rs +++ b/crates/quote/src/rpc.rs @@ -8,8 +8,8 @@ use alloy::{ primitives::Address, }; use rain_error_decoding::{AbiDecodedErrorType, ErrorRegistry}; -use rain_orderbook_bindings::provider::{mk_read_provider, ReadProvider}; -use rain_orderbook_bindings::IRaindexV6::{quote2Call, quote2Return, IRaindexV6Instance}; +use raindex_bindings::provider::{mk_read_provider, ReadProvider}; +use raindex_bindings::IRaindexV6::{quote2Call, quote2Return, IRaindexV6Instance}; use url::Url; const DEFAULT_QUOTE_CHUNK_SIZE: usize = 16; @@ -51,7 +51,7 @@ async fn quote_chunk_once( } for quote_target in quote_targets { - let ob_instance = IRaindexV6Instance::new(quote_target.orderbook, provider.clone()); + let ob_instance = IRaindexV6Instance::new(quote_target.raindex, provider.clone()); let call = ob_instance .quote2(quote_target.quote_config.clone()) .into_call(true); @@ -251,7 +251,7 @@ mod tests { use httpmock::{Method::POST, MockServer}; use rain_error_decoding::ErrorRegistry; use rain_math_float::Float; - use rain_orderbook_bindings::IRaindexV6::{quote2Call, quote2Return}; + use raindex_bindings::IRaindexV6::{quote2Call, quote2Return}; use serde_json::json; #[test] diff --git a/crates/rest_api/Cargo.toml b/crates/rest_api/Cargo.toml index bb95ea3614..a2d72a553b 100644 --- a/crates/rest_api/Cargo.toml +++ b/crates/rest_api/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_rest_api" -description = "REST API server for rain orderbook" +name = "raindex_rest_api" +description = "REST API server for raindex" version.workspace = true edition.workspace = true license.workspace = true @@ -8,11 +8,11 @@ homepage.workspace = true publish = false [[bin]] -name = "rain-orderbook-api" +name = "raindex-api" path = "src/main.rs" [dependencies] -rain_orderbook_common = { workspace = true } +raindex_common = { workspace = true } rocket = { version = "0.5.1", features = ["json"] } rocket_cors = "0.6" serde = { workspace = true, features = ["derive"] } diff --git a/crates/rest_api/src/error.rs b/crates/rest_api/src/error.rs index 71981ba305..106e79804d 100644 --- a/crates/rest_api/src/error.rs +++ b/crates/rest_api/src/error.rs @@ -1,4 +1,4 @@ -use rain_orderbook_common::raindex_client::RaindexError; +use raindex_common::raindex_client::RaindexError; use rocket::http::Status; use rocket::response::{self, Responder}; use rocket::serde::json::Json; @@ -51,7 +51,7 @@ impl ApiError { } RaindexError::ChainIdNotFound(_) - | RaindexError::OrderbookNotFound(_, _) + | RaindexError::RaindexNotFound(_, _) | RaindexError::OrderNotFound(_, _, _) | RaindexError::VaultNotFound(_, _, _) | RaindexError::SubgraphNotFound(_, _) @@ -138,7 +138,7 @@ mod tests { fn test_status_code_not_found_config_errors() { let not_found_errors = vec![ ApiError::Raindex(RaindexError::ChainIdNotFound(1)), - ApiError::Raindex(RaindexError::OrderbookNotFound("0x123".to_string(), 1)), + ApiError::Raindex(RaindexError::RaindexNotFound("0x123".to_string(), 1)), ApiError::Raindex(RaindexError::OrderNotFound( "0x123".to_string(), 1, diff --git a/crates/rest_api/src/main.rs b/crates/rest_api/src/main.rs index 124685a80a..f292a5042d 100644 --- a/crates/rest_api/src/main.rs +++ b/crates/rest_api/src/main.rs @@ -14,8 +14,8 @@ use utoipa_swagger_ui::SwaggerUi; #[derive(OpenApi)] #[openapi( info( - title = "Rain Orderbook API", - description = "REST API for interacting with Rain Orderbook." + title = "Rain Raindex API", + description = "REST API for interacting with Rain Raindex." ), paths(routes::take_orders::buy, routes::take_orders::sell), components(schemas( @@ -394,7 +394,7 @@ mod tests { let spec: serde_json::Value = serde_json::from_str(&body).unwrap(); assert_eq!(spec["openapi"], "3.1.0"); - assert_eq!(spec["info"]["title"], "Rain Orderbook API"); + assert_eq!(spec["info"]["title"], "Rain Raindex API"); } #[test] @@ -464,7 +464,7 @@ mod tests { assert_eq!( buy_schema["yamlContent"]["description"], - "YAML configuration containing network RPC endpoints, subgraph URLs, and orderbook addresses" + "YAML configuration containing network RPC endpoints, subgraph URLs, and raindex addresses" ); assert_eq!( buy_schema["taker"]["description"], @@ -507,7 +507,7 @@ mod tests { assert_eq!( sell_schema["yamlContent"]["description"], - "YAML configuration containing network RPC endpoints, subgraph URLs, and orderbook addresses" + "YAML configuration containing network RPC endpoints, subgraph URLs, and raindex addresses" ); assert_eq!( sell_schema["taker"]["description"], @@ -549,8 +549,8 @@ mod tests { let ready_schema = &spec["components"]["schemas"]["TakeOrdersReadyResponse"]["properties"]; assert_eq!( - ready_schema["orderbook"]["description"], - "Address of the orderbook contract to call" + ready_schema["raindex"]["description"], + "Address of the raindex contract to call" ); assert_eq!( ready_schema["calldata"]["description"], @@ -581,7 +581,7 @@ mod tests { ); assert_eq!( approval_schema["spender"]["description"], - "Spender address (the orderbook contract)" + "Spender address (the raindex contract)" ); assert_eq!( approval_schema["amount"]["description"], @@ -619,7 +619,7 @@ mod tests { let ready_value = &examples["Ready"]["value"]; assert_eq!(ready_value["status"], "ready"); - assert!(ready_value["data"]["orderbook"].is_string()); + assert!(ready_value["data"]["raindex"].is_string()); assert!(ready_value["data"]["calldata"].is_string()); assert!(ready_value["data"]["effectivePrice"].is_string()); assert!(ready_value["data"]["prices"].is_array()); diff --git a/crates/rest_api/src/routes/take_orders.rs b/crates/rest_api/src/routes/take_orders.rs index a1549ee949..c3814b499e 100644 --- a/crates/rest_api/src/routes/take_orders.rs +++ b/crates/rest_api/src/routes/take_orders.rs @@ -1,7 +1,7 @@ use crate::error::{ApiError, ApiErrorResponse}; -use rain_orderbook_common::raindex_client::take_orders::TakeOrdersRequest; -use rain_orderbook_common::raindex_client::RaindexClient; -use rain_orderbook_common::take_orders::TakeOrdersMode; +use raindex_common::raindex_client::take_orders::TakeOrdersRequest; +use raindex_common::raindex_client::RaindexClient; +use raindex_common::take_orders::TakeOrdersMode; use rocket::serde::json::Json; use rocket::{post, Route}; use serde::{Deserialize, Serialize}; @@ -10,9 +10,9 @@ use utoipa::ToSchema; #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct BuyRequest { - /// YAML configuration containing network RPC endpoints, subgraph URLs, and orderbook addresses + /// YAML configuration containing network RPC endpoints, subgraph URLs, and raindex addresses #[schema( - example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn\norderbooks:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" + example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn\nraindexes:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" )] pub yaml_content: String, /// Address that will execute the transaction @@ -42,9 +42,9 @@ pub struct BuyRequest { #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] pub struct SellRequest { - /// YAML configuration containing network RPC endpoints, subgraph URLs, and orderbook addresses + /// YAML configuration containing network RPC endpoints, subgraph URLs, and raindex addresses #[schema( - example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn\norderbooks:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" + example = "networks:\n base:\n rpc: https://mainnet.base.org\n chain-id: 8453\nsubgraphs:\n base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/ob4-base/0.9/gn\nraindexes:\n base:\n address: 0xd2938e7c9fe3597f78832ce780feb61945c377d7\n network: base\n subgraph: base" )] pub yaml_content: String, /// Address that will execute the transaction @@ -84,7 +84,7 @@ pub struct ApprovalApiResponse { /// Token address that needs approval #[schema(example = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913")] pub token: String, - /// Spender address (the orderbook contract) + /// Spender address (the raindex contract) #[schema(example = "0xd2938e7c9fe3597f78832ce780feb61945c377d7")] pub spender: String, /// Amount to approve (raw value) @@ -101,7 +101,7 @@ pub struct ApprovalApiResponse { #[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] #[serde(rename_all = "camelCase")] #[schema(example = json!({ - "orderbook": "0xd2938e7c9fe3597f78832ce780feb61945c377d7", + "raindex": "0xd2938e7c9fe3597f78832ce780feb61945c377d7", "calldata": "0x...", "effectivePrice": "0.00045", "prices": ["0.00044", "0.00046"], @@ -109,9 +109,9 @@ pub struct ApprovalApiResponse { "maxSellCap": "500" }))] pub struct TakeOrdersReadyResponse { - /// Address of the orderbook contract to call + /// Address of the raindex contract to call #[schema(example = "0xd2938e7c9fe3597f78832ce780feb61945c377d7")] - pub orderbook: String, + pub raindex: String, /// ABI-encoded calldata for the takeOrders4 function #[schema(example = "0x...")] pub calldata: String, @@ -148,9 +148,7 @@ async fn execute_take_orders( if let Some(approval_info) = result.approval_info() { let amount = approval_info.amount().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; Ok(TakeOrdersApiResponse::NeedsApproval(ApprovalApiResponse { @@ -162,9 +160,7 @@ async fn execute_take_orders( })) } else if let Some(take_orders_info) = result.take_orders_info() { let effective_price = take_orders_info.effective_price().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; let prices: Result, _> = take_orders_info @@ -172,27 +168,21 @@ async fn execute_take_orders( .iter() .map(|p| { p.format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) }) }) .collect(); let expected_sell = take_orders_info.expected_sell().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; let max_sell_cap = take_orders_info.max_sell_cap().format().map_err(|e| { - ApiError::Raindex(rain_orderbook_common::raindex_client::RaindexError::Float( - e, - )) + ApiError::Raindex(raindex_common::raindex_client::RaindexError::Float(e)) })?; Ok(TakeOrdersApiResponse::Ready(TakeOrdersReadyResponse { - orderbook: take_orders_info.orderbook().to_string(), + raindex: take_orders_info.raindex().to_string(), calldata: take_orders_info.calldata().to_string(), effective_price, prices: prices?, @@ -214,11 +204,11 @@ async fn execute_take_orders( examples( ("Ready" = ( summary = "Calldata ready to execute", - description = "Returned when the taker has sufficient token approval. The calldata can be submitted directly to the orderbook.", + description = "Returned when the taker has sufficient token approval. The calldata can be submitted directly to the raindex contract.", value = json!({ "status": "ready", "data": { - "orderbook": "0xd2938e7c9fe3597f78832ce780feb61945c377d7", + "raindex": "0xd2938e7c9fe3597f78832ce780feb61945c377d7", "calldata": "0x...", "effectivePrice": "0.00045", "prices": ["0.00044", "0.00046"], @@ -294,11 +284,11 @@ pub async fn buy(request: Json) -> Result>>` and a `Cache`. - `new(sources, validation)` loads YAML strings, applies validation gates via `ValidationConfig`, and returns a provider. - Context initialization: `initialize_context_and_expand_remote_data()` injects remote networks/tokens from the cache into a fresh `Context`. @@ -56,7 +56,7 @@ Two top‑level providers wrap one or more YAML documents and expose a convenien - Tokens: `get_token_keys`, `get_tokens`, `get_token(key)`. - Remote tokens: `get_remote_tokens` (parse optional `using-tokens-from`). - Subgraphs: `get_subgraph_keys`, `get_subgraphs`, `get_subgraph(key)`. - - Orderbooks: `get_orderbook_keys`, `get_orderbooks`, `get_orderbook(key)`, `get_orderbook_by_address(Address)`, `get_orderbooks_by_network_key(&str)`. + - Raindexes: `get_raindex_keys`, `get_raindexes`, `get_raindex(key)`, `get_raindex_by_address(Address)`, `get_raindexes_by_network_key(&str)`. - Metaboards: `get_metaboard_keys`, `get_metaboards`, `get_metaboard(key)`, `add_metaboard(key, url)`. - Deployers: `get_deployer_keys`, `get_deployers`, `get_deployer(key)`. - Sentry: `get_sentry()` → Option from `sentry` scalar. @@ -73,7 +73,7 @@ Two top‑level providers wrap one or more YAML documents and expose a convenien - Deployments: `get_deployment_keys`, `get_deployments`, `get_deployment(key)`. - GUI: `get_gui(current_deployment)` parses optional GUI section with deployment‑scoped overrides and select‑tokens. - Charts: `get_chart_keys`, `get_charts`, `get_chart(key)`. - - Serde mirrors `OrderbookYaml`. + - Serde mirrors `RaindexYaml`. ## Core Config Objects @@ -118,24 +118,24 @@ All core configs implement `YamlParsableHash` unless noted, and each instance ca - `SubgraphCfg { key, url }` as a simple `subgraphs:` map. - `add_record_to_yaml(document, key, url)` helper with URL validation. -### Orderbooks (`orderbook.rs`) +### Raindexes (`raindex.rs`) -- `OrderbookCfg { key, address, network: Arc, subgraph: Arc, local_db_remote?: Arc, label?, deployment_block }`. +- `RaindexCfg { key, address, network: Arc, subgraph: Arc, local_db_remote?: Arc, label?, deployment_block }`. - Validators: `validate_address(&str) -> Address`, `validate_deployment_block(&str) -> u64`. -- Lookup helpers: `parse_network_key(docs, orderbook_key)` returns the referenced network key or defaults to the orderbook key. +- Lookup helpers: `parse_network_key(docs, raindex_key)` returns the referenced network key or defaults to the raindex key. - Parses with references to previously parsed networks and subgraphs; duplicates are rejected. -- Error enum: `ParseOrderbookConfigSourceError` (invalid address, missing network/subgraph, block parse error) with readable messages. +- Error enum: `ParseRaindexConfigSourceError` (invalid address, missing network/subgraph, block parse error) with readable messages. ### Local DB Remotes (`local_db_remotes.rs`) - `local-db-remotes:` is a optional top-level map. Each entry is parsed as `LocalDbRemoteCfg { key, url }`. -- The `orderbooks[*].local-db-remote` field is optional. If omitted, it defaults to the orderbook's key. When provided explicitly, it must reference a defined remote key under `local-db-remotes`. - - See `src/orderbook.rs` for the implementation and tests, e.g. `test_orderbook_local_db_remote_absent_defaults_to_orderbook_key`, `test_orderbook_local_db_remote_resolves`, and `test_orderbook_local_db_remote_not_found`. +- The `raindexes[*].local-db-remote` field is optional. If omitted, it defaults to the raindex's key. When provided explicitly, it must reference a defined remote key under `local-db-remotes`. + - See `src/raindex.rs` for the implementation and tests, e.g. `test_raindex_local_db_remote_absent_defaults_to_raindex_key`, `test_raindex_local_db_remote_resolves`, and `test_raindex_local_db_remote_not_found`. ### Deployers (`deployer.rs`) - `DeployerCfg { key, address, network }`. -- Validators and `parse_network_key` similar to orderbooks (defaults to key if `network` is omitted). +- Validators and `parse_network_key` similar to raindexes (defaults to key if `network` is omitted). - Error enum: `ParseDeployerConfigSourceError`. ### Accounts (`accounts.rs`) @@ -151,7 +151,7 @@ All core configs implement `YamlParsableHash` unless noted, and each instance ca ### Spec Version and Sentry - `SpecVersion` reads required root scalar `version`. Const `CURRENT_SPEC_VERSION = "3"` and helpers `current()` / `is_current()`. -- `Sentry` parses optional root scalar `sentry`. `OrderbookYaml::get_sentry()` normalizes to `Option` accepting `true/false/1/0`. +- `Sentry` parses optional root scalar `sentry`. `RaindexYaml::get_sentry()` normalizes to `Option` accepting `true/false/1/0`. ## Orders, Scenarios, Deployments @@ -160,17 +160,17 @@ These three model how orders are defined, how they are executed (bindings, block ### Orders (`order.rs`) -- `OrderCfg { key, inputs: Vec, outputs: Vec, network: Arc, deployer?: Arc, orderbook?: Arc }`. +- `OrderCfg { key, inputs: Vec, outputs: Vec, network: Arc, deployer?: Arc, raindex?: Arc }`. - `OrderIOCfg { token_key: String, token?: Arc, vault_id?: U256 }` – `token_key` preserves the declared token name even when the token is unresolved for select‑tokens; vault IDs are arbitrary U256 strings. - Validation and network unification - Inputs/outputs must each contain `token` (unless permitted by GUI select‑tokens through context) and optional `vault-id`. - - The order’s effective `network` is inferred from first matching component (deployer/orderbook/token), and all references must match. Mismatch yields detailed errors (`DeployerNetworkDoesNotMatch`, `OrderbookNetworkDoesNotMatch`, `InputTokenNetworkDoesNotMatch`, `OutputTokenNetworkDoesNotMatch`). If no network can be determined, `NetworkNotFoundError` is raised. + - The order’s effective `network` is inferred from first matching component (deployer/raindex/token), and all references must match. Mismatch yields detailed errors (`DeployerNetworkDoesNotMatch`, `RaindexNetworkDoesNotMatch`, `InputTokenNetworkDoesNotMatch`, `OutputTokenNetworkDoesNotMatch`). If no network can be determined, `NetworkNotFoundError` is raised. - Vault IDs are validated via `U256::from_str`. - Mutations - `update_vault_id(vault_type, token_key, vault_id_opt)` updates a vault ID for a specific input/output token inside the YAML. - `populate_vault_ids()` fills missing input/output `vault-id`s in the YAML with a freshly generated random U256, and updates the in‑memory struct accordingly. - Helpers - - `parse_network_key(docs, order_key)` – resolves the expected network key by reconciling deployer/orderbook and all IO token networks; errors if any disagree. + - `parse_network_key(docs, order_key)` – resolves the expected network key by reconciling deployer/raindex and all IO token networks; errors if any disagree. - Error enum: `ParseOrderConfigSourceError` implements `to_readable_msg()` for user‑oriented descriptions. ### Scenarios (`scenario.rs`) @@ -278,15 +278,15 @@ Remote sections allow enriching local YAML with data fetched at runtime and merg - Key format: `"--"`. - Conflicting keys across URLs produce `ConflictingTokens`. -Both remote features are surfaced to parsing via the `Context`/`Cache`. `OrderbookYaml` and `DotrainYaml` expose helper methods to fetch/update cache and then merge these into subsequent parses. +Both remote features are surfaced to parsing via the `Context`/`Cache`. `RaindexYaml` and `DotrainYaml` expose helper methods to fetch/update cache and then merge these into subsequent parses. ## Miscellaneous Modules - `accounts.rs`: named EVM addresses in `accounts:`. Simple map with validation and duplicate checks. -- `sentry.rs`: optional root scalar `sentry` read as string and normalized to `Option` by `OrderbookYaml`. +- `sentry.rs`: optional root scalar `sentry` read as string and normalized to `Option` by `RaindexYaml`. - `spec_version.rs`: required root scalar `version` and helpers to compare to the current spec version (constant "3"). -- `test.rs`: test helpers to construct mock networks/tokens/deployers/orderbooks. +- `test.rs`: test helpers to construct mock networks/tokens/deployers/raindexes. - `unit_test.rs`: auxiliary types (`UnitTestConfigSource`, `TestConfigSource`, `ScenarioConfigSource`) used by the test harness in other crates. `TestConfigSource::into_test_config()` converts the simplified source into a `TestConfig` with an embedded `ScenarioCfg`. @@ -312,9 +312,9 @@ When building for `wasm32`, many types derive `Tsify` and implement WASM trait h ## Typical Workflows -- Validate orderbook YAML for networks/tokens/etc. and query objects: - 1. Load strings into `OrderbookYaml::new([...], OrderbookYamlValidation::full())`. - 2. Optionally fetch remote networks/tokens, store in cache, and then call `get_*` methods to retrieve `NetworkCfg`, `TokenCfg`, `OrderbookCfg`, etc. +- Validate raindex YAML for networks/tokens/etc. and query objects: + 1. Load strings into `RaindexYaml::new([...], RaindexYamlValidation::full())`. + 2. Optionally fetch remote networks/tokens, store in cache, and then call `get_*` methods to retrieve `NetworkCfg`, `TokenCfg`, `RaindexCfg`, etc. 3. Use update helpers to persist changes back to YAML documents. - Validate dotrain YAML and build a deployment plan: @@ -333,11 +333,11 @@ When building for `wasm32`, many types derive `Tsify` and implement WASM trait h - `networks: { key: { rpcs: [url,...], chain-id, label?, network-id?, currency? } }` - `tokens: { key: { network, address, decimals?, label?, symbol? } }` - `subgraphs: { key: url }` - - `orderbooks: { key: { address, network?, subgraph?, label?, deployment-block } }` + - `raindexes: { key: { address, network?, subgraph?, label?, deployment-block } }` - `metaboards: { key: url }` - `deployers: { key: { address, network? } }` - `accounts: { key: address }` - - `orders: { key: { inputs: [{ token, vault-id? }, ...], outputs: [...], deployer?, orderbook? } }` + - `orders: { key: { inputs: [{ token, vault-id? }, ...], outputs: [...], deployer?, raindex? } }` - `scenarios: { key: { bindings: {k:v}, runs?, blocks?, deployer?, scenarios?: {...} } }` - `deployments: { key: { scenario, order } }` - `gui: { name, description, deployments: { key: { name, description, deposits: [...], fields: [...], select-tokens?: [...] } } }` @@ -347,9 +347,9 @@ When building for `wasm32`, many types derive `Tsify` and implement WASM trait h ## Testing -The crate ships extensive unit tests for every parser and update path, including error paths with precise messages. Test helpers in `src/test.rs` construct mock networks/deployers/tokens/orderbooks; parser modules provide happy‑path and negative test cases (duplicate keys, missing/invalid fields, range validation for blocks, GUI validation, remote fetch flows with http mocks, etc.). +The crate ships extensive unit tests for every parser and update path, including error paths with precise messages. Test helpers in `src/test.rs` construct mock networks/deployers/tokens/raindexes; parser modules provide happy‑path and negative test cases (duplicate keys, missing/invalid fields, range validation for blocks, GUI validation, remote fetch flows with http mocks, etc.). ## Summary -The settings crate provides a single, well‑typed interface over YAML configuration for the Rain Orderbook ecosystem: robust parsing across multiple files, strict validation with user‑friendly errors, safe in‑place updates, optional remote augmentation, contextual interpolation, GUI and chart DSLs, and WASM interop. Other crates consume these types to build CLIs, runtimes, and UIs without re‑implementing YAML logic. +The settings crate provides a single, well‑typed interface over YAML configuration for the Raindex ecosystem: robust parsing across multiple files, strict validation with user‑friendly errors, safe in‑place updates, optional remote augmentation, contextual interpolation, GUI and chart DSLs, and WASM interop. Other crates consume these types to build CLIs, runtimes, and UIs without re‑implementing YAML logic. diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index a6e95db656..78730c4c1e 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_app_settings" -description = "Rain Orderbook app settings parsing & validation" +name = "raindex_app_settings" +description = "Raindex app settings parsing & validation" version.workspace = true edition.workspace = true license.workspace = true @@ -18,7 +18,7 @@ serde_json = { workspace = true } strict-yaml-rust = { workspace = true } alloy = { workspace = true, features = ["serde", "rand"] } reqwest = { workspace = true } -rain_orderbook_bindings = { workspace = true } +raindex_bindings = { workspace = true } futures = { workspace = true } wasm-bindgen-utils = { workspace = true } diff --git a/crates/settings/src/gui.rs b/crates/settings/src/gui.rs index b5c2b83c42..4b47eaede6 100644 --- a/crates/settings/src/gui.rs +++ b/crates/settings/src/gui.rs @@ -1195,7 +1195,7 @@ mod tests { outputs: vec![], network: mock_network(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }; let deployment = DeploymentCfg { diff --git a/crates/settings/src/lib.rs b/crates/settings/src/lib.rs index 053c8d05ae..a58c6fff8c 100644 --- a/crates/settings/src/lib.rs +++ b/crates/settings/src/lib.rs @@ -9,8 +9,8 @@ pub mod local_db_sync; pub mod metaboard; pub mod network; pub mod order; -pub mod orderbook; pub mod plot_source; +pub mod raindex; pub mod rainlang; pub mod remote; pub mod remote_networks; @@ -30,8 +30,8 @@ pub(crate) use gui::*; pub(crate) use local_db_sync::*; pub(crate) use network::*; pub(crate) use order::*; -pub(crate) use orderbook::*; pub(crate) use plot_source::*; +pub(crate) use raindex::*; pub(crate) use rainlang::*; pub(crate) use remote_networks::*; pub(crate) use scenario::*; diff --git a/crates/settings/src/local_db_manifest.rs b/crates/settings/src/local_db_manifest.rs index a736a3ede1..2bffeee983 100644 --- a/crates/settings/src/local_db_manifest.rs +++ b/crates/settings/src/local_db_manifest.rs @@ -9,7 +9,8 @@ use strict_yaml_rust::{strict_yaml::Hash, StrictYaml, StrictYamlEmitter}; use url::Url; pub const MANIFEST_VERSION: u32 = 1; -pub const DB_SCHEMA_VERSION: u32 = 2; +// Bumped from 2 to 3 for orderbook_address -> raindex_address column rename +pub const DB_SCHEMA_VERSION: u32 = 3; #[derive(Debug, Clone, PartialEq)] pub struct LocalDbManifest { @@ -27,19 +28,19 @@ impl Default for LocalDbManifest { #[derive(Debug, Clone, PartialEq)] pub struct ManifestNetwork { pub chain_id: u32, - pub orderbooks: Vec, + pub raindexes: Vec, } impl ManifestNetwork { pub fn new(chain_id: u32) -> Self { Self { chain_id, - orderbooks: Vec::new(), + raindexes: Vec::new(), } } - pub fn push_orderbook(&mut self, orderbook: ManifestOrderbook) { - self.orderbooks.push(orderbook); + pub fn push_raindex(&mut self, raindex: ManifestRaindex) { + self.raindexes.push(raindex); } fn to_yaml_hash(&self) -> Hash { @@ -49,15 +50,15 @@ impl ManifestNetwork { StrictYaml::String(self.chain_id.to_string()), ); - let orderbooks_yaml: Vec = self - .orderbooks + let raindexes_yaml: Vec = self + .raindexes .iter() - .map(ManifestOrderbook::to_yaml_hash) + .map(ManifestRaindex::to_yaml_hash) .collect(); hash.insert( - StrictYaml::String("orderbooks".to_string()), - StrictYaml::Array(orderbooks_yaml), + StrictYaml::String("raindexes".to_string()), + StrictYaml::Array(raindexes_yaml), ); hash @@ -65,7 +66,7 @@ impl ManifestNetwork { } #[derive(Debug, Clone, PartialEq)] -pub struct ManifestOrderbook { +pub struct ManifestRaindex { pub address: Address, pub dump_url: Url, pub end_block: u64, @@ -73,7 +74,7 @@ pub struct ManifestOrderbook { pub end_block_time_ms: u64, } -impl ManifestOrderbook { +impl ManifestRaindex { fn to_yaml_hash(&self) -> StrictYaml { let mut hash = Hash::new(); hash.insert( @@ -101,11 +102,15 @@ impl ManifestOrderbook { } impl LocalDbManifest { - pub fn find(&self, chain_id: u32, address: Address) -> Option<&ManifestOrderbook> { + pub fn find(&self, chain_id: u32, address: Address) -> Option<&ManifestRaindex> { self.networks .values() .find(|n| n.chain_id == chain_id) - .and_then(|n| n.orderbooks.iter().find(|ob| ob.address == address)) + .and_then(|n| { + n.raindexes + .iter() + .find(|raindex_entry| raindex_entry.address == address) + }) } pub fn new() -> Self { @@ -153,14 +158,14 @@ impl LocalDbManifest { Ok(()) } - pub fn push_orderbook( + pub fn push_raindex( &mut self, network_key: &str, - orderbook: ManifestOrderbook, + raindex: ManifestRaindex, ) -> Result<(), YamlError> { match self.networks.get_mut(network_key) { Some(network) => { - network.push_orderbook(orderbook); + network.push_raindex(raindex); Ok(()) } None => Err(YamlError::Field { @@ -345,25 +350,25 @@ fn parse_single_network( location_network.clone(), )?; - let orderbooks_yaml = require_vec(network_yaml, "orderbooks", Some(location_network.clone()))?; + let raindexes_yaml = require_vec(network_yaml, "raindexes", Some(location_network.clone()))?; - let mut orderbooks: Vec = Vec::new(); - for (idx, ob_yaml) in orderbooks_yaml.iter().enumerate() { - orderbooks.push(parse_single_orderbook(idx, ob_yaml, &location_network)?); + let mut raindexes: Vec = Vec::new(); + for (idx, ob_yaml) in raindexes_yaml.iter().enumerate() { + raindexes.push(parse_single_raindex(idx, ob_yaml, &location_network)?); } Ok(ManifestNetwork { chain_id, - orderbooks, + raindexes, }) } -fn parse_single_orderbook( +fn parse_single_raindex( idx: usize, ob_yaml: &StrictYaml, location_network: &str, -) -> Result { - let location_ob = format!("{}.orderbooks[{}]", location_network, idx); +) -> Result { + let location_ob = format!("{}.raindexes[{}]", location_network, idx); let address_str = require_string(ob_yaml, Some("address"), Some(location_ob.clone()))?; let address = Address::from_str(&address_str).map_err(|e| YamlError::Field { @@ -403,7 +408,7 @@ fn parse_single_orderbook( location_ob.clone(), )?; - Ok(ManifestOrderbook { + Ok(ManifestRaindex { address, dump_url, end_block, @@ -422,8 +427,8 @@ mod tests { StrictYamlLoader::load_from_str(yaml).unwrap()[0].clone() } - fn sample_orderbook() -> ManifestOrderbook { - ManifestOrderbook { + fn sample_raindex() -> ManifestRaindex { + ManifestRaindex { address: Address::from_str("0x00000000000000000000000000000000000000aa").unwrap(), dump_url: Url::parse("https://example.com/dump").unwrap(), end_block: 42, @@ -438,14 +443,14 @@ mod tests { manifest.add_network("mainnet", 1).unwrap(); manifest.add_network("polygon", 137).unwrap(); - let ob_main = ManifestOrderbook { + let ob_main = ManifestRaindex { address: Address::from_str("0x0000000000000000000000000000000000000001").unwrap(), dump_url: Url::parse("https://example.com/mainnet").unwrap(), end_block: 50, end_block_hash: Bytes::from_str("0x0def").unwrap(), end_block_time_ms: 2000, }; - let ob_polygon = ManifestOrderbook { + let ob_polygon = ManifestRaindex { address: Address::from_str("0x0000000000000000000000000000000000000002").unwrap(), dump_url: Url::parse("https://example.com/polygon").unwrap(), end_block: 60, @@ -453,9 +458,9 @@ mod tests { end_block_time_ms: 3000, }; - manifest.push_orderbook("mainnet", ob_main.clone()).unwrap(); + manifest.push_raindex("mainnet", ob_main.clone()).unwrap(); manifest - .push_orderbook("polygon", ob_polygon.clone()) + .push_raindex("polygon", ob_polygon.clone()) .unwrap(); let yaml_one = manifest.to_yaml_string().unwrap(); @@ -468,11 +473,11 @@ mod tests { } #[test] - fn test_push_orderbook_without_network_errors() { + fn test_push_raindex_without_network_errors() { let mut manifest = LocalDbManifest::new(); - let orderbook = sample_orderbook(); + let raindex = sample_raindex(); let err = manifest - .push_orderbook("missing", orderbook) + .push_raindex("missing", raindex) .expect_err("should error when network missing"); match err { YamlError::Field { @@ -530,18 +535,18 @@ mod tests { // OK header let yaml_ok = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let doc = load(yaml_ok); let (mv, sv) = parse_manifest_header(&doc, "manifest").expect("header parses"); assert_eq!(mv, 1); - assert_eq!(sv, 2); + assert_eq!(sv, 3); // Incompatible manifest version let yaml_bad = r#" manifest-version: 999 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_header(&load(yaml_bad), "manifest").unwrap_err(); @@ -579,11 +584,11 @@ networks: {} fn test_networks_helper_empty_key_rejected() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: "": chain-id: 1 - orderbooks: [] + raindexes: [] "#; let err = parse_networks(&load(yaml), "manifest").unwrap_err(); match err { @@ -599,10 +604,10 @@ networks: } #[test] - fn test_orderbook_helper_ok_and_bad_address() { + fn test_raindex_helper_ok_and_bad_address() { let base_loc = "manifest.networks.mainnet"; - // Valid orderbook + // Valid raindex let ob_ok = r#" address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com" @@ -610,10 +615,11 @@ end-block: 1 end-block-hash: "0x0abc" end-block-time-ms: 1 "#; - let ob_doc = load(ob_ok); - let ob = parse_single_orderbook(0, &ob_doc, base_loc).expect("orderbook parses"); - assert_eq!(ob.end_block, 1); - assert_eq!(ob.end_block_time_ms, 1); + let raindex_doc = load(ob_ok); + let raindex_entry = + parse_single_raindex(0, &raindex_doc, base_loc).expect("raindex parses"); + assert_eq!(raindex_entry.end_block, 1); + assert_eq!(raindex_entry.end_block_time_ms, 1); // Bad address let ob_bad = r#" @@ -623,14 +629,14 @@ end-block: 1 end-block-hash: "0x0abc" end-block-time-ms: 1 "#; - let err = parse_single_orderbook(0, &load(ob_bad), base_loc).unwrap_err(); + let err = parse_single_raindex(0, &load(ob_bad), base_loc).unwrap_err(); match err { YamlError::Field { kind: FieldErrorKind::InvalidValue { field, .. }, location, } => { assert_eq!(field, "address"); - assert_eq!(location, "manifest.networks.mainnet.orderbooks[0]"); + assert_eq!(location, "manifest.networks.mainnet.raindexes[0]"); } other => panic!("unexpected error: {other:?}"), } @@ -639,7 +645,7 @@ end-block-time-ms: 1 #[test] fn test_missing_manifest_version() { let yaml = r#" -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_doc(&load(yaml)).unwrap_err(); @@ -660,7 +666,7 @@ networks: {} fn test_missing_networks_defaults_to_empty() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 "#; let manifest = parse_manifest_doc(&load(yaml)).unwrap(); assert!(manifest.networks.is_empty()); @@ -690,7 +696,7 @@ networks: {} fn test_zero_or_invalid_manifest_and_schema_versions() { let yaml_zero_manifest = r#" manifest-version: 0 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_doc(&load(yaml_zero_manifest)).unwrap_err(); @@ -709,7 +715,7 @@ networks: {} fn test_network_missing_chain_id_and_invalid() { let yaml_missing = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: {} "#; @@ -718,21 +724,21 @@ networks: let yaml_zero = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 0 - orderbooks: [] + raindexes: [] "#; let err = parse_manifest_doc(&load(yaml_zero)).unwrap_err(); assert!(matches!(err, YamlError::Field { .. })); } #[test] - fn test_orderbooks_required_and_type() { + fn test_raindexes_required_and_type() { let yaml_missing = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 @@ -742,26 +748,26 @@ networks: let yaml_non_list = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: {} + raindexes: {} "#; let err = parse_manifest_doc(&load(yaml_non_list)).unwrap_err(); assert!(matches!(err, YamlError::Field { .. })); } #[test] - fn test_orderbook_missing_fields() { + fn test_raindex_missing_fields() { // Full, valid baseline let good = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com" end-block: 1 @@ -773,11 +779,11 @@ networks: // Now omit each required field individually let missing_address = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - dump-url: "http://example.com" end-block: 1 end-block-hash: "0x0abc" @@ -790,11 +796,11 @@ networks: let missing_dump = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" end-block: 1 end-block-hash: "0x0abc" @@ -807,11 +813,11 @@ networks: let missing_end_block = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com" end-block-hash: "0x0abc" @@ -824,11 +830,11 @@ networks: let missing_end_hash = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com" end-block: 1 @@ -841,11 +847,11 @@ networks: let missing_end_time = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com" end-block: 1 @@ -861,11 +867,11 @@ networks: fn test_find_across_networks_and_negatives() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x1111111111111111111111111111111111111111" dump-url: "http://example.com/a" end-block: 10 @@ -873,7 +879,7 @@ networks: end-block-time-ms: 100 other: chain-id: 2 - orderbooks: + raindexes: - address: "0x2222222222222222222222222222222222222222" dump-url: "http://example.com/b" end-block: 20 @@ -919,7 +925,7 @@ networks: fn test_incompatible_manifest_version_rejected() { let yaml = r#" manifest-version: 999 -db-schema-version: 2 +db-schema-version: 3 networks: {} "#; let err = parse_manifest_doc(&load(yaml)).unwrap_err(); @@ -939,11 +945,11 @@ networks: {} fn test_empty_network_key_is_rejected() { let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: "": chain-id: 1 - orderbooks: [] + raindexes: [] "#; let err = parse_manifest_doc(&load(yaml)).unwrap_err(); match err { diff --git a/crates/settings/src/order.rs b/crates/settings/src/order.rs index 2debcdc43d..09ddb579f2 100644 --- a/crates/settings/src/order.rs +++ b/crates/settings/src/order.rs @@ -9,7 +9,7 @@ use std::{ use strict_yaml_rust::{strict_yaml::Hash, StrictYaml}; use thiserror::Error; -const ALLOWED_ORDER_KEYS: [&str; 5] = ["inputs", "oracle-url", "orderbook", "outputs", "rainlang"]; +const ALLOWED_ORDER_KEYS: [&str; 5] = ["inputs", "oracle-url", "raindex", "outputs", "rainlang"]; const ALLOWED_ORDER_IO_KEYS: [&str; 2] = ["token", "vault-id"]; use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; use yaml::{ @@ -55,7 +55,7 @@ pub struct OrderCfg { #[cfg_attr(target_family = "wasm", tsify(optional))] pub rainlang: Option>, #[cfg_attr(target_family = "wasm", tsify(optional))] - pub orderbook: Option>, + pub raindex: Option>, #[cfg_attr(target_family = "wasm", tsify(optional))] #[serde(rename = "oracle-url")] pub oracle_url: Option, @@ -349,14 +349,13 @@ impl OrderCfg { } } - if let Some(orderbook_key) = optional_string(order_yaml, "orderbook") { - let key = - OrderbookCfg::parse_network_key(documents.clone(), &orderbook_key)?; + if let Some(raindex_key) = optional_string(order_yaml, "raindex") { + let key = RaindexCfg::parse_network_key(documents.clone(), &raindex_key)?; if let Some(ref existing_key) = network_key { if *existing_key != key { return Err(YamlError::ParseOrderConfigSourceError( - ParseOrderConfigSourceError::OrderbookNetworkDoesNotMatch { + ParseOrderConfigSourceError::RaindexNetworkDoesNotMatch { expected: existing_key.clone(), found: key.clone(), }, @@ -532,7 +531,7 @@ impl YamlParsableHash for OrderCfg { let mut orders = HashMap::new(); let rainlangs = RainlangCfg::parse_all_from_yaml(documents.clone(), context); - let orderbooks = OrderbookCfg::parse_all_from_yaml(documents.clone(), context); + let raindexes = RaindexCfg::parse_all_from_yaml(documents.clone(), context); let tokens = TokenCfg::parse_all_from_yaml(documents.clone(), context); let tokens = if let Some(context) = context { @@ -609,36 +608,36 @@ impl YamlParsableHash for OrderCfg { None => None, }; - let orderbook = match optional_string(order_yaml, "orderbook") { - Some(orderbook_name) => { - let orderbooks = orderbooks.as_ref().map_err(|e| YamlError::Field { + let raindex = match optional_string(order_yaml, "raindex") { + Some(raindex_name) => { + let raindexes = raindexes.as_ref().map_err(|e| YamlError::Field { kind: FieldErrorKind::InvalidValue { - field: "orderbooks".to_string(), + field: "raindexes".to_string(), reason: e.to_string(), }, location: "root".to_string(), })?; - let orderbook = Arc::new( - orderbooks - .get(&orderbook_name) + let raindex = Arc::new( + raindexes + .get(&raindex_name) .ok_or_else(|| { - YamlError::KeyNotFound(orderbook_name.to_string()) + YamlError::KeyNotFound(raindex_name.to_string()) })? .clone(), ); if let Some(n) = &network { - if orderbook.network != *n { + if raindex.network != *n { return Err(YamlError::ParseOrderConfigSourceError( - ParseOrderConfigSourceError::OrderbookNetworkDoesNotMatch { + ParseOrderConfigSourceError::RaindexNetworkDoesNotMatch { expected: n.key.clone(), - found: orderbook.network.key.clone(), + found: raindex.network.key.clone(), }, )); } } else { - network = Some(orderbook.network.clone()); + network = Some(raindex.network.clone()); } - Some(orderbook) + Some(raindex) } None => None, }; @@ -824,7 +823,7 @@ impl YamlParsableHash for OrderCfg { ParseOrderConfigSourceError::NetworkNotFoundError(String::new()), )?, rainlang, - orderbook, + raindex, oracle_url, }; @@ -934,7 +933,7 @@ impl Default for OrderCfg { outputs: vec![], network: Arc::new(NetworkCfg::default()), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, } } @@ -947,7 +946,7 @@ impl PartialEq for OrderCfg { && self.outputs == other.outputs && self.network == other.network && self.rainlang == other.rainlang - && self.orderbook == other.orderbook + && self.raindex == other.raindex && self.oracle_url == other.oracle_url } } @@ -956,8 +955,8 @@ impl PartialEq for OrderCfg { pub enum ParseOrderConfigSourceError { #[error("Failed to parse rainlang")] RainlangParseError(ParseRainlangConfigSourceError), - #[error("Failed to parse orderbook")] - OrderbookParseError(ParseOrderbookConfigSourceError), + #[error("Failed to parse raindex")] + RaindexParseError(ParseRaindexConfigSourceError), #[error("Failed to parse token")] TokenParseError(ParseTokenConfigSourceError), #[error("Network not found for Order: {0}")] @@ -966,8 +965,8 @@ pub enum ParseOrderConfigSourceError { NetworkNotMatch, #[error("Rainlang network does not match: expected {expected}, found {found}")] RainlangNetworkDoesNotMatch { expected: String, found: String }, - #[error("Orderbook network does not match: expected {expected}, found {found}")] - OrderbookNetworkDoesNotMatch { expected: String, found: String }, + #[error("Raindex network does not match: expected {expected}, found {found}")] + RaindexNetworkDoesNotMatch { expected: String, found: String }, #[error( "Input token network with key: {key} does not match: expected {expected}, found {found}" )] @@ -993,18 +992,18 @@ impl ParseOrderConfigSourceError { match self { ParseOrderConfigSourceError::RainlangParseError(err) => err.to_readable_msg(), - ParseOrderConfigSourceError::OrderbookParseError(err) => + ParseOrderConfigSourceError::RaindexParseError(err) => err.to_readable_msg(), ParseOrderConfigSourceError::TokenParseError(err) => err.to_readable_msg(), ParseOrderConfigSourceError::NetworkNotFoundError(_) => - "No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks.".to_string(), + "No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks.".to_string(), ParseOrderConfigSourceError::NetworkNotMatch => - "The networks specified in your order configuration do not match. All components (tokens, rainlangs, orderbooks) must use the same network.".to_string(), + "The networks specified in your order configuration do not match. All components (tokens, rainlangs, raindexes) must use the same network.".to_string(), ParseOrderConfigSourceError::RainlangNetworkDoesNotMatch { expected, found } => format!("Network mismatch in your YAML configuration: The rainlang is using network '{}' but the order is using network '{}'. Please ensure all components use the same network.", found, expected), - ParseOrderConfigSourceError::OrderbookNetworkDoesNotMatch { expected, found } => - format!("Network mismatch in your YAML configuration: The orderbook is using network '{}' but the order is using network '{}'. Please ensure all components use the same network.", found, expected), + ParseOrderConfigSourceError::RaindexNetworkDoesNotMatch { expected, found } => + format!("Network mismatch in your YAML configuration: The raindex is using network '{}' but the order is using network '{}'. Please ensure all components use the same network.", found, expected), ParseOrderConfigSourceError::InputTokenNetworkDoesNotMatch { key, expected, found } => format!("Network mismatch in your YAML configuration: The input token '{}' is using network '{}' but the order is using network '{}'. Please ensure all components use the same network.", key, found, expected), ParseOrderConfigSourceError::OutputTokenNetworkDoesNotMatch { key, expected, found } => @@ -1242,7 +1241,7 @@ orders: test ); assert_eq!( error.to_readable_msg(), - "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks." + "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks." ); let yaml = r#" @@ -1258,7 +1257,7 @@ orders: ); assert_eq!( error.to_readable_msg(), - "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks." + "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks." ); let yaml = r#" @@ -1274,7 +1273,7 @@ orders: ); assert_eq!( error.to_readable_msg(), - "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or orderbooks have valid networks." + "Order configuration error in your YAML: No network could be determined for this order. Please specify a network or ensure that tokens, rainlangs, or raindexes have valid networks." ); } @@ -1288,7 +1287,7 @@ orders: outputs: - token: usdc rainlang: mainnet - orderbook: mainnet + raindex: mainnet unknown-key: should-be-dropped another-unknown: also-dropped "#; @@ -1312,7 +1311,7 @@ orders: assert!(order_hash.contains_key(&StrictYaml::String("inputs".to_string()))); assert!(order_hash.contains_key(&StrictYaml::String("outputs".to_string()))); assert!(order_hash.contains_key(&StrictYaml::String("rainlang".to_string()))); - assert!(order_hash.contains_key(&StrictYaml::String("orderbook".to_string()))); + assert!(order_hash.contains_key(&StrictYaml::String("raindex".to_string()))); assert!(!order_hash.contains_key(&StrictYaml::String("unknown-key".to_string()))); assert!(!order_hash.contains_key(&StrictYaml::String("another-unknown".to_string()))); } diff --git a/crates/settings/src/orderbook.rs b/crates/settings/src/raindex.rs similarity index 65% rename from crates/settings/src/orderbook.rs rename to crates/settings/src/raindex.rs index ed5105a403..d09528b98f 100644 --- a/crates/settings/src/orderbook.rs +++ b/crates/settings/src/raindex.rs @@ -19,7 +19,7 @@ use yaml::{ default_document, optional_string, require_hash, require_string, YamlError, YamlParsableHash, }; -const ALLOWED_ORDERBOOK_KEYS: [&str; 6] = [ +const ALLOWED_RAINDEX_KEYS: [&str; 6] = [ "address", "deployment-block", "label", @@ -31,7 +31,7 @@ const ALLOWED_ORDERBOOK_KEYS: [&str; 6] = [ #[derive(Debug, Serialize, Deserialize, Clone)] #[cfg_attr(target_family = "wasm", derive(Tsify))] #[serde(rename_all = "camelCase")] -pub struct OrderbookCfg { +pub struct RaindexCfg { #[serde(skip, default = "default_document")] pub document: Arc>, pub key: String, @@ -46,48 +46,48 @@ pub struct OrderbookCfg { pub deployment_block: u64, } #[cfg(target_family = "wasm")] -impl_wasm_traits!(OrderbookCfg); +impl_wasm_traits!(RaindexCfg); -impl OrderbookCfg { - pub fn validate_address(address: &str) -> Result { - Address::from_str(address).map_err(ParseOrderbookConfigSourceError::AddressParseError) +impl RaindexCfg { + pub fn validate_address(address: &str) -> Result { + Address::from_str(address).map_err(ParseRaindexConfigSourceError::AddressParseError) } - pub fn validate_deployment_block(value: &str) -> Result { + pub fn validate_deployment_block(value: &str) -> Result { value .parse::() - .map_err(ParseOrderbookConfigSourceError::DeploymentBlockParseError) + .map_err(ParseRaindexConfigSourceError::DeploymentBlockParseError) } pub fn parse_network_key( documents: Vec>>, - orderbook_key: &str, + raindex_key: &str, ) -> Result { for document in &documents { let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; - if let Ok(orderbooks_hash) = require_hash(&document_read, Some("orderbooks"), None) { - if let Some(orderbook_yaml) = - orderbooks_hash.get(&StrictYaml::String(orderbook_key.to_string())) + if let Ok(raindex_hash) = require_hash(&document_read, Some("raindexes"), None) { + if let Some(raindex_yaml) = + raindex_hash.get(&StrictYaml::String(raindex_key.to_string())) { - return require_string(orderbook_yaml, Some("network"), None) - .or_else(|_| Ok(orderbook_key.to_string())); + return require_string(raindex_yaml, Some("network"), None) + .or_else(|_| Ok(raindex_key.to_string())); } } } Err(YamlError::Field { - kind: FieldErrorKind::Missing(format!("network for orderbook '{}'", orderbook_key)), + kind: FieldErrorKind::Missing(format!("network for raindex '{}'", raindex_key)), location: "root".to_string(), }) } } -impl YamlParsableHash for OrderbookCfg { +impl YamlParsableHash for RaindexCfg { fn parse_all_from_yaml( documents: Vec>>, context: Option<&Context>, ) -> Result, YamlError> { - let mut orderbooks = HashMap::new(); + let mut raindexes = HashMap::new(); let networks = NetworkCfg::parse_all_from_yaml(documents.clone(), context)?; let subgraphs = SubgraphCfg::parse_all_from_yaml(documents.clone(), context)?; @@ -96,14 +96,14 @@ impl YamlParsableHash for OrderbookCfg { for document in &documents { let document_read = document.read().map_err(|_| YamlError::ReadLockError)?; - if let Ok(orderbooks_hash) = require_hash(&document_read, Some("orderbooks"), None) { - for (key_yaml, orderbook_yaml) in orderbooks_hash { - let orderbook_key = key_yaml.as_str().unwrap_or_default().to_string(); - let location = format!("orderbook '{}'", orderbook_key); + if let Ok(raindex_hash) = require_hash(&document_read, Some("raindexes"), None) { + for (key_yaml, raindex_yaml) in raindex_hash { + let raindex_key = key_yaml.as_str().unwrap_or_default().to_string(); + let location = format!("raindex '{}'", raindex_key); let address_str = - require_string(orderbook_yaml, Some("address"), Some(location.clone()))?; - let address = OrderbookCfg::validate_address(&address_str).map_err(|e| { + require_string(raindex_yaml, Some("address"), Some(location.clone()))?; + let address = RaindexCfg::validate_address(&address_str).map_err(|e| { YamlError::Field { kind: FieldErrorKind::InvalidValue { field: "address".to_string(), @@ -113,9 +113,9 @@ impl YamlParsableHash for OrderbookCfg { } })?; - let network_name = match optional_string(orderbook_yaml, "network") { + let network_name = match optional_string(raindex_yaml, "network") { Some(network_name) => network_name, - None => orderbook_key.clone(), + None => raindex_key.clone(), }; let network = networks .get(&network_name) @@ -127,9 +127,9 @@ impl YamlParsableHash for OrderbookCfg { location: location.clone(), })?; - let subgraph_name = match optional_string(orderbook_yaml, "subgraph") { + let subgraph_name = match optional_string(raindex_yaml, "subgraph") { Some(subgraph_name) => subgraph_name, - None => orderbook_key.clone(), + None => raindex_key.clone(), }; let subgraph = subgraphs @@ -142,22 +142,22 @@ impl YamlParsableHash for OrderbookCfg { location: location.clone(), })?; - let label = optional_string(orderbook_yaml, "label"); + let label = optional_string(raindex_yaml, "label"); - let local_db_remote_name = optional_string(orderbook_yaml, "local-db-remote"); + let local_db_remote_name = optional_string(raindex_yaml, "local-db-remote"); let local_db_remote = if let Some(name) = local_db_remote_name { local_db_remotes.get(&name).cloned() } else { - local_db_remotes.get(&orderbook_key).cloned() + local_db_remotes.get(&raindex_key).cloned() } .map(Arc::new); let deployment_block_str = require_string( - orderbook_yaml, + raindex_yaml, Some("deployment-block"), Some(location.clone()), )?; - let deployment_block = OrderbookCfg::validate_deployment_block( + let deployment_block = RaindexCfg::validate_deployment_block( &deployment_block_str, ) .map_err(|e| YamlError::Field { @@ -168,9 +168,9 @@ impl YamlParsableHash for OrderbookCfg { location: location.clone(), })?; - let orderbook = OrderbookCfg { + let raindex_entry = RaindexCfg { document: document.clone(), - key: orderbook_key.clone(), + key: raindex_key.clone(), address, network: Arc::new(network.clone()), subgraph: Arc::new(subgraph.clone()), @@ -179,25 +179,25 @@ impl YamlParsableHash for OrderbookCfg { deployment_block, }; - if orderbooks.contains_key(&orderbook_key) { + if raindexes.contains_key(&raindex_key) { return Err(YamlError::KeyShadowing( - orderbook_key, - "orderbooks".to_string(), + raindex_key, + "raindexes".to_string(), )); } - orderbooks.insert(orderbook_key, orderbook); + raindexes.insert(raindex_key, raindex_entry); } } } - if orderbooks.is_empty() { + if raindexes.is_empty() { return Err(YamlError::Field { - kind: FieldErrorKind::Missing("orderbooks".to_string()), + kind: FieldErrorKind::Missing("raindexes".to_string()), location: "root".to_string(), }); } - Ok(orderbooks) + Ok(raindexes) } fn sanitize_documents(documents: &[Arc>]) -> Result<(), YamlError> { @@ -207,55 +207,55 @@ impl YamlParsableHash for OrderbookCfg { continue; }; - let orderbooks_key = StrictYaml::String("orderbooks".to_string()); - let Some(orderbooks_value) = root_hash.get(&orderbooks_key) else { + let raindex_section_key = StrictYaml::String("raindexes".to_string()); + let Some(raindex_value) = root_hash.get(&raindex_section_key) else { continue; }; - let StrictYaml::Hash(ref orderbooks_hash) = *orderbooks_value else { + let StrictYaml::Hash(ref raindex_hash) = *raindex_value else { continue; }; - let mut sanitized_orderbooks: Vec<(String, StrictYaml)> = Vec::new(); + let mut sanitized_raindex_entries: Vec<(String, StrictYaml)> = Vec::new(); - for (orderbook_key, orderbook_value) in orderbooks_hash { - let Some(orderbook_key_str) = orderbook_key.as_str() else { + for (raindex_key, raindex_value) in raindex_hash { + let Some(raindex_key_str) = raindex_key.as_str() else { continue; }; - let StrictYaml::Hash(ref orderbook_hash) = *orderbook_value else { + let StrictYaml::Hash(ref raindex_entry_hash) = *raindex_value else { continue; }; - let mut sanitized_orderbook = Hash::new(); + let mut sanitized_raindex = Hash::new(); - for allowed_key in ALLOWED_ORDERBOOK_KEYS.iter() { + for allowed_key in ALLOWED_RAINDEX_KEYS.iter() { let key_yaml = StrictYaml::String(allowed_key.to_string()); - if let Some(v) = orderbook_hash.get(&key_yaml) { - sanitized_orderbook.insert(key_yaml, v.clone()); + if let Some(v) = raindex_entry_hash.get(&key_yaml) { + sanitized_raindex.insert(key_yaml, v.clone()); } } - sanitized_orderbooks.push(( - orderbook_key_str.to_string(), - StrictYaml::Hash(sanitized_orderbook), + sanitized_raindex_entries.push(( + raindex_key_str.to_string(), + StrictYaml::Hash(sanitized_raindex), )); } - sanitized_orderbooks.sort_by(|(a, _), (b, _)| a.cmp(b)); + sanitized_raindex_entries.sort_by(|(a, _), (b, _)| a.cmp(b)); - let mut new_orderbooks_hash = Hash::new(); - for (key, value) in sanitized_orderbooks { - new_orderbooks_hash.insert(StrictYaml::String(key), value); + let mut new_raindex_hash = Hash::new(); + for (key, value) in sanitized_raindex_entries { + new_raindex_hash.insert(StrictYaml::String(key), value); } - root_hash.insert(orderbooks_key, StrictYaml::Hash(new_orderbooks_hash)); + root_hash.insert(raindex_section_key, StrictYaml::Hash(new_raindex_hash)); } Ok(()) } } -impl Default for OrderbookCfg { +impl Default for RaindexCfg { fn default() -> Self { Self { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), @@ -269,7 +269,7 @@ impl Default for OrderbookCfg { } } } -impl PartialEq for OrderbookCfg { +impl PartialEq for RaindexCfg { fn eq(&self, other: &Self) -> bool { self.key == other.key && self.address == other.address @@ -282,10 +282,10 @@ impl PartialEq for OrderbookCfg { } #[derive(Error, Debug, PartialEq)] -pub enum ParseOrderbookConfigSourceError { +pub enum ParseRaindexConfigSourceError { #[error("Failed to parse address")] AddressParseError(FromHexError), - #[error("Network not found for Orderbook: {0}")] + #[error("Network not found for Raindex: {0}")] NetworkNotFoundError(String), #[error("Subgraph not found: {0}")] SubgraphNotFoundError(String), @@ -293,17 +293,17 @@ pub enum ParseOrderbookConfigSourceError { DeploymentBlockParseError(ParseIntError), } -impl ParseOrderbookConfigSourceError { +impl ParseRaindexConfigSourceError { pub fn to_readable_msg(&self) -> String { match self { - ParseOrderbookConfigSourceError::AddressParseError(err) => - format!("The orderbook address in your YAML configuration is invalid. Please provide a valid EVM address: {}", err), - ParseOrderbookConfigSourceError::NetworkNotFoundError(network) => - format!("The network '{}' specified for this orderbook was not found in your YAML configuration. Please define this network or use an existing one.", network), - ParseOrderbookConfigSourceError::SubgraphNotFoundError(subgraph) => - format!("The subgraph '{}' specified for this orderbook was not found in your YAML configuration. Please define this subgraph or use an existing one.", subgraph), - ParseOrderbookConfigSourceError::DeploymentBlockParseError(err) => - format!("The deployment block in your orderbook configuration must be a valid number: {}", err), + ParseRaindexConfigSourceError::AddressParseError(err) => + format!("The raindex address in your YAML configuration is invalid. Please provide a valid EVM address: {}", err), + ParseRaindexConfigSourceError::NetworkNotFoundError(network) => + format!("The network '{}' specified for this raindex was not found in your YAML configuration. Please define this network or use an existing one.", network), + ParseRaindexConfigSourceError::SubgraphNotFoundError(subgraph) => + format!("The subgraph '{}' specified for this raindex was not found in your YAML configuration. Please define this subgraph or use an existing one.", subgraph), + ParseRaindexConfigSourceError::DeploymentBlockParseError(err) => + format!("The deployment block in your raindex configuration must be a valid number: {}", err), } } } @@ -314,11 +314,11 @@ mod tests { use crate::yaml::tests::get_document; #[test] - fn test_parse_orderbooks_from_yaml() { + fn test_parse_raindexes_from_yaml() { let yaml = r#" test: test "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -339,7 +339,7 @@ networks: chain-id: 1 test: test "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -362,17 +362,17 @@ subgraphs: SomeSubgraph: https://subgraph.com test: test "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("orderbooks".to_string()), + kind: FieldErrorKind::Missing("raindexes".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'orderbooks' in root" + "Missing required field 'raindexes' in root" ); let yaml = r#" @@ -383,20 +383,20 @@ networks: chain-id: 1 subgraphs: SomeSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { kind: FieldErrorKind::Missing("address".to_string()), - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'address' in orderbook 'TestOrderbook'" + "Missing required field 'address' in raindex 'TestRaindex'" ); let yaml = r#" @@ -407,12 +407,12 @@ networks: chain-id: 1 subgraphs: SomeSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -420,10 +420,10 @@ orderbooks: field: "network".to_string(), reason: "Network 'TestNetwork' not found".to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); - assert_eq!(error.to_readable_msg(), "Invalid value for field 'network' in orderbook 'TestOrderbook': Network 'TestNetwork' not found"); + assert_eq!(error.to_readable_msg(), "Invalid value for field 'network' in raindex 'TestRaindex': Network 'TestNetwork' not found"); let yaml = r#" networks: @@ -433,15 +433,15 @@ networks: chain-id: 1 subgraphs: SomeSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 12345 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -449,14 +449,14 @@ orderbooks: field: "subgraph".to_string(), reason: "Subgraph 'TestSubgraph' not found".to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); - assert_eq!(error.to_readable_msg(), "Invalid value for field 'subgraph' in orderbook 'TestOrderbook': Subgraph 'TestSubgraph' not found"); + assert_eq!(error.to_readable_msg(), "Invalid value for field 'subgraph' in raindex 'TestRaindex': Subgraph 'TestSubgraph' not found"); } #[test] - fn test_parse_orderbooks_from_yaml_multiple_files() { + fn test_parse_raindexes_from_yaml_multiple_files() { let yaml_one = r#" networks: TestNetwork: @@ -465,8 +465,8 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - OrderbookOne: +raindexes: + RaindexOne: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph @@ -474,8 +474,8 @@ orderbooks: deployment-block: 12345 "#; let yaml_two = r#" -orderbooks: - OrderbookTwo: +raindexes: + RaindexTwo: address: 0x0987654321098765432109876543210987654321 network: TestNetwork subgraph: TestSubgraph @@ -484,24 +484,24 @@ orderbooks: "#; let documents = vec![get_document(yaml_one), get_document(yaml_two)]; - let orderbooks = OrderbookCfg::parse_all_from_yaml(documents, None).unwrap(); + let raindexes = RaindexCfg::parse_all_from_yaml(documents, None).unwrap(); - assert_eq!(orderbooks.len(), 2); - assert!(orderbooks.contains_key("OrderbookOne")); - assert!(orderbooks.contains_key("OrderbookTwo")); + assert_eq!(raindexes.len(), 2); + assert!(raindexes.contains_key("RaindexOne")); + assert!(raindexes.contains_key("RaindexTwo")); assert_eq!( - orderbooks.get("OrderbookOne").unwrap().address.to_string(), + raindexes.get("RaindexOne").unwrap().address.to_string(), "0x1234567890123456789012345678901234567890" ); assert_eq!( - orderbooks.get("OrderbookTwo").unwrap().address.to_string(), + raindexes.get("RaindexTwo").unwrap().address.to_string(), "0x0987654321098765432109876543210987654321" ); } #[test] - fn test_parse_orderbooks_from_yaml_duplicate_key() { + fn test_parse_raindexes_from_yaml_duplicate_key() { let yaml_one = r#" networks: TestNetwork: @@ -510,8 +510,8 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - DuplicateOrderbook: +raindexes: + DuplicateRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph @@ -519,8 +519,8 @@ orderbooks: deployment-block: 12345 "#; let yaml_two = r#" -orderbooks: - DuplicateOrderbook: +raindexes: + DuplicateRaindex: address: 0x0987654321098765432109876543210987654321 network: TestNetwork subgraph: TestSubgraph @@ -529,17 +529,17 @@ orderbooks: "#; let documents = vec![get_document(yaml_one), get_document(yaml_two)]; - let error = OrderbookCfg::parse_all_from_yaml(documents, None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(documents, None).unwrap_err(); assert_eq!( error, - YamlError::KeyShadowing("DuplicateOrderbook".to_string(), "orderbooks".to_string()) + YamlError::KeyShadowing("DuplicateRaindex".to_string(), "raindexes".to_string()) ); - assert_eq!(error.to_readable_msg(), "The key 'DuplicateOrderbook' is defined multiple times in your YAML configuration at orderbooks"); + assert_eq!(error.to_readable_msg(), "The key 'DuplicateRaindex' is defined multiple times in your YAML configuration at raindexes"); } #[test] - fn test_parse_orderbook_from_yaml_network_key() { + fn test_parse_raindex_from_yaml_network_key() { let yaml = r#" networks: mainnet: @@ -548,7 +548,7 @@ networks: chain-id: 1 subgraphs: mainnet: https://subgraph.com -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -557,7 +557,7 @@ orderbooks: "#; let documents = vec![get_document(yaml)]; - let network_key = OrderbookCfg::parse_network_key(documents, "mainnet").unwrap(); + let network_key = RaindexCfg::parse_network_key(documents, "mainnet").unwrap(); assert_eq!(network_key, "mainnet"); let yaml = r#" @@ -568,70 +568,67 @@ networks: chain-id: 1 subgraphs: mainnet: https://subgraph.com -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 deployment-block: 12345 local-db-remote: mainnet "#; let documents = vec![get_document(yaml)]; - let network_key = OrderbookCfg::parse_network_key(documents, "mainnet").unwrap(); + let network_key = RaindexCfg::parse_network_key(documents, "mainnet").unwrap(); assert_eq!(network_key, "mainnet"); } #[test] fn test_parse_network_key() { let yaml = r#" -orderbooks: test +raindexes: test "#; - let error = - OrderbookCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + let error = RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("network for orderbook 'order1'".to_string()), + kind: FieldErrorKind::Missing("network for raindex 'order1'".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'network for orderbook 'order1'' in root" + "Missing required field 'network for raindex 'order1'' in root" ); let yaml = r#" -orderbooks: +raindexes: - test "#; - let error = - OrderbookCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + let error = RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("network for orderbook 'order1'".to_string()), + kind: FieldErrorKind::Missing("network for raindex 'order1'".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'network for orderbook 'order1'' in root" + "Missing required field 'network for raindex 'order1'' in root" ); let yaml = r#" -orderbooks: +raindexes: - test: test "#; - let error = - OrderbookCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); + let error = RaindexCfg::parse_network_key(vec![get_document(yaml)], "order1").unwrap_err(); assert_eq!( error, YamlError::Field { - kind: FieldErrorKind::Missing("network for orderbook 'order1'".to_string()), + kind: FieldErrorKind::Missing("network for raindex 'order1'".to_string()), location: "root".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'network for orderbook 'order1'' in root" + "Missing required field 'network for raindex 'order1'' in root" ); } @@ -645,24 +642,24 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { kind: FieldErrorKind::Missing("deployment-block".to_string()), - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); assert_eq!( error.to_readable_msg(), - "Missing required field 'deployment-block' in orderbook 'TestOrderbook'" + "Missing required field 'deployment-block' in raindex 'TestRaindex'" ); } @@ -676,38 +673,35 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook1: +raindexes: + TestRaindex1: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 0 - TestOrderbook2: + TestRaindex2: address: 0x0987654321098765432109876543210987654321 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 18446744073709551615 - TestOrderbook3: + TestRaindex3: address: 0x1111111111111111111111111111111111111111 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 12345678 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - assert_eq!(orderbooks.len(), 3); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + assert_eq!(raindexes.len(), 3); + assert_eq!(raindexes.get("TestRaindex1").unwrap().deployment_block, 0); assert_eq!( - orderbooks.get("TestOrderbook1").unwrap().deployment_block, - 0 - ); - assert_eq!( - orderbooks.get("TestOrderbook2").unwrap().deployment_block, + raindexes.get("TestRaindex2").unwrap().deployment_block, 18446744073709551615 ); assert_eq!( - orderbooks.get("TestOrderbook3").unwrap().deployment_block, + raindexes.get("TestRaindex3").unwrap().deployment_block, 12345678 ); } @@ -722,15 +716,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: -1 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -739,7 +733,7 @@ orderbooks: reason: "Failed to parse deployment block: invalid digit found in string" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } @@ -754,15 +748,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 18446744073709551616 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -772,7 +766,7 @@ orderbooks: "Failed to parse deployment block: number too large to fit in target type" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } @@ -787,15 +781,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: abc123 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -804,7 +798,7 @@ orderbooks: reason: "Failed to parse deployment block: invalid digit found in string" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } @@ -819,15 +813,15 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 123.45 "#; - let error = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); + let error = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap_err(); assert_eq!( error, YamlError::Field { @@ -836,13 +830,13 @@ orderbooks: reason: "Failed to parse deployment block: invalid digit found in string" .to_string(), }, - location: "orderbook 'TestOrderbook'".to_string(), + location: "raindex 'TestRaindex'".to_string(), } ); } #[test] - fn test_orderbook_local_db_remote_absent_defaults_to_orderbook_key() { + fn test_raindex_local_db_remote_absent_defaults_to_raindex_key() { let yaml = r#" networks: TestNetwork: @@ -852,26 +846,29 @@ networks: subgraphs: TestSubgraph: https://subgraph.com local-db-remotes: - TestOrderbook: https://example.com/localdb/TestOrderbook -orderbooks: - TestOrderbook: + TestRaindex: https://example.com/localdb/TestRaindex +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); - let remote = ob.local_db_remote.as_ref().expect("expected remote"); - assert_eq!(remote.key, "TestOrderbook"); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + let remote = raindex_cfg + .local_db_remote + .as_ref() + .expect("expected remote"); + assert_eq!(remote.key, "TestRaindex"); assert_eq!( remote.url.to_string(), - "https://example.com/localdb/TestOrderbook" + "https://example.com/localdb/TestRaindex" ); } #[test] - fn test_orderbook_local_db_remote_resolves() { + fn test_raindex_local_db_remote_resolves() { let yaml = r#" networks: TestNetwork: @@ -882,17 +879,20 @@ subgraphs: TestSubgraph: https://subgraph.com local-db-remotes: mainnet: https://example.com/localdb/mainnet -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: mainnet deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); - let remote = ob.local_db_remote.as_ref().expect("expected remote"); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + let remote = raindex_cfg + .local_db_remote + .as_ref() + .expect("expected remote"); assert_eq!(remote.key, "mainnet"); assert_eq!( remote.url.to_string(), @@ -901,7 +901,7 @@ orderbooks: } #[test] - fn test_orderbook_local_db_remote_not_found() { + fn test_raindex_local_db_remote_not_found() { let yaml = r#" networks: TestNetwork: @@ -910,17 +910,17 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: missing deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); - assert!(ob.local_db_remote.is_none()); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + assert!(raindex_cfg.local_db_remote.is_none()); let yaml = r#" networks: @@ -930,23 +930,23 @@ networks: chain-id: 1 subgraphs: TestSubgraph: https://subgraph.com -orderbooks: - TestOrderbook: +raindexes: + TestRaindex: address: 0x1234567890123456789012345678901234567890 network: TestNetwork subgraph: TestSubgraph local-db-remote: missing deployment-block: 123 "#; - let orderbooks = OrderbookCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); - let ob = orderbooks.get("TestOrderbook").unwrap(); - assert!(ob.local_db_remote.is_none()); + let raindexes = RaindexCfg::parse_all_from_yaml(vec![get_document(yaml)], None).unwrap(); + let raindex_cfg = raindexes.get("TestRaindex").unwrap(); + assert!(raindex_cfg.local_db_remote.is_none()); } #[test] fn test_sanitize_drops_unknown_keys() { let yaml = r#" -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -956,16 +956,16 @@ orderbooks: another-unknown: also-removed "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let mainnet = orderbooks + let mainnet = raindexes .get(&StrictYaml::String("mainnet".to_string())) .unwrap() .as_hash() @@ -982,26 +982,26 @@ orderbooks: #[test] fn test_sanitize_preserves_all_allowed_keys() { let yaml = r#" -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet subgraph: mainnet local-db-remote: mainnet - label: Mainnet Orderbook + label: Mainnet Raindex deployment-block: 12345 "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let mainnet = orderbooks + let mainnet = raindexes .get(&StrictYaml::String("mainnet".to_string())) .unwrap() .as_hash() @@ -1027,7 +1027,7 @@ orderbooks: ); assert_eq!( mainnet.get(&StrictYaml::String("label".to_string())), - Some(&StrictYaml::String("Mainnet Orderbook".to_string())) + Some(&StrictYaml::String("Mainnet Raindex".to_string())) ); assert_eq!( mainnet.get(&StrictYaml::String("deployment-block".to_string())), @@ -1036,33 +1036,33 @@ orderbooks: } #[test] - fn test_sanitize_drops_non_hash_orderbook_entries() { + fn test_sanitize_drops_non_hash_raindex_entries() { let yaml = r#" -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 deployment-block: 12345 invalid-string: just-a-string "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - assert!(orderbooks.contains_key(&StrictYaml::String("mainnet".to_string()))); - assert!(!orderbooks.contains_key(&StrictYaml::String("invalid-string".to_string()))); + assert!(raindexes.contains_key(&StrictYaml::String("mainnet".to_string()))); + assert!(!raindexes.contains_key(&StrictYaml::String("invalid-string".to_string()))); } #[test] - fn test_sanitize_sorts_orderbooks_lexicographically() { + fn test_sanitize_sorts_raindexes_lexicographically() { let yaml = r#" -orderbooks: +raindexes: zebra: address: 0x1111111111111111111111111111111111111111 deployment-block: 1 @@ -1074,22 +1074,22 @@ orderbooks: deployment-block: 3 "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let keys: Vec<_> = orderbooks.keys().map(|k| k.as_str().unwrap()).collect(); + let keys: Vec<_> = raindexes.keys().map(|k| k.as_str().unwrap()).collect(); assert_eq!(keys, vec!["alpha", "mainnet", "zebra"]); } #[test] - fn test_sanitize_handles_missing_orderbooks_section() { + fn test_sanitize_handles_missing_raindexes_section() { let yaml = r#" networks: mainnet: @@ -1098,50 +1098,50 @@ networks: chain-id: 1 "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - assert!(!root.contains_key(&StrictYaml::String("orderbooks".to_string()))); + assert!(!root.contains_key(&StrictYaml::String("raindexes".to_string()))); } #[test] fn test_sanitize_handles_non_hash_root() { let yaml = r#"just-a-string"#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); assert!(doc_read.as_str().is_some()); } #[test] - fn test_sanitize_skips_non_hash_orderbooks_section() { + fn test_sanitize_skips_non_hash_raindexes_section() { let yaml = r#" -orderbooks: not-a-hash +raindexes: not-a-hash "#; let doc = get_document(yaml); - OrderbookCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); + RaindexCfg::sanitize_documents(std::slice::from_ref(&doc)).unwrap(); let doc_read = doc.read().unwrap(); let root = doc_read.as_hash().unwrap(); - let orderbooks = root - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes = root + .get(&StrictYaml::String("raindexes".to_string())) .unwrap(); - assert_eq!(orderbooks.as_str(), Some("not-a-hash")); + assert_eq!(raindexes.as_str(), Some("not-a-hash")); } #[test] fn test_sanitize_per_document_isolation() { let yaml1 = r#" -orderbooks: +raindexes: from-doc1: address: 0x1111111111111111111111111111111111111111 deployment-block: 1 extra-key: removed "#; let yaml2 = r#" -orderbooks: +raindexes: from-doc2: address: 0x2222222222222222222222222222222222222222 deployment-block: 2 @@ -1150,36 +1150,36 @@ orderbooks: let doc1 = get_document(yaml1); let doc2 = get_document(yaml2); - OrderbookCfg::sanitize_documents(&[doc1.clone(), doc2.clone()]).unwrap(); + RaindexCfg::sanitize_documents(&[doc1.clone(), doc2.clone()]).unwrap(); let doc1_read = doc1.read().unwrap(); let root1 = doc1_read.as_hash().unwrap(); - let orderbooks1 = root1 - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes1 = root1 + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let from_doc1 = orderbooks1 + let from_doc1 = raindexes1 .get(&StrictYaml::String("from-doc1".to_string())) .unwrap() .as_hash() .unwrap(); assert!(!from_doc1.contains_key(&StrictYaml::String("extra-key".to_string()))); - assert!(!orderbooks1.contains_key(&StrictYaml::String("from-doc2".to_string()))); + assert!(!raindexes1.contains_key(&StrictYaml::String("from-doc2".to_string()))); let doc2_read = doc2.read().unwrap(); let root2 = doc2_read.as_hash().unwrap(); - let orderbooks2 = root2 - .get(&StrictYaml::String("orderbooks".to_string())) + let raindexes2 = root2 + .get(&StrictYaml::String("raindexes".to_string())) .unwrap() .as_hash() .unwrap(); - let from_doc2 = orderbooks2 + let from_doc2 = raindexes2 .get(&StrictYaml::String("from-doc2".to_string())) .unwrap() .as_hash() .unwrap(); assert!(!from_doc2.contains_key(&StrictYaml::String("another-extra".to_string()))); - assert!(!orderbooks2.contains_key(&StrictYaml::String("from-doc1".to_string()))); + assert!(!raindexes2.contains_key(&StrictYaml::String("from-doc1".to_string()))); } } diff --git a/crates/settings/src/remote/manifest.rs b/crates/settings/src/remote/manifest.rs index f689cfe892..499d55a06f 100644 --- a/crates/settings/src/remote/manifest.rs +++ b/crates/settings/src/remote/manifest.rs @@ -56,11 +56,11 @@ mod tests { let server = MockServer::start_async().await; let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com/dump1" end-block: 123 @@ -82,20 +82,20 @@ networks: .unwrap(); assert_eq!(manifest.manifest_version, 1); - assert_eq!(manifest.db_schema_version, 2); + assert_eq!(manifest.db_schema_version, 3); let net = manifest.networks.get("mainnet").unwrap(); assert_eq!(net.chain_id, 1); - assert_eq!(net.orderbooks.len(), 1); + assert_eq!(net.raindexes.len(), 1); assert_eq!( - net.orderbooks[0].address, + net.raindexes[0].address, address!("0x0000000000000000000000000000000000000001") ); - assert_eq!(net.orderbooks[0].end_block, 123); + assert_eq!(net.raindexes[0].end_block, 123); assert_eq!( - net.orderbooks[0].end_block_hash, + net.raindexes[0].end_block_hash, Bytes::from_str("0x0abc").unwrap() ); - assert_eq!(net.orderbooks[0].end_block_time_ms, 1000); + assert_eq!(net.raindexes[0].end_block_time_ms, 1000); // find helper let found = manifest.find(1, address!("0x0000000000000000000000000000000000000001")); @@ -107,19 +107,19 @@ networks: let server = MockServer::start_async().await; let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 extra-root: ignored networks: goerli: chain-id: 5 extra: ignored - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000002" dump-url: "http://example.com/dump2" end-block: 555 end-block-hash: "0x0def" end-block-time-ms: 2000 - extra-ob: ignored + extra-raindex: ignored "#; server @@ -136,7 +136,7 @@ networks: assert!(manifest.networks.contains_key("goerli")); let net = manifest.networks.get("goerli").unwrap(); assert_eq!(net.chain_id, 5); - assert_eq!(net.orderbooks.len(), 1); + assert_eq!(net.raindexes.len(), 1); } #[tokio::test] @@ -169,11 +169,11 @@ networks: let server = MockServer::start_async().await; let yaml = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: 123 # invalid type dump-url: "not-a-url" end-block: 0 @@ -215,11 +215,11 @@ networks: let yaml_one = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: mainnet: chain-id: 1 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000001" dump-url: "http://example.com/dump1" end-block: 123 @@ -229,11 +229,11 @@ networks: let yaml_two = r#" manifest-version: 1 -db-schema-version: 2 +db-schema-version: 3 networks: goerli: chain-id: 5 - orderbooks: + raindexes: - address: "0x0000000000000000000000000000000000000002" dump-url: "http://example.com/dump2" end-block: 555 diff --git a/crates/settings/src/scenario.rs b/crates/settings/src/scenario.rs index dd705643e9..8bbe0bcf32 100644 --- a/crates/settings/src/scenario.rs +++ b/crates/settings/src/scenario.rs @@ -517,8 +517,8 @@ pub enum ParseScenarioConfigSourceError { ParentRainlangShadowedError(String), #[error("Rainlang not found: {0}")] RainlangNotFound(String), - #[error("Parent orderbook shadowed by child: {0}")] - ParentOrderbookShadowedError(String), + #[error("Parent raindex shadowed by child: {0}")] + ParentRaindexShadowedError(String), #[error("Failed to parse blocks: {0}")] BlocksParseError(String), } @@ -534,8 +534,8 @@ impl ParseScenarioConfigSourceError { format!("Rainlang conflict in your YAML configuration: The child scenario is trying to use rainlang '{}' which differs from the rainlang specified in the parent scenario. Child scenarios must use the same rainlang as their parent.", rainlang), ParseScenarioConfigSourceError::RainlangNotFound(scenario) => format!("No rainlang was found for scenario '{}' in your YAML configuration. Please specify a rainlang for this scenario or ensure it inherits one from a parent scenario.", scenario), - ParseScenarioConfigSourceError::ParentOrderbookShadowedError(orderbook) => - format!("Orderbook conflict in your YAML configuration: The child scenario is trying to use orderbook '{}' which differs from the orderbook specified in the parent scenario. Child scenarios must use the same orderbook as their parent.", orderbook), + ParseScenarioConfigSourceError::ParentRaindexShadowedError(raindex) => + format!("Raindex conflict in your YAML configuration: The child scenario is trying to use raindex '{}' which differs from the raindex specified in the parent scenario. Child scenarios must use the same raindex as their parent.", raindex), ParseScenarioConfigSourceError::BlocksParseError(blocks) => format!("Failed to parse the 'blocks' configuration in your YAML: {}. Please ensure it follows the correct format.", blocks), } diff --git a/crates/settings/src/spec_version.rs b/crates/settings/src/spec_version.rs index 335afc962c..59d8d0c904 100644 --- a/crates/settings/src/spec_version.rs +++ b/crates/settings/src/spec_version.rs @@ -5,7 +5,7 @@ use strict_yaml_rust::StrictYaml; #[derive(Clone, Debug)] pub struct SpecVersion; -pub const CURRENT_SPEC_VERSION: &str = "5"; +pub const CURRENT_SPEC_VERSION: &str = "6"; impl SpecVersion { pub fn current() -> String { @@ -90,13 +90,13 @@ mod tests { #[test] fn test_is_current() { - assert!(SpecVersion::is_current("5")); + assert!(SpecVersion::is_current("6")); assert!(!SpecVersion::is_current("1")); } #[test] fn test_current() { - assert_eq!(SpecVersion::current(), "5"); + assert_eq!(SpecVersion::current(), "6"); } #[test] diff --git a/crates/settings/src/test.rs b/crates/settings/src/test.rs index 75517d5b7a..559e317600 100644 --- a/crates/settings/src/test.rs +++ b/crates/settings/src/test.rs @@ -28,12 +28,12 @@ pub fn mock_rainlang() -> Arc { }) } -// Helper function to create a mock orderbook -pub fn mock_orderbook() -> Arc { - Arc::new(OrderbookCfg { +// Helper function to create a mock raindex +pub fn mock_raindex() -> Arc { + Arc::new(RaindexCfg { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), key: "".to_string(), - label: Some("Orderbook1".into()), + label: Some("Raindex1".into()), address: Address::repeat_byte(0x04), subgraph: Arc::new(SubgraphCfg { document: Arc::new(RwLock::new(StrictYaml::String("".to_string()))), diff --git a/crates/settings/src/yaml/context.rs b/crates/settings/src/yaml/context.rs index 3460a30f01..7906540d26 100644 --- a/crates/settings/src/yaml/context.rs +++ b/crates/settings/src/yaml/context.rs @@ -434,7 +434,7 @@ mod tests { }], network: mock_network(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }) } @@ -451,7 +451,7 @@ mod tests { outputs: vec![], network: mock_network(), rainlang: None, - orderbook: None, + raindex: None, oracle_url: None, }) } @@ -586,7 +586,7 @@ mod tests { }], network: mock_network(), rainlang: Some(mock_rainlang()), - orderbook: Some(mock_orderbook()), + raindex: Some(mock_raindex()), oracle_url: None, }; context.add_order(Arc::new(order)); @@ -602,7 +602,7 @@ mod tests { assert_eq!(context_order.outputs[0].vault_id, None); assert_eq!(context_order.network, mock_network()); assert_eq!(context_order.rainlang, Some(mock_rainlang())); - assert_eq!(context_order.orderbook, Some(mock_orderbook())); + assert_eq!(context_order.raindex, Some(mock_raindex())); } #[test] diff --git a/crates/settings/src/yaml/dotrain.rs b/crates/settings/src/yaml/dotrain.rs index 4c1456e795..aee2dd7d36 100644 --- a/crates/settings/src/yaml/dotrain.rs +++ b/crates/settings/src/yaml/dotrain.rs @@ -1,4 +1,4 @@ -use super::{cache::Cache, orderbook::OrderbookYaml, sanitize_all_documents, ValidationConfig, *}; +use super::{cache::Cache, raindex::RaindexYaml, sanitize_all_documents, ValidationConfig, *}; use crate::{spec_version::SpecVersion, ChartCfg, DeploymentCfg, GuiCfg, OrderCfg, ScenarioCfg}; use serde::{ de::{self, IgnoredAny, MapAccess, SeqAccess, Visitor}, @@ -61,7 +61,7 @@ impl ValidationConfig for DotrainYamlValidation { fn should_validate_local_db_sync(&self) -> bool { false } - fn should_validate_orderbooks(&self) -> bool { + fn should_validate_raindexes(&self) -> bool { false } fn should_validate_metaboards(&self) -> bool { @@ -134,10 +134,10 @@ impl YamlParsable for DotrainYaml { } } - fn from_orderbook_yaml(orderbook_yaml: OrderbookYaml) -> Self { + fn from_raindex_yaml(raindex_yaml: RaindexYaml) -> Self { DotrainYaml { - documents: orderbook_yaml.documents, - cache: orderbook_yaml.cache, + documents: raindex_yaml.documents, + cache: raindex_yaml.cache, profile: ContextProfile::Strict, } } @@ -376,14 +376,14 @@ mod tests { test::*, yaml::{ context::{ContextProfile, YamlCacheTrait}, - orderbook::OrderbookYamlValidation, + raindex::RaindexYamlValidation, }, BinXOptionsCfg, BinXTransformCfg, DotOptionsCfg, GuiSelectTokensCfg, HexBinOptionsCfg, HexBinTransformCfg, LineOptionsCfg, MarkCfg, RectYOptionsCfg, TransformCfg, TransformOutputsCfg, VaultType, }; use alloy::primitives::U256; - use orderbook::OrderbookYaml; + use raindex::RaindexYaml; use super::*; @@ -605,7 +605,7 @@ mod tests { #[test] fn test_full_yaml() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let dotrain_yaml = DotrainYaml::new(vec![full_yaml()], DotrainYamlValidation::default()).unwrap(); diff --git a/crates/settings/src/yaml/emitter.rs b/crates/settings/src/yaml/emitter.rs index 98218aa89f..fafcc6fa6c 100644 --- a/crates/settings/src/yaml/emitter.rs +++ b/crates/settings/src/yaml/emitter.rs @@ -6,7 +6,7 @@ use crate::{ accounts::AccountCfg, local_db_remotes::LocalDbRemoteCfg, local_db_sync::LocalDbSyncCfg, metaboard::MetaboardCfg, remote_networks::RemoteNetworksCfg, remote_tokens::RemoteTokensCfg, sentry::Sentry, spec_version::SpecVersion, subgraph::SubgraphCfg, ChartCfg, DeploymentCfg, - GuiCfg, NetworkCfg, OrderCfg, OrderbookCfg, RainlangCfg, ScenarioCfg, TokenCfg, + GuiCfg, NetworkCfg, OrderCfg, RaindexCfg, RainlangCfg, ScenarioCfg, TokenCfg, }; use std::sync::{Arc, RwLock}; use strict_yaml_rust::{strict_yaml::Hash, StrictYaml, StrictYamlEmitter}; @@ -19,7 +19,7 @@ const CANONICAL_ROOT_KEYS: &[&str] = &[ "metaboards", "tokens", "rainlangs", - "orderbooks", + "raindexes", "orders", "scenarios", "deployments", @@ -43,7 +43,7 @@ pub fn validate_and_emit_documents( validate_hash_section::(documents, context)?; validate_hash_section::(documents, context)?; validate_hash_section::(documents, context)?; - validate_hash_section::(documents, context)?; + validate_hash_section::(documents, context)?; validate_hash_section::(documents, context)?; ChartCfg::parse_all_from_yaml(documents.to_vec(), context)?; @@ -267,7 +267,7 @@ rainlangs: address: 0x0000000000000000000000000000000000000001 subgraphs: sg1: https://api.thegraph.com/subgraphs -orderbooks: +raindexes: ob1: network: mainnet address: 0x0000000000000000000000000000000000000002 @@ -276,7 +276,7 @@ orderbooks: orders: order1: rainlang: registry1 - orderbook: ob1 + raindex: ob1 inputs: - token: weth outputs: diff --git a/crates/settings/src/yaml/mod.rs b/crates/settings/src/yaml/mod.rs index 16bf52d3a2..8ec8b58fe4 100644 --- a/crates/settings/src/yaml/mod.rs +++ b/crates/settings/src/yaml/mod.rs @@ -2,18 +2,18 @@ pub mod cache; pub mod context; pub mod dotrain; pub mod emitter; -pub mod orderbook; +pub mod raindex; use crate::{ remote_networks::ParseRemoteNetworksError, remote_tokens::ParseRemoteTokensError, NetworkCfg, ParseDeploymentConfigSourceError, ParseNetworkConfigSourceError, ParseOrderConfigSourceError, - ParseOrderbookConfigSourceError, ParseRainlangConfigSourceError, - ParseScenarioConfigSourceError, ParseTokenConfigSourceError, TokenCfg, + ParseRaindexConfigSourceError, ParseRainlangConfigSourceError, ParseScenarioConfigSourceError, + ParseTokenConfigSourceError, TokenCfg, }; use alloy::primitives::ruint::ParseError as RuintParseError; use context::{Context, ContextError, ContextProfile}; use dotrain::DotrainYaml; -use orderbook::OrderbookYaml; +use raindex::RaindexYaml; use std::collections::HashMap; use std::sync::{Arc, RwLock}; use strict_yaml_rust::StrictYamlEmitter; @@ -32,7 +32,7 @@ pub trait ValidationConfig { fn should_validate_subgraphs(&self) -> bool; fn should_validate_local_db_remotes(&self) -> bool; fn should_validate_local_db_sync(&self) -> bool; - fn should_validate_orderbooks(&self) -> bool; + fn should_validate_raindexes(&self) -> bool; fn should_validate_metaboards(&self) -> bool; fn should_validate_rainlangs(&self) -> bool; fn should_validate_orders(&self) -> bool; @@ -45,7 +45,7 @@ pub trait YamlParsable: Sized { fn new(sources: Vec, validate: Self::ValidationConfig) -> Result; fn from_documents(documents: Vec>>) -> Self; - fn from_orderbook_yaml(orderbook_yaml: OrderbookYaml) -> Self; + fn from_raindex_yaml(raindex_yaml: RaindexYaml) -> Self; fn from_dotrain_yaml(dotrain_yaml: DotrainYaml) -> Self; fn get_yaml_string(document: Arc>) -> Result { @@ -199,7 +199,7 @@ pub enum YamlError { #[error(transparent)] ParseTokenConfigSourceError(#[from] ParseTokenConfigSourceError), #[error(transparent)] - ParseOrderbookConfigSourceError(#[from] ParseOrderbookConfigSourceError), + ParseRaindexConfigSourceError(#[from] ParseRaindexConfigSourceError), #[error(transparent)] ParseRainlangConfigSourceError(#[from] ParseRainlangConfigSourceError), #[error(transparent)] @@ -250,10 +250,9 @@ impl PartialEq for YamlError { (Self::ParseTokenConfigSourceError(e1), Self::ParseTokenConfigSourceError(e2)) => { e1 == e2 } - ( - Self::ParseOrderbookConfigSourceError(e1), - Self::ParseOrderbookConfigSourceError(e2), - ) => e1 == e2, + (Self::ParseRaindexConfigSourceError(e1), Self::ParseRaindexConfigSourceError(e2)) => { + e1 == e2 + } ( Self::ParseRainlangConfigSourceError(e1), Self::ParseRainlangConfigSourceError(e2), @@ -344,8 +343,8 @@ impl YamlError { "Token configuration error in your YAML: {}", err.to_readable_msg() ), - YamlError::ParseOrderbookConfigSourceError(err) => format!( - "Orderbook configuration error in your YAML: {}", + YamlError::ParseRaindexConfigSourceError(err) => format!( + "Raindex configuration error in your YAML: {}", err.to_readable_msg() ), YamlError::ParseRainlangConfigSourceError(err) => format!( @@ -552,7 +551,7 @@ pub fn sanitize_all_documents(documents: &[Arc>]) -> Result<( crate::LocalDbSyncCfg::sanitize_documents(documents)?; crate::NetworkCfg::sanitize_documents(documents)?; crate::OrderCfg::sanitize_documents(documents)?; - crate::OrderbookCfg::sanitize_documents(documents)?; + crate::RaindexCfg::sanitize_documents(documents)?; crate::RemoteNetworksCfg::sanitize_documents(documents)?; crate::ScenarioCfg::sanitize_documents(documents)?; crate::TokenCfg::sanitize_documents(documents)?; diff --git a/crates/settings/src/yaml/orderbook.rs b/crates/settings/src/yaml/raindex.rs similarity index 80% rename from crates/settings/src/yaml/orderbook.rs rename to crates/settings/src/yaml/raindex.rs index fb5360a848..d2facc5fb5 100644 --- a/crates/settings/src/yaml/orderbook.rs +++ b/crates/settings/src/yaml/raindex.rs @@ -2,7 +2,7 @@ use super::{cache::Cache, sanitize_all_documents, ValidationConfig, *}; use crate::{ accounts::AccountCfg, local_db_remotes::LocalDbRemoteCfg, local_db_sync::LocalDbSyncCfg, metaboard::MetaboardCfg, remote_networks::RemoteNetworksCfg, remote_tokens::RemoteTokensCfg, - sentry::Sentry, spec_version::SpecVersion, subgraph::SubgraphCfg, NetworkCfg, OrderbookCfg, + sentry::Sentry, spec_version::SpecVersion, subgraph::SubgraphCfg, NetworkCfg, RaindexCfg, RainlangCfg, TokenCfg, }; use alloy::primitives::Address; @@ -21,17 +21,17 @@ use wasm_bindgen_utils::{impl_wasm_traits, prelude::*}; #[derive(Debug, Clone, Default)] #[cfg_attr(target_family = "wasm", derive(Tsify))] -pub struct OrderbookYaml { +pub struct RaindexYaml { #[cfg_attr(target_family = "wasm", tsify(type = "string[]"))] pub documents: Vec>>, pub cache: Cache, pub profile: ContextProfile, } #[cfg(target_family = "wasm")] -impl_wasm_traits!(OrderbookYaml); +impl_wasm_traits!(RaindexYaml); #[derive(Debug, Clone, Default)] -pub struct OrderbookYamlValidation { +pub struct RaindexYamlValidation { pub networks: bool, pub remote_networks: bool, pub tokens: bool, @@ -39,13 +39,13 @@ pub struct OrderbookYamlValidation { pub subgraphs: bool, pub local_db_remotes: bool, pub local_db_sync: bool, - pub orderbooks: bool, + pub raindexes: bool, pub metaboards: bool, pub rainlangs: bool, } -impl OrderbookYamlValidation { +impl RaindexYamlValidation { pub fn full() -> Self { - OrderbookYamlValidation { + RaindexYamlValidation { networks: true, remote_networks: true, tokens: true, @@ -53,13 +53,13 @@ impl OrderbookYamlValidation { subgraphs: true, local_db_remotes: true, local_db_sync: true, - orderbooks: true, + raindexes: true, metaboards: true, rainlangs: true, } } } -impl ValidationConfig for OrderbookYamlValidation { +impl ValidationConfig for RaindexYamlValidation { fn should_validate_networks(&self) -> bool { self.networks } @@ -81,8 +81,8 @@ impl ValidationConfig for OrderbookYamlValidation { fn should_validate_local_db_sync(&self) -> bool { self.local_db_sync } - fn should_validate_orderbooks(&self) -> bool { - self.orderbooks + fn should_validate_raindexes(&self) -> bool { + self.raindexes } fn should_validate_metaboards(&self) -> bool { self.metaboards @@ -107,10 +107,10 @@ pub struct FetchedRemoteData { pub remote_tokens: HashMap, } -impl YamlParsable for OrderbookYaml { - type ValidationConfig = OrderbookYamlValidation; +impl YamlParsable for RaindexYaml { + type ValidationConfig = RaindexYamlValidation; - fn new(sources: Vec, validate: OrderbookYamlValidation) -> Result { + fn new(sources: Vec, validate: RaindexYamlValidation) -> Result { let mut documents = Vec::new(); for source in sources { @@ -148,8 +148,8 @@ impl YamlParsable for OrderbookYaml { if validate.should_validate_local_db_sync() { LocalDbSyncCfg::parse_all_from_yaml(documents.clone(), None)?; } - if validate.should_validate_orderbooks() { - OrderbookCfg::parse_all_from_yaml(documents.clone(), None)?; + if validate.should_validate_raindexes() { + RaindexCfg::parse_all_from_yaml(documents.clone(), None)?; } if validate.should_validate_metaboards() { MetaboardCfg::parse_all_from_yaml(documents.clone(), None)?; @@ -158,7 +158,7 @@ impl YamlParsable for OrderbookYaml { RainlangCfg::parse_all_from_yaml(documents.clone(), None)?; } - Ok(OrderbookYaml { + Ok(RaindexYaml { documents, cache: Cache::default(), profile: ContextProfile::Strict, @@ -166,23 +166,23 @@ impl YamlParsable for OrderbookYaml { } fn from_documents(documents: Vec>>) -> Self { - OrderbookYaml { + RaindexYaml { documents, cache: Cache::default(), profile: ContextProfile::Strict, } } - fn from_orderbook_yaml(orderbook_yaml: OrderbookYaml) -> Self { - OrderbookYaml { - documents: orderbook_yaml.documents, - cache: orderbook_yaml.cache, - profile: orderbook_yaml.profile, + fn from_raindex_yaml(raindex_yaml: RaindexYaml) -> Self { + RaindexYaml { + documents: raindex_yaml.documents, + cache: raindex_yaml.cache, + profile: raindex_yaml.profile, } } fn from_dotrain_yaml(dotrain_yaml: DotrainYaml) -> Self { - OrderbookYaml { + RaindexYaml { documents: dotrain_yaml.documents, cache: dotrain_yaml.cache, profile: dotrain_yaml.profile, @@ -190,7 +190,7 @@ impl YamlParsable for OrderbookYaml { } } -impl ContextProvider for OrderbookYaml { +impl ContextProvider for RaindexYaml { fn get_remote_networks_from_cache(&self) -> HashMap { self.cache.get_remote_networks() } @@ -200,10 +200,10 @@ impl ContextProvider for OrderbookYaml { } } -impl OrderbookYaml { +impl RaindexYaml { pub fn new_with_profile( sources: Vec, - validate: OrderbookYamlValidation, + validate: RaindexYamlValidation, profile: ContextProfile, ) -> Result { let mut instance = Self::new(sources, validate)?; @@ -325,71 +325,68 @@ impl OrderbookYaml { LocalDbSyncCfg::parse_from_yaml(self.documents.clone(), key, Some(&context)) } - pub fn get_orderbook_keys(&self) -> Result, YamlError> { - Ok(self.get_orderbooks()?.keys().cloned().collect()) + pub fn get_raindex_keys(&self) -> Result, YamlError> { + Ok(self.get_raindexes()?.keys().cloned().collect()) } - pub fn get_orderbooks(&self) -> Result, YamlError> { + pub fn get_raindexes(&self) -> Result, YamlError> { let context = self.build_context(); - OrderbookCfg::parse_all_from_yaml(self.documents.clone(), Some(&context)) + RaindexCfg::parse_all_from_yaml(self.documents.clone(), Some(&context)) } - pub fn get_orderbook(&self, key: &str) -> Result { + pub fn get_raindex(&self, key: &str) -> Result { let context = self.build_context(); - OrderbookCfg::parse_from_yaml(self.documents.clone(), key, Some(&context)) + RaindexCfg::parse_from_yaml(self.documents.clone(), key, Some(&context)) } - pub fn get_orderbook_by_address(&self, address: Address) -> Result { + pub fn get_raindex_by_address(&self, address: Address) -> Result { let context = self.build_context(); - let orderbooks = OrderbookCfg::parse_all_from_yaml(self.documents.clone(), Some(&context))?; - for (_, orderbook) in orderbooks { - if orderbook.address == address { - return Ok(orderbook); + let raindexes = RaindexCfg::parse_all_from_yaml(self.documents.clone(), Some(&context))?; + for (_, raindex) in raindexes { + if raindex.address == address { + return Ok(raindex); } } Err(YamlError::NotFound(format!( - "orderbook with address: {}", + "raindex with address: {}", address ))) } - pub fn get_orderbooks_by_network_key( + pub fn get_raindexes_by_network_key( &self, network_key: &str, - ) -> Result, YamlError> { - let mut orderbooks: Vec<_> = self - .get_orderbooks()? + ) -> Result, YamlError> { + let mut raindexes: Vec<_> = self + .get_raindexes()? .into_iter() - .filter(|(_, ob)| ob.network.key == network_key) - .map(|(_, ob)| ob) + .filter(|(_, raindex_cfg)| raindex_cfg.network.key == network_key) + .map(|(_, raindex_cfg)| raindex_cfg) .collect(); - orderbooks.sort_by(|a, b| a.key.cmp(&b.key)); + raindexes.sort_by(|a, b| a.key.cmp(&b.key)); - if orderbooks.is_empty() { + if raindexes.is_empty() { return Err(YamlError::NotFound(format!( - "orderbook with network key: {}", + "raindex with network key: {}", network_key ))); } - Ok(orderbooks) + Ok(raindexes) } - pub fn get_orderbooks_by_chain_id( - &self, - chain_id: u32, - ) -> Result, YamlError> { + pub fn get_raindexes_by_chain_id(&self, chain_id: u32) -> Result, YamlError> { let network = self.get_network_by_chain_id(chain_id)?; - let mut orderbooks: Vec<_> = self - .get_orderbooks()? + let mut raindexes: Vec<_> = self + .get_raindexes()? .into_iter() - .filter(|(_, ob)| ob.network.key == network.key) - .map(|(_, ob)| ob) + .filter(|(_, raindex_cfg)| raindex_cfg.network.key == network.key) + .map(|(_, raindex_cfg)| raindex_cfg) .collect(); - orderbooks.sort_by(|a, b| a.key.cmp(&b.key)); + raindexes.sort_by(|a, b| a.key.cmp(&b.key)); - if orderbooks.is_empty() { + if raindexes.is_empty() { return Err(YamlError::NotFound(format!( - "orderbook with chain-id: {}", + "raindex with chain-id: {}", chain_id ))); } - Ok(orderbooks) + Ok(raindexes) } pub fn get_metaboard_keys(&self) -> Result, YamlError> { @@ -457,7 +454,7 @@ impl OrderbookYaml { } } -impl Serialize for OrderbookYaml { +impl Serialize for RaindexYaml { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -468,22 +465,22 @@ impl Serialize for OrderbookYaml { documents.push(yaml_str); } - let mut state = serializer.serialize_struct("OrderbookYaml", 2)?; + let mut state = serializer.serialize_struct("RaindexYaml", 2)?; state.serialize_field("documents", &documents)?; state.serialize_field("profile", &self.profile)?; state.end() } } -impl<'de> Deserialize<'de> for OrderbookYaml { +impl<'de> Deserialize<'de> for RaindexYaml { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - struct OrderbookYamlVisitor; + struct RaindexYamlVisitor; - impl<'de> Visitor<'de> for OrderbookYamlVisitor { - type Value = OrderbookYaml; + impl<'de> Visitor<'de> for RaindexYamlVisitor { + type Value = RaindexYaml; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence of YAML documents as strings") @@ -526,7 +523,7 @@ impl<'de> Deserialize<'de> for OrderbookYaml { }) .collect::, M::Error>>()?; - Ok(OrderbookYaml { + Ok(RaindexYaml { documents, cache: Cache::default(), profile, @@ -549,7 +546,7 @@ impl<'de> Deserialize<'de> for OrderbookYaml { documents.push(Arc::new(RwLock::new(doc))); } - Ok(OrderbookYaml { + Ok(RaindexYaml { documents, cache: Cache::default(), profile: ContextProfile::Strict, @@ -557,7 +554,7 @@ impl<'de> Deserialize<'de> for OrderbookYaml { } } - deserializer.deserialize_any(OrderbookYamlVisitor) + deserializer.deserialize_any(RaindexYamlVisitor) } } @@ -571,38 +568,38 @@ mod tests { use url::Url; #[test] - fn test_orderbook_yaml_profile_helpers() { + fn test_raindex_yaml_profile_helpers() { let sources = vec![full_yaml()]; - let ob = OrderbookYaml::new_with_profile( + let yaml = RaindexYaml::new_with_profile( sources.clone(), - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), ContextProfile::Gui { current_deployment: "deployment1".to_string(), }, ) .unwrap(); - assert!(matches!(ob.profile, ContextProfile::Gui { .. })); + assert!(matches!(yaml.profile, ContextProfile::Gui { .. })); - let ob_default = OrderbookYaml::new(sources, OrderbookYamlValidation::default()).unwrap(); - assert!(matches!(ob_default.profile, ContextProfile::Strict)); + let yaml_default = RaindexYaml::new(sources, RaindexYamlValidation::default()).unwrap(); + assert!(matches!(yaml_default.profile, ContextProfile::Strict)); - let ob_strict = ob.with_profile(ContextProfile::Strict); - assert!(matches!(ob_strict.profile, ContextProfile::Strict)); + let yaml_strict = yaml.with_profile(ContextProfile::Strict); + assert!(matches!(yaml_strict.profile, ContextProfile::Strict)); } #[test] - fn test_orderbook_yaml_serialization_preserves_profile() { - let ob = OrderbookYaml::new_with_profile( + fn test_raindex_yaml_serialization_preserves_profile() { + let yaml = RaindexYaml::new_with_profile( vec![full_yaml()], - OrderbookYamlValidation::default(), + RaindexYamlValidation::default(), ContextProfile::Gui { current_deployment: "deployment1".to_string(), }, ) .unwrap(); - let serialized = serde_json::to_string(&ob).unwrap(); - let round_tripped: OrderbookYaml = serde_json::from_str(&serialized).unwrap(); + let serialized = serde_json::to_string(&yaml).unwrap(); + let round_tripped: RaindexYaml = serde_json::from_str(&serialized).unwrap(); match round_tripped.profile { ContextProfile::Gui { current_deployment } => { assert_eq!(current_deployment, "deployment1"); @@ -612,9 +609,9 @@ mod tests { } #[test] - fn test_orderbook_yaml_legacy_sequence_deserialization_defaults_profile() { + fn test_raindex_yaml_legacy_sequence_deserialization_defaults_profile() { let legacy_serialized = serde_json::to_string(&vec![full_yaml()]).unwrap(); - let deserialized: OrderbookYaml = serde_json::from_str(&legacy_serialized).unwrap(); + let deserialized: RaindexYaml = serde_json::from_str(&legacy_serialized).unwrap(); assert!(matches!(deserialized.profile, ContextProfile::Strict)); assert_eq!(deserialized.documents.len(), 1); @@ -646,13 +643,13 @@ mod tests { metaboards: board1: https://meta.example.com/board1 board2: https://meta.example.com/board2 - orderbooks: - orderbook1: + raindexes: + raindex1: address: 0x0000000000000000000000000000000000000002 network: mainnet subgraph: mainnet local-db-remote: mainnet - label: Primary Orderbook + label: Primary Raindex deployment-block: 12345 tokens: token1: @@ -684,8 +681,8 @@ mod tests { mainnet: https://api.thegraph.com/subgraphs/name/xyz metaboards: board1: https://meta.example.com/board1 - orderbooks: - orderbook1: + raindexes: + raindex1: address: 0x1234567890abcdef deployment-block: 12345 tokens: @@ -700,7 +697,7 @@ mod tests { #[test] fn test_full_yaml() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); assert_eq!(ob_yaml.get_network_keys().unwrap().len(), 1); let network = ob_yaml.get_network("mainnet").unwrap(); @@ -754,25 +751,25 @@ mod tests { Url::parse("https://api.thegraph.com/subgraphs/name/xyz").unwrap() ); - assert_eq!(ob_yaml.get_orderbook_keys().unwrap().len(), 1); - let orderbook = ob_yaml.get_orderbook("orderbook1").unwrap(); + assert_eq!(ob_yaml.get_raindex_keys().unwrap().len(), 1); + let raindex = ob_yaml.get_raindex("raindex1").unwrap(); assert_eq!( - orderbook.address, + raindex.address, Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); - assert_eq!(orderbook.network, network.clone().into()); - assert_eq!(orderbook.subgraph, subgraph.into()); - assert_eq!(orderbook.label, Some("Primary Orderbook".to_string())); + assert_eq!(raindex.network, network.clone().into()); + assert_eq!(raindex.subgraph, subgraph.into()); + assert_eq!(raindex.label, Some("Primary Raindex".to_string())); assert_eq!( - OrderbookCfg::parse_network_key(ob_yaml.documents.clone(), "orderbook1").unwrap(), + RaindexCfg::parse_network_key(ob_yaml.documents.clone(), "raindex1").unwrap(), "mainnet" ); - let orderbook_by_address = ob_yaml - .get_orderbook_by_address( + let raindex_by_address = ob_yaml + .get_raindex_by_address( Address::from_str("0x0000000000000000000000000000000000000002").unwrap(), ) .unwrap(); - assert_eq!(orderbook_by_address, orderbook); + assert_eq!(raindex_by_address, raindex); assert_eq!(ob_yaml.get_metaboard_keys().unwrap().len(), 2); assert_eq!( @@ -814,7 +811,7 @@ mod tests { #[test] fn test_update_network_rpc() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let mut network = ob_yaml.get_network("mainnet").unwrap(); assert_eq!( @@ -853,7 +850,7 @@ mod tests { #[test] fn test_update_token_address() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let mut token = ob_yaml.get_token("token1").unwrap(); assert_eq!( @@ -889,7 +886,7 @@ networks: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); TokenCfg::add_record_to_yaml( ob_yaml.documents.clone(), @@ -917,7 +914,7 @@ networks: #[test] fn test_remove_token_from_yaml() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); assert!(ob_yaml.get_token("token1").is_ok()); TokenCfg::remove_record_from_yaml(ob_yaml.documents.clone(), "token1").unwrap(); @@ -933,7 +930,7 @@ test: test "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); ob_yaml .add_metaboard("test-metaboard", "https://test-metaboard.com") @@ -952,7 +949,7 @@ test: test #[test] fn test_get_network_by_chain_id() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); // Test successful lookup let network = ob_yaml.get_network_by_chain_id(1).unwrap(); @@ -980,31 +977,31 @@ test: test } #[test] - fn test_get_orderbook_by_network_key() { + fn test_get_raindexes_by_network_key() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); // Test successful lookup - let orderbooks = ob_yaml.get_orderbooks_by_network_key("mainnet").unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].key, "orderbook1"); - assert_eq!(orderbooks[0].network.key, "mainnet"); + let raindexes = ob_yaml.get_raindexes_by_network_key("mainnet").unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].key, "raindex1"); + assert_eq!(raindexes[0].network.key, "mainnet"); assert_eq!( - orderbooks[0].address, + raindexes[0].address, Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); // Test error case - network key not found let error = ob_yaml - .get_orderbooks_by_network_key("nonexistent") + .get_raindexes_by_network_key("nonexistent") .unwrap_err(); assert_eq!( error, - YamlError::NotFound("orderbook with network key: nonexistent".to_string()) + YamlError::NotFound("raindex with network key: nonexistent".to_string()) ); assert_eq!( error.to_readable_msg(), - "The requested item \"orderbook with network key: nonexistent\" could not be found in the YAML configuration." + "The requested item \"raindex with network key: nonexistent\" could not be found in the YAML configuration." ); } @@ -1037,20 +1034,20 @@ test: test currency: ETH subgraphs: mainnet: https://api.thegraph.com/subgraphs/name/xyz - orderbooks: - mainnet-orderbook: + raindexes: + mainnet-raindex: address: 0x1234567890123456789012345678901234567890 network: mainnet subgraph: mainnet local-db-remote: mainnet deployment-block: 12345 - other-orderbook: + other-raindex: address: 0x1234567890123456789012345678901234567891 network: mainnet subgraph: mainnet local-db-remote: mainnet deployment-block: 12345 - polygon-orderbook: + polygon-raindex: address: 0x0987654321098765432109876543210987654321 network: polygon deployment-block: 12345 @@ -1060,7 +1057,7 @@ test: test spec_version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); // Test each network let mainnet = ob_yaml.get_network_by_chain_id(1).unwrap(); @@ -1075,44 +1072,44 @@ test: test assert_eq!(arbitrum.key, "arbitrum"); assert_eq!(arbitrum.chain_id, 42161); - // Test orderbook lookup by network key - let orderbooks = ob_yaml.get_orderbooks_by_network_key("mainnet").unwrap(); - assert_eq!(orderbooks.len(), 2); - assert_eq!(orderbooks[0].key, "mainnet-orderbook"); - assert_eq!(orderbooks[0].network.key, "mainnet"); - assert_eq!(orderbooks[1].key, "other-orderbook"); - assert_eq!(orderbooks[1].network.key, "mainnet"); + // Test raindex lookup by network key + let raindexes = ob_yaml.get_raindexes_by_network_key("mainnet").unwrap(); + assert_eq!(raindexes.len(), 2); + assert_eq!(raindexes[0].key, "mainnet-raindex"); + assert_eq!(raindexes[0].network.key, "mainnet"); + assert_eq!(raindexes[1].key, "other-raindex"); + assert_eq!(raindexes[1].network.key, "mainnet"); - let orderbooks = ob_yaml.get_orderbooks_by_network_key("polygon").unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].key, "polygon-orderbook"); - assert_eq!(orderbooks[0].network.key, "polygon"); + let raindexes = ob_yaml.get_raindexes_by_network_key("polygon").unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].key, "polygon-raindex"); + assert_eq!(raindexes[0].network.key, "polygon"); - // Test error for network without orderbook + // Test error for network without raindex let error = ob_yaml - .get_orderbooks_by_network_key("arbitrum") + .get_raindexes_by_network_key("arbitrum") .unwrap_err(); assert_eq!( error, - YamlError::NotFound("orderbook with network key: arbitrum".to_string()) + YamlError::NotFound("raindex with network key: arbitrum".to_string()) ); } #[test] - fn test_get_orderbooks_by_chain_id_single_network() { + fn test_get_raindexes_by_chain_id_single_network() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); - let orderbooks = ob_yaml.get_orderbooks_by_chain_id(1).unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].key, "orderbook1"); - assert_eq!(orderbooks[0].network.key, "mainnet"); + let raindexes = ob_yaml.get_raindexes_by_chain_id(1).unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].key, "raindex1"); + assert_eq!(raindexes[0].network.key, "mainnet"); assert_eq!( - orderbooks[0].address, + raindexes[0].address, Address::from_str("0x0000000000000000000000000000000000000002").unwrap() ); - let err = ob_yaml.get_orderbooks_by_chain_id(999).unwrap_err(); + let err = ob_yaml.get_raindexes_by_chain_id(999).unwrap_err(); assert_eq!( err, YamlError::NotFound("network with chain-id: 999".to_string()) @@ -1124,7 +1121,7 @@ test: test } #[test] - fn test_get_orderbooks_by_chain_id_multiple_networks() { + fn test_get_raindexes_by_chain_id_multiple_networks() { let yaml = format!( r#" version: {spec_version} @@ -1143,20 +1140,20 @@ test: test chain-id: 42161 subgraphs: mainnet: https://api.thegraph.com/subgraphs/name/xyz - orderbooks: - mainnet-orderbook: + raindexes: + mainnet-raindex: address: 0x1234567890123456789012345678901234567890 network: mainnet subgraph: mainnet local-db-remote: mainnet deployment-block: 12345 - other-orderbook: + other-raindex: address: 0x1234567890123456789012345678901234567891 network: mainnet subgraph: mainnet local-db-remote: mainnet deployment-block: 12345 - polygon-orderbook: + polygon-raindex: address: 0x0987654321098765432109876543210987654321 network: polygon deployment-block: 12345 @@ -1166,31 +1163,31 @@ test: test spec_version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); // mainnet chain id - let orderbooks = ob_yaml.get_orderbooks_by_chain_id(1).unwrap(); - assert_eq!(orderbooks.len(), 2); - assert_eq!(orderbooks[0].network.key, "mainnet"); - assert_eq!(orderbooks[1].network.key, "mainnet"); + let raindexes = ob_yaml.get_raindexes_by_chain_id(1).unwrap(); + assert_eq!(raindexes.len(), 2); + assert_eq!(raindexes[0].network.key, "mainnet"); + assert_eq!(raindexes[1].network.key, "mainnet"); // polygon chain id - let orderbooks = ob_yaml.get_orderbooks_by_chain_id(137).unwrap(); - assert_eq!(orderbooks.len(), 1); - assert_eq!(orderbooks[0].network.key, "polygon"); + let raindexes = ob_yaml.get_raindexes_by_chain_id(137).unwrap(); + assert_eq!(raindexes.len(), 1); + assert_eq!(raindexes[0].network.key, "polygon"); - // arbitrum chain id has no orderbooks - let err = ob_yaml.get_orderbooks_by_chain_id(42161).unwrap_err(); + // arbitrum chain id has no raindexes + let err = ob_yaml.get_raindexes_by_chain_id(42161).unwrap_err(); assert_eq!( err, - YamlError::NotFound("orderbook with chain-id: 42161".to_string()) + YamlError::NotFound("raindex with chain-id: 42161".to_string()) ); } #[test] fn test_get_local_db_remote_keys() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let keys = ob_yaml.get_local_db_remote_keys().unwrap(); assert_eq!(keys, vec!["mainnet".to_string()]); @@ -1199,7 +1196,7 @@ test: test #[test] fn test_get_local_db_remotes_and_single_remote() { let ob_yaml = - OrderbookYaml::new(vec![full_yaml()], OrderbookYamlValidation::default()).unwrap(); + RaindexYaml::new(vec![full_yaml()], RaindexYamlValidation::default()).unwrap(); let remotes = ob_yaml.get_local_db_remotes().unwrap(); assert_eq!(remotes.len(), 1); @@ -1235,7 +1232,7 @@ subgraphs: version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let err = ob_yaml.get_local_db_remote("polygon").unwrap_err(); assert_eq!(err, YamlError::KeyNotFound("polygon".to_string())); } @@ -1258,7 +1255,7 @@ local-db-sync: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let keys = ob_yaml.get_local_db_sync_keys().unwrap(); assert_eq!(keys, vec!["test".to_string()]); @@ -1295,7 +1292,7 @@ local-db-sync: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let cfg = ob_yaml.get_local_db_sync("test").unwrap(); assert_eq!(cfg.key, "test"); @@ -1327,7 +1324,7 @@ local-db-sync: "#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let err = ob_yaml.get_local_db_sync("nonexistent").unwrap_err(); assert_eq!(err, YamlError::KeyNotFound("nonexistent".to_string())); @@ -1341,7 +1338,7 @@ version: {version} test: test"#, version = SpecVersion::current() ); - let ob_yaml = OrderbookYaml::new(vec![yaml], OrderbookYamlValidation::default()).unwrap(); + let ob_yaml = RaindexYaml::new(vec![yaml], RaindexYamlValidation::default()).unwrap(); let syncs = ob_yaml.get_local_db_syncs().unwrap(); assert!(syncs.is_empty()); diff --git a/crates/subgraph/Cargo.toml b/crates/subgraph/Cargo.toml index 5508309c26..e052b3d9aa 100644 --- a/crates/subgraph/Cargo.toml +++ b/crates/subgraph/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "rain_orderbook_subgraph_client" -description = "Subgraph client, queries & schemas for the Rain Orderbook" +name = "raindex_subgraph_client" +description = "Subgraph client, queries & schemas for the Raindex" version.workspace = true edition.workspace = true license.workspace = true @@ -15,8 +15,8 @@ thiserror = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } alloy = { workspace = true, features = ["rand"] } -rain_orderbook_bindings = { workspace = true } -rain_orderbook_math = { workspace = true } +raindex_bindings = { workspace = true } +raindex_math = { workspace = true } chrono = { workspace = true } url = { workspace = true, features = ["serde"] } cynic-introspection = "3.7.3" diff --git a/crates/subgraph/build.rs b/crates/subgraph/build.rs index bba4827c91..d4aee0cf17 100644 --- a/crates/subgraph/build.rs +++ b/crates/subgraph/build.rs @@ -1,6 +1,6 @@ fn main() { - cynic_codegen::register_schema("orderbook") - .from_sdl_file("schema/orderbook.graphql") + cynic_codegen::register_schema("raindex") + .from_sdl_file("schema/raindex.graphql") .unwrap() .as_default() .unwrap(); diff --git a/crates/subgraph/queries/multiOrderDetail.graphql b/crates/subgraph/queries/multiOrderDetail.graphql index bea36a3cc0..35fde19bdf 100644 --- a/crates/subgraph/queries/multiOrderDetail.graphql +++ b/crates/subgraph/queries/multiOrderDetail.graphql @@ -25,7 +25,7 @@ query MultiOrderDetailQuery($ids: [Bytes!]!) { balance vaultId } - orderbook { + raindex { id } active diff --git a/crates/subgraph/queries/orderDetail.graphql b/crates/subgraph/queries/orderDetail.graphql index e021f1f9ba..d34f478b94 100644 --- a/crates/subgraph/queries/orderDetail.graphql +++ b/crates/subgraph/queries/orderDetail.graphql @@ -25,7 +25,7 @@ query OrderDetailQuery($id: Bytes!) { balance vaultId } - orderbook { + raindex { id } active diff --git a/crates/subgraph/queries/orderTakeDetail.graphql b/crates/subgraph/queries/orderTakeDetail.graphql index b83c140d15..52ff5442c9 100644 --- a/crates/subgraph/queries/orderTakeDetail.graphql +++ b/crates/subgraph/queries/orderTakeDetail.graphql @@ -21,7 +21,7 @@ query OrderTakeDetailQuery($id: Bytes!) { order { orderHash } - orderbook { + raindex { id } inputVaultBalanceChange { diff --git a/crates/subgraph/queries/orderTakesList.graphql b/crates/subgraph/queries/orderTakesList.graphql index 57ea44d0d9..9ce3899579 100644 --- a/crates/subgraph/queries/orderTakesList.graphql +++ b/crates/subgraph/queries/orderTakesList.graphql @@ -26,7 +26,7 @@ query OrderTakesListQuery($id: Bytes!, $skip: Int = 0, $first: Int = 25) { id orderHash } - orderbook { + raindex { id } inputVaultBalanceChange { diff --git a/crates/subgraph/queries/ordersList.graphql b/crates/subgraph/queries/ordersList.graphql index 894491b34b..4762970d99 100644 --- a/crates/subgraph/queries/ordersList.graphql +++ b/crates/subgraph/queries/ordersList.graphql @@ -25,7 +25,7 @@ query OrdersListQuery($skip: Int = 0, $first: Int = 25) { balance vaultId } - orderbook { + raindex { id } active diff --git a/crates/subgraph/queries/vaultBalanceChangesList.graphql b/crates/subgraph/queries/vaultBalanceChangesList.graphql index 0449d6096b..eccf525451 100644 --- a/crates/subgraph/queries/vaultBalanceChangesList.graphql +++ b/crates/subgraph/queries/vaultBalanceChangesList.graphql @@ -15,7 +15,7 @@ query VaultBalanceChangesListQuery($id: Bytes!, $skip: Int = 0, $first: Int = 25 vault { id } - orderbook { + raindex { id } } diff --git a/crates/subgraph/queries/vaultDetail.graphql b/crates/subgraph/queries/vaultDetail.graphql index 761a1e44aa..4893ee7f85 100644 --- a/crates/subgraph/queries/vaultDetail.graphql +++ b/crates/subgraph/queries/vaultDetail.graphql @@ -9,7 +9,7 @@ query VaultDetailQuery($id: Bytes!) { decimals } owner - orderbook { + raindex { id } ordersAsOutput { diff --git a/crates/subgraph/queries/vaultsList.graphql b/crates/subgraph/queries/vaultsList.graphql index 48f14dc230..263b5e0113 100644 --- a/crates/subgraph/queries/vaultsList.graphql +++ b/crates/subgraph/queries/vaultsList.graphql @@ -10,7 +10,7 @@ query VaultsListQuery($skip: Int = 0, $first: Int = 25) { decimals } balance - orderbook { + raindex { id } ordersAsInput { diff --git a/crates/subgraph/schema/orderbook.graphql b/crates/subgraph/schema/raindex.graphql similarity index 91% rename from crates/subgraph/schema/orderbook.graphql rename to crates/subgraph/schema/raindex.graphql index 97004a3bb0..5d59371db8 100644 --- a/crates/subgraph/schema/orderbook.graphql +++ b/crates/subgraph/schema/raindex.graphql @@ -80,9 +80,9 @@ type AddOrder implements Event { order: Order! """ - The orderbook this add order event is in + The raindex this add order event is in """ - orderbook: Orderbook! + raindex: Raindex! transaction: Transaction! """ @@ -123,27 +123,27 @@ input AddOrder_filter { order_not_ends_with: String order_not_ends_with_nocase: String order_: Order_filter - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter transaction: String transaction_not: String transaction_gt: String @@ -195,8 +195,8 @@ enum AddOrder_orderBy { order__orderBytes order__meta order__timestampAdded - orderbook - orderbook__id + raindex + raindex__id transaction transaction__id transaction__timestamp @@ -262,9 +262,9 @@ type Clear implements TradeEvent { bobBountyVaultBalanceChange: ClearBounty """ - The orderbook this trade event is for + The raindex this trade event is for """ - orderbook: Orderbook! + raindex: Raindex! """ The trades that occured in this event @@ -397,27 +397,27 @@ input Clear_filter { bobBountyVaultBalanceChange_not_ends_with: String bobBountyVaultBalanceChange_not_ends_with_nocase: String bobBountyVaultBalanceChange_: ClearBounty_filter - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter trades_: Trade_filter transaction: String transaction_not: String @@ -481,8 +481,8 @@ enum Clear_orderBy { bobBountyVaultBalanceChange__oldVaultBalance bobBountyVaultBalanceChange__newVaultBalance bobBountyVaultBalanceChange__timestamp - orderbook - orderbook__id + raindex + raindex__id trades transaction transaction__id @@ -496,9 +496,9 @@ type ClearBounty implements VaultBalanceChange { id: Bytes! """ - The orderbook this balance change is for + The raindex this balance change is for """ - orderbook: Orderbook! + raindex: Raindex! """ The msg.sender of this clear call and owner of the vault @@ -547,27 +547,27 @@ input ClearBounty_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter sender: Bytes sender_not: Bytes sender_gt: Bytes @@ -669,8 +669,8 @@ input ClearBounty_filter { enum ClearBounty_orderBy { id - orderbook - orderbook__id + raindex + raindex__id sender vault vault__id @@ -888,9 +888,9 @@ type Deposit implements Event & VaultBalanceChange { id: Bytes! """ - The orderbook this balance change is for + The raindex this balance change is for """ - orderbook: Orderbook! + raindex: Raindex! """ The vault that was deposited into @@ -927,27 +927,27 @@ input Deposit_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter vault: String vault_not: String vault_gt: String @@ -1049,8 +1049,8 @@ input Deposit_filter { enum Deposit_orderBy { id - orderbook - orderbook__id + raindex + raindex__id vault vault__id vault__owner @@ -1249,9 +1249,9 @@ type Order { id: Bytes! """ - The orderbook this order is in + The raindex this order is in """ - orderbook: Orderbook! + raindex: Raindex! """ Whether this order is active or not @@ -1355,27 +1355,27 @@ input Order_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter active: Boolean active_not: Boolean active_in: [Boolean!] @@ -1466,8 +1466,8 @@ input Order_filter { enum Order_orderBy { id - orderbook - orderbook__id + raindex + raindex__id active orderHash owner @@ -1482,11 +1482,11 @@ enum Order_orderBy { timestampAdded } -type Orderbook { +type Raindex { id: Bytes! """ - All orders in the orderbook + All orders in the raindex """ orders( skip: Int = 0 @@ -1497,7 +1497,7 @@ type Orderbook { ): [Order!]! """ - All trades in the orderbook + All trades in the raindex """ trades( skip: Int = 0 @@ -1508,7 +1508,7 @@ type Orderbook { ): [Trade!]! """ - All vaults in the orderbook + All vaults in the raindex """ vaults( skip: Int = 0 @@ -1519,7 +1519,7 @@ type Orderbook { ): [Vault!]! """ - All vault balance changes in the orderbook + All vault balance changes in the raindex """ vaultBalanceChanges( skip: Int = 0 @@ -1530,7 +1530,7 @@ type Orderbook { ): [VaultBalanceChange!]! """ - All deposit events in the orderbook + All deposit events in the raindex """ deposits( skip: Int = 0 @@ -1541,7 +1541,7 @@ type Orderbook { ): [Deposit!]! """ - All withdrawal events in the orderbook + All withdrawal events in the raindex """ withdrawals( skip: Int = 0 @@ -1552,7 +1552,7 @@ type Orderbook { ): [Withdrawal!]! """ - All add order events in the orderbook + All add order events in the raindex """ addOrders( skip: Int = 0 @@ -1563,7 +1563,7 @@ type Orderbook { ): [AddOrder!]! """ - All remove order events in the orderbook + All remove order events in the raindex """ removeOrders( skip: Int = 0 @@ -1574,7 +1574,7 @@ type Orderbook { ): [RemoveOrder!]! """ - All take order events in the orderbook + All take order events in the raindex """ takeOrders( skip: Int = 0 @@ -1585,7 +1585,7 @@ type Orderbook { ): [TakeOrder!]! """ - All trade events in the orderbook + All trade events in the raindex """ tradeEvents( skip: Int = 0 @@ -1596,7 +1596,7 @@ type Orderbook { ): [TradeEvent!]! } -input Orderbook_filter { +input Raindex_filter { id: Bytes id_not: Bytes id_gt: Bytes @@ -1622,11 +1622,11 @@ input Orderbook_filter { Filter for the block changed event. """ _change_block: BlockChangedFilter - and: [Orderbook_filter] - or: [Orderbook_filter] + and: [Raindex_filter] + or: [Raindex_filter] } -enum Orderbook_orderBy { +enum Raindex_orderBy { id orders trades @@ -1649,7 +1649,7 @@ enum OrderDirection { } type Query { - orderbook( + raindex( id: ID! """ @@ -1666,13 +1666,13 @@ type Query { Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. """ subgraphError: _SubgraphErrorPolicy_! = deny - ): Orderbook - orderbooks( + ): Raindex + raindexs( skip: Int = 0 first: Int = 100 - orderBy: Orderbook_orderBy + orderBy: Raindex_orderBy orderDirection: OrderDirection - where: Orderbook_filter + where: Raindex_filter """ The block at which the query should be executed. Can either be a `{ hash: @@ -1688,7 +1688,7 @@ type Query { Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. """ subgraphError: _SubgraphErrorPolicy_! = deny - ): [Orderbook!]! + ): [Raindex!]! vault( id: ID! @@ -2385,9 +2385,9 @@ type RemoveOrder implements Event { order: Order! """ - The orderbook this remove order event is in + The raindex this remove order event is in """ - orderbook: Orderbook! + raindex: Raindex! transaction: Transaction! """ @@ -2428,27 +2428,27 @@ input RemoveOrder_filter { order_not_ends_with: String order_not_ends_with_nocase: String order_: Order_filter - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter transaction: String transaction_not: String transaction_gt: String @@ -2500,8 +2500,8 @@ enum RemoveOrder_orderBy { order__orderBytes order__meta order__timestampAdded - orderbook - orderbook__id + raindex + raindex__id transaction transaction__id transaction__timestamp @@ -2511,7 +2511,7 @@ enum RemoveOrder_orderBy { } type Subscription { - orderbook( + raindex( id: ID! """ @@ -2528,13 +2528,13 @@ type Subscription { Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. """ subgraphError: _SubgraphErrorPolicy_! = deny - ): Orderbook - orderbooks( + ): Raindex + raindexs( skip: Int = 0 first: Int = 100 - orderBy: Orderbook_orderBy + orderBy: Raindex_orderBy orderDirection: OrderDirection - where: Orderbook_filter + where: Raindex_filter """ The block at which the query should be executed. Can either be a `{ hash: @@ -2550,7 +2550,7 @@ type Subscription { Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. """ subgraphError: _SubgraphErrorPolicy_! = deny - ): [Orderbook!]! + ): [Raindex!]! vault( id: ID! @@ -3257,9 +3257,9 @@ type TakeOrder implements TradeEvent { takeOrderConfigBytes: Bytes! """ - The orderbook this trade event is for + The raindex this trade event is for """ - orderbook: Orderbook! + raindex: Raindex! """ The trades that occured in this event @@ -3320,27 +3320,27 @@ input TakeOrder_filter { takeOrderConfigBytes_not_in: [Bytes!] takeOrderConfigBytes_contains: Bytes takeOrderConfigBytes_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter trades_: Trade_filter transaction: String transaction_not: String @@ -3387,8 +3387,8 @@ enum TakeOrder_orderBy { inputAmount outputAmount takeOrderConfigBytes - orderbook - orderbook__id + raindex + raindex__id trades transaction transaction__id @@ -3407,9 +3407,9 @@ type Trade { id: Bytes! """ - The orderbook this trade is for + The raindex this trade is for """ - orderbook: Orderbook! + raindex: Raindex! """ The order that was traded @@ -3448,27 +3448,27 @@ input Trade_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter order: String order_not: String order_gt: String @@ -3572,8 +3572,8 @@ input Trade_filter { enum Trade_orderBy { id - orderbook - orderbook__id + raindex + raindex__id order order__id order__active @@ -3605,9 +3605,9 @@ interface TradeEvent { id: Bytes! """ - The orderbook this trade event is for + The raindex this trade event is for """ - orderbook: Orderbook! + raindex: Raindex! """ The trades that occured in this event @@ -3638,27 +3638,27 @@ input TradeEvent_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter trades_: Trade_filter transaction: String transaction_not: String @@ -3702,8 +3702,8 @@ input TradeEvent_filter { enum TradeEvent_orderBy { id - orderbook - orderbook__id + raindex + raindex__id trades transaction transaction__id @@ -3717,9 +3717,9 @@ type TradeVaultBalanceChange implements VaultBalanceChange { id: Bytes! """ - The orderbook this balance change is for + The raindex this balance change is for """ - orderbook: Orderbook! + raindex: Raindex! """ The trade that this balance change is for @@ -3768,27 +3768,27 @@ input TradeVaultBalanceChange_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter trade: String trade_not: String trade_gt: String @@ -3901,8 +3901,8 @@ input TradeVaultBalanceChange_filter { enum TradeVaultBalanceChange_orderBy { id - orderbook - orderbook__id + raindex + raindex__id trade trade__id trade__timestamp @@ -3995,9 +3995,9 @@ type Vault { id: Bytes! """ - The orderbook this vault is in + The raindex this vault is in """ - orderbook: Orderbook! + raindex: Raindex! """ The token that this vault is for @@ -4064,27 +4064,27 @@ input Vault_filter { id_not_in: [Bytes!] id_contains: Bytes id_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter token: String token_not: String token_gt: String @@ -4150,8 +4150,8 @@ input Vault_filter { enum Vault_orderBy { id - orderbook - orderbook__id + raindex + raindex__id token token__id token__address @@ -4168,9 +4168,9 @@ enum Vault_orderBy { interface VaultBalanceChange { """ - The orderbook this balance change is for + The raindex this balance change is for """ - orderbook: Orderbook! + raindex: Raindex! """ The vault that was affected @@ -4204,27 +4204,27 @@ interface VaultBalanceChange { } input VaultBalanceChange_filter { - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter vault: String vault_not: String vault_gt: String @@ -4315,8 +4315,8 @@ input VaultBalanceChange_filter { } enum VaultBalanceChange_orderBy { - orderbook - orderbook__id + raindex + raindex__id vault vault__id vault__owner @@ -4342,9 +4342,9 @@ type Withdrawal implements Event & VaultBalanceChange { targetAmount: Bytes! """ - The orderbook this balance change is for + The raindex this balance change is for """ - orderbook: Orderbook! + raindex: Raindex! """ The vault that was withdrawn from @@ -4391,27 +4391,27 @@ input Withdrawal_filter { targetAmount_not_in: [Bytes!] targetAmount_contains: Bytes targetAmount_not_contains: Bytes - orderbook: String - orderbook_not: String - orderbook_gt: String - orderbook_lt: String - orderbook_gte: String - orderbook_lte: String - orderbook_in: [String!] - orderbook_not_in: [String!] - orderbook_contains: String - orderbook_contains_nocase: String - orderbook_not_contains: String - orderbook_not_contains_nocase: String - orderbook_starts_with: String - orderbook_starts_with_nocase: String - orderbook_not_starts_with: String - orderbook_not_starts_with_nocase: String - orderbook_ends_with: String - orderbook_ends_with_nocase: String - orderbook_not_ends_with: String - orderbook_not_ends_with_nocase: String - orderbook_: Orderbook_filter + raindex: String + raindex_not: String + raindex_gt: String + raindex_lt: String + raindex_gte: String + raindex_lte: String + raindex_in: [String!] + raindex_not_in: [String!] + raindex_contains: String + raindex_contains_nocase: String + raindex_not_contains: String + raindex_not_contains_nocase: String + raindex_starts_with: String + raindex_starts_with_nocase: String + raindex_not_starts_with: String + raindex_not_starts_with_nocase: String + raindex_ends_with: String + raindex_ends_with_nocase: String + raindex_not_ends_with: String + raindex_not_ends_with_nocase: String + raindex_: Raindex_filter vault: String vault_not: String vault_gt: String @@ -4514,8 +4514,8 @@ input Withdrawal_filter { enum Withdrawal_orderBy { id targetAmount - orderbook - orderbook__id + raindex + raindex__id vault vault__id vault__owner diff --git a/crates/subgraph/src/lib.rs b/crates/subgraph/src/lib.rs index 952845184f..fb36ac1b6f 100644 --- a/crates/subgraph/src/lib.rs +++ b/crates/subgraph/src/lib.rs @@ -1,16 +1,16 @@ mod cynic_client; -mod multi_orderbook_client; -mod orderbook_client; +mod multi_raindex_client; mod pagination; pub mod performance; +mod raindex_client; pub mod types; pub mod utils; pub mod validate; mod vault_balance_changes_query; -#[cynic::schema("orderbook")] +#[cynic::schema("raindex")] pub mod schema {} -pub use multi_orderbook_client::{MultiOrderbookSubgraphClient, MultiSubgraphArgs}; -pub use orderbook_client::{OrderbookSubgraphClient, OrderbookSubgraphClientError}; +pub use multi_raindex_client::{MultiRaindexSubgraphClient, MultiSubgraphArgs}; pub use pagination::{PageQueryClient, SgPaginationArgs}; +pub use raindex_client::{RaindexSubgraphClient, RaindexSubgraphClientError}; diff --git a/crates/subgraph/src/multi_orderbook_client.rs b/crates/subgraph/src/multi_raindex_client.rs similarity index 91% rename from crates/subgraph/src/multi_orderbook_client.rs rename to crates/subgraph/src/multi_raindex_client.rs index 685a17d1be..f5a86b0c1b 100644 --- a/crates/subgraph/src/multi_orderbook_client.rs +++ b/crates/subgraph/src/multi_raindex_client.rs @@ -3,7 +3,7 @@ use crate::{ SgErc20WithSubgraphName, SgOrderWithSubgraphName, SgOrdersListFilterArgs, SgVaultWithSubgraphName, SgVaultsListFilterArgs, }, - OrderbookSubgraphClient, OrderbookSubgraphClientError, SgPaginationArgs, + RaindexSubgraphClient, RaindexSubgraphClientError, SgPaginationArgs, }; use futures::future::join_all; use reqwest::Url; @@ -18,16 +18,16 @@ pub struct MultiSubgraphArgs { } impl_wasm_traits!(MultiSubgraphArgs); -pub struct MultiOrderbookSubgraphClient { +pub struct MultiRaindexSubgraphClient { subgraphs: Vec, } -impl MultiOrderbookSubgraphClient { +impl MultiRaindexSubgraphClient { pub fn new(subgraphs: Vec) -> Self { Self { subgraphs } } - fn get_orderbook_subgraph_client(&self, url: Url) -> OrderbookSubgraphClient { - OrderbookSubgraphClient::new(url) + fn get_raindex_subgraph_client(&self, url: Url) -> RaindexSubgraphClient { + RaindexSubgraphClient::new(url) } pub async fn orders_list( @@ -40,7 +40,7 @@ impl MultiOrderbookSubgraphClient { let filter_args = filter_args.clone(); let pagination_args = pagination_args.clone(); async move { - let client = self.get_orderbook_subgraph_client(url); + let client = self.get_raindex_subgraph_client(url); let orders = client.orders_list(filter_args, pagination_args).await?; let wrapped_orders: Vec = orders .into_iter() @@ -49,7 +49,7 @@ impl MultiOrderbookSubgraphClient { subgraph_name: subgraph.name.clone(), }) .collect(); - Ok::<_, OrderbookSubgraphClientError>(wrapped_orders) + Ok::<_, RaindexSubgraphClientError>(wrapped_orders) } }); @@ -73,12 +73,12 @@ impl MultiOrderbookSubgraphClient { pub async fn orders_count( &self, filter_args: SgOrdersListFilterArgs, - ) -> Result { + ) -> Result { let futures = self.subgraphs.iter().map(|subgraph| { let url = subgraph.url.clone(); let filter_args = filter_args.clone(); async move { - let client = self.get_orderbook_subgraph_client(url); + let client = self.get_raindex_subgraph_client(url); client.orders_count(filter_args).await } }); @@ -101,7 +101,7 @@ impl MultiOrderbookSubgraphClient { let filter_args = filter_args.clone(); let pagination_args = pagination_args.clone(); async move { - let client = self.get_orderbook_subgraph_client(url); + let client = self.get_raindex_subgraph_client(url); let vaults = client.vaults_list(filter_args, pagination_args).await?; let wrapped_vaults: Vec = vaults .into_iter() @@ -110,7 +110,7 @@ impl MultiOrderbookSubgraphClient { subgraph_name: subgraph.name.clone(), }) .collect(); - Ok::<_, OrderbookSubgraphClientError>(wrapped_vaults) + Ok::<_, RaindexSubgraphClientError>(wrapped_vaults) } }); @@ -129,7 +129,7 @@ impl MultiOrderbookSubgraphClient { let futures = self.subgraphs.iter().map(|subgraph| { let url = subgraph.url.clone(); async move { - let client = self.get_orderbook_subgraph_client(url); + let client = self.get_raindex_subgraph_client(url); let tokens = client.tokens_list_all().await?; let wrapped_tokens: Vec = tokens .into_iter() @@ -138,7 +138,7 @@ impl MultiOrderbookSubgraphClient { subgraph_name: subgraph.name.clone(), }) .collect(); - Ok::<_, OrderbookSubgraphClientError>(wrapped_tokens) + Ok::<_, RaindexSubgraphClientError>(wrapped_tokens) } }); @@ -158,7 +158,7 @@ impl MultiOrderbookSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrder, SgOrderbook, SgOrdersListFilterArgs, SgVault, + SgBigInt, SgBytes, SgErc20, SgOrder, SgOrdersListFilterArgs, SgRaindex, SgVault, }; use crate::utils::float::*; use httpmock::prelude::*; @@ -173,8 +173,8 @@ mod tests { owner: SgBytes("0xdefault_owner".to_string()), outputs: vec![], inputs: vec![], - orderbook: SgOrderbook { - id: SgBytes("0xdefault_orderbook_id".to_string()), + raindex: SgRaindex { + id: SgBytes("0xdefault_raindex_id".to_string()), }, active: true, timestamp_added: SgBigInt(timestamp.to_string()), @@ -191,7 +191,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], } } @@ -204,7 +204,7 @@ mod tests { #[tokio::test] async fn test_orders_list_no_subgraphs() { - let client = MultiOrderbookSubgraphClient::new(vec![]); + let client = MultiRaindexSubgraphClient::new(vec![]); let result = client .orders_list(default_filter_args(), default_pagination_args()) .await; @@ -224,7 +224,7 @@ mod tests { .json_body(json!({"data": {"orders": [order1_s1]}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![MultiSubgraphArgs { + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), }]); @@ -262,7 +262,7 @@ mod tests { .json_body(json!({"data": {"orders": [order_b_s2, order_c_s2]}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -307,7 +307,7 @@ mod tests { then.status(200).json_body(json!({"data": {"orders": []}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -346,7 +346,7 @@ mod tests { then.status(500); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -383,7 +383,7 @@ mod tests { then.status(500); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -415,7 +415,7 @@ mod tests { .json_body(json!({"data": {"orders": [order_a, order_b, order_c]}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![MultiSubgraphArgs { + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), }]); @@ -447,7 +447,7 @@ mod tests { ); }); - let client = MultiOrderbookSubgraphClient::new(vec![MultiSubgraphArgs { + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), }]); @@ -481,7 +481,7 @@ mod tests { #[tokio::test] async fn test_orders_count_no_subgraphs() { - let client = MultiOrderbookSubgraphClient::new(vec![]); + let client = MultiRaindexSubgraphClient::new(vec![]); let count = client.orders_count(default_filter_args()).await.unwrap(); assert_eq!(count, 0); } @@ -500,7 +500,7 @@ mod tests { .json_body(json!({"data": {"orders": orders}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![MultiSubgraphArgs { + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { url: sg1_url, name: "sg_one".to_string(), }]); @@ -534,7 +534,7 @@ mod tests { .json_body(json!({"data": {"orders": orders_s2}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: "sg_one".to_string(), @@ -569,7 +569,7 @@ mod tests { then.status(500); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: "sg_one".to_string(), @@ -600,7 +600,7 @@ mod tests { then.status(500); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: "sg_one_err".to_string(), @@ -617,7 +617,7 @@ mod tests { #[tokio::test] async fn test_orders_count_pagination_boundary() { - use crate::orderbook_client::ALL_PAGES_QUERY_PAGE_SIZE; + use crate::raindex_client::ALL_PAGES_QUERY_PAGE_SIZE; let server = MockServer::start_async().await; let sg_url = Url::parse(&server.url("")).unwrap(); @@ -642,7 +642,7 @@ mod tests { .json_body(json!({"data": {"orders": page2_orders}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![MultiSubgraphArgs { + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { url: sg_url, name: "sg_one".to_string(), }]); @@ -661,9 +661,9 @@ mod tests { } } - fn sample_sg_orderbook(id_suffix: &str) -> SgOrderbook { - SgOrderbook { - id: SgBytes(format!("0xorderbook_id_{}", id_suffix)), + fn sample_sg_raindex(id_suffix: &str) -> SgRaindex { + SgRaindex { + id: SgBytes(format!("0xraindex_id_{}", id_suffix)), } } @@ -681,7 +681,7 @@ mod tests { )), balance: SgBytes(F1.as_hex()), token: sample_sg_erc20(id_suffix), - orderbook: sample_sg_orderbook(id_suffix), + raindex: sample_sg_raindex(id_suffix), orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], @@ -693,14 +693,14 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, } } #[tokio::test] async fn test_vaults_list_no_subgraphs() { - let client = MultiOrderbookSubgraphClient::new(vec![]); + let client = MultiRaindexSubgraphClient::new(vec![]); let result = client .vaults_list(default_vault_filter_args(), default_pagination_args()) .await; @@ -720,7 +720,7 @@ mod tests { .json_body(json!({"data": {"vaults": [vault1_s1]}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![MultiSubgraphArgs { + let client = MultiRaindexSubgraphClient::new(vec![MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), }]); @@ -758,7 +758,7 @@ mod tests { .json_body(json!({"data": {"vaults": [vault_b_s2, vault_c_s2]}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -809,7 +809,7 @@ mod tests { then.status(200).json_body(json!({"data": {"vaults": []}})); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -848,7 +848,7 @@ mod tests { then.status(500); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), @@ -885,7 +885,7 @@ mod tests { then.status(500); }); - let client = MultiOrderbookSubgraphClient::new(vec![ + let client = MultiRaindexSubgraphClient::new(vec![ MultiSubgraphArgs { url: sg1_url, name: sg1_name.to_string(), diff --git a/crates/subgraph/src/performance/apy.rs b/crates/subgraph/src/performance/apy.rs index a30a3a35f6..2b2500a088 100644 --- a/crates/subgraph/src/performance/apy.rs +++ b/crates/subgraph/src/performance/apy.rs @@ -6,7 +6,7 @@ use crate::{ use alloy::primitives::U256; use chrono::TimeDelta; use rain_math_float::Float; -use rain_orderbook_math::{BigUintMath, ONE18}; +use raindex_math::{BigUintMath, ONE18}; use serde::{Deserialize, Serialize}; use std::str::FromStr; #[cfg(target_family = "wasm")] @@ -165,7 +165,7 @@ mod tests { use crate::{ performance::vol::VolumeDetails, types::common::{ - SgBigInt, SgBytes, SgOrderbook, SgTradeEvent, SgTradeStructPartialOrder, + SgBigInt, SgBytes, SgRaindex, SgTradeEvent, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }, }; @@ -358,7 +358,7 @@ mod tests { }, }, timestamp: SgBigInt("1".to_string()), - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, output_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), __typename: "TradeVaultBalanceChange".to_string(), @@ -377,7 +377,7 @@ mod tests { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, input_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), @@ -397,7 +397,7 @@ mod tests { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, }; @@ -417,7 +417,7 @@ mod tests { }, }, timestamp: SgBigInt("2".to_string()), - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, output_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), __typename: "TradeVaultBalanceChange".to_string(), @@ -436,7 +436,7 @@ mod tests { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, input_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), @@ -456,7 +456,7 @@ mod tests { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, }; vec![trade2, trade1] diff --git a/crates/subgraph/src/performance/mod.rs b/crates/subgraph/src/performance/mod.rs index 758b7290eb..6ca3e56dbd 100644 --- a/crates/subgraph/src/performance/mod.rs +++ b/crates/subgraph/src/performance/mod.rs @@ -1,5 +1,5 @@ use rain_math_float::FloatError; -use rain_orderbook_math::MathError; +use raindex_math::MathError; use std::num::ParseIntError; use thiserror::Error; @@ -7,7 +7,7 @@ use thiserror::Error; // use alloy::primitives::{ruint::ParseError, U256}; // use chrono::TimeDelta; // use once_cell::sync::Lazy; -// use rain_orderbook_math::ONE18; +// use raindex_math::ONE18; // TODO: APY related logic // pub mod apy; diff --git a/crates/subgraph/src/performance/order_performance.rs b/crates/subgraph/src/performance/order_performance.rs index 140c031cd6..763c0b365f 100644 --- a/crates/subgraph/src/performance/order_performance.rs +++ b/crates/subgraph/src/performance/order_performance.rs @@ -8,7 +8,7 @@ use crate::{ }; use alloy::primitives::U256; use rain_math_float::Float; -use rain_orderbook_math::{BigUintMath, ONE18}; +use raindex_math::{BigUintMath, ONE18}; use serde::{Deserialize, Serialize}; use std::cmp::Ordering; use std::collections::HashMap; @@ -58,8 +58,8 @@ pub struct OrderPerformance { pub order_id: String, /// Order hash pub order_hash: String, - /// Order's orderbook - pub orderbook: String, + /// Order's raindex + pub raindex: String, /// Order's measured performance as a whole pub denominated_performance: Option, /// Start timestamp of the performance measring timeframe @@ -142,7 +142,7 @@ impl OrderPerformance { let mut order_performance = OrderPerformance { order_id: order.id.0.clone(), order_hash: order.order_hash.0.clone(), - orderbook: order.orderbook.id.0.clone(), + raindex: order.raindex.id.0.clone(), start_time, end_time, inputs_vaults: inputs, @@ -464,7 +464,7 @@ mod test { use super::super::*; use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgOrder, SgOrderbook, SgTradeEvent, SgTradeStructPartialOrder, + SgBigInt, SgBytes, SgOrder, SgRaindex, SgTradeEvent, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVault, SgVaultBalanceChangeVault, }; use alloy::primitives::{Address, B256}; @@ -744,7 +744,7 @@ mod test { let expected = OrderPerformance { order_id: "order-id".to_string(), order_hash: "".to_string(), - orderbook: "".to_string(), + raindex: "".to_string(), start_time: 1, end_time: 10000001, inputs_vaults: vec![token1_perf.clone(), token2_perf.clone()], @@ -799,7 +799,7 @@ mod test { vault_id: SgBytes(vault_id1.to_string()), balance: SgBytes("".to_string()), token: token1, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("".to_string()), }, orders_as_output: vec![], @@ -812,7 +812,7 @@ mod test { vault_id: SgBytes(vault_id2.to_string()), balance: SgBytes("".to_string()), token: token2, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("".to_string()), }, orders_as_output: vec![], @@ -826,7 +826,7 @@ mod test { owner: SgBytes("".to_string()), outputs: vec![vault1.clone(), vault2.clone()], inputs: vec![vault1, vault2], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("".to_string()), }, active: true, @@ -860,7 +860,7 @@ mod test { }, }, timestamp: SgBigInt("1".to_string()), - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, output_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), __typename: "TradeVaultBalanceChange".to_string(), @@ -879,7 +879,7 @@ mod test { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, input_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), @@ -899,7 +899,7 @@ mod test { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, }; @@ -919,7 +919,7 @@ mod test { }, }, timestamp: SgBigInt("2".to_string()), - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, output_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), __typename: "TradeVaultBalanceChange".to_string(), @@ -938,7 +938,7 @@ mod test { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, input_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), @@ -958,7 +958,7 @@ mod test { block_number: bigint.clone(), timestamp: SgBigInt("1".to_string()), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, }, }; vec![trade2, trade1] diff --git a/crates/subgraph/src/performance/vol.rs b/crates/subgraph/src/performance/vol.rs index 30b0b92602..fd0f05a977 100644 --- a/crates/subgraph/src/performance/vol.rs +++ b/crates/subgraph/src/performance/vol.rs @@ -132,7 +132,7 @@ mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgOrderbook, SgTradeEvent, SgTradeEventTypename, SgTradeRef, + SgBigInt, SgBytes, SgRaindex, SgTradeEvent, SgTradeEventTypename, SgTradeRef, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; @@ -243,7 +243,7 @@ mod tests { }, }, timestamp: bigint.clone(), - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, output_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), __typename: "TradeVaultBalanceChange".to_string(), @@ -262,7 +262,7 @@ mod tests { block_number: bigint.clone(), timestamp: bigint.clone(), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, trade: SgTradeRef { trade_event: SgTradeEventTypename { __typename: "TradeEvent".to_string(), @@ -287,7 +287,7 @@ mod tests { block_number: bigint.clone(), timestamp: bigint.clone(), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, trade: SgTradeRef { trade_event: SgTradeEventTypename { __typename: "TradeEvent".to_string(), @@ -312,7 +312,7 @@ mod tests { }, }, timestamp: bigint.clone(), - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, output_vault_balance_change: SgTradeVaultBalanceChange { id: bytes.clone(), __typename: "TradeVaultBalanceChange".to_string(), @@ -331,7 +331,7 @@ mod tests { block_number: bigint.clone(), timestamp: bigint.clone(), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, trade: SgTradeRef { trade_event: SgTradeEventTypename { __typename: "TradeEvent".to_string(), @@ -356,7 +356,7 @@ mod tests { block_number: bigint.clone(), timestamp: bigint.clone(), }, - orderbook: SgOrderbook { id: bytes.clone() }, + raindex: SgRaindex { id: bytes.clone() }, trade: SgTradeRef { trade_event: SgTradeEventTypename { __typename: "TradeEvent".to_string(), @@ -541,7 +541,7 @@ mod tests { // }, // }, // timestamp: bigint.clone(), - // orderbook: SgOrderbook { id: bytes.clone() }, + // raindex: SgRaindex { id: bytes.clone() }, // output_vault_balance_change: SgTradeVaultBalanceChange { // id: bytes.clone(), // __typename: "TradeVaultBalanceChange".to_string(), @@ -560,7 +560,7 @@ mod tests { // block_number: bigint.clone(), // timestamp: bigint.clone(), // }, - // orderbook: SgOrderbook { id: bytes.clone() }, + // raindex: SgRaindex { id: bytes.clone() }, // }, // input_vault_balance_change: SgTradeVaultBalanceChange { // id: bytes.clone(), @@ -580,7 +580,7 @@ mod tests { // block_number: bigint.clone(), // timestamp: bigint.clone(), // }, - // orderbook: SgOrderbook { id: bytes.clone() }, + // raindex: SgRaindex { id: bytes.clone() }, // }, // }; // @@ -600,7 +600,7 @@ mod tests { // }, // }, // timestamp: bigint.clone(), - // orderbook: SgOrderbook { id: bytes.clone() }, + // raindex: SgRaindex { id: bytes.clone() }, // output_vault_balance_change: SgTradeVaultBalanceChange { // id: bytes.clone(), // __typename: "TradeVaultBalanceChange".to_string(), @@ -619,7 +619,7 @@ mod tests { // block_number: bigint.clone(), // timestamp: bigint.clone(), // }, - // orderbook: SgOrderbook { id: bytes.clone() }, + // raindex: SgRaindex { id: bytes.clone() }, // }, // input_vault_balance_change: SgTradeVaultBalanceChange { // id: bytes.clone(), @@ -639,7 +639,7 @@ mod tests { // block_number: bigint.clone(), // timestamp: bigint.clone(), // }, - // orderbook: SgOrderbook { id: bytes.clone() }, + // raindex: SgRaindex { id: bytes.clone() }, // }, // }; // diff --git a/crates/subgraph/src/orderbook_client/mod.rs b/crates/subgraph/src/raindex_client/mod.rs similarity index 86% rename from crates/subgraph/src/orderbook_client/mod.rs rename to crates/subgraph/src/raindex_client/mod.rs index c26a72993c..9f665a7f69 100644 --- a/crates/subgraph/src/orderbook_client/mod.rs +++ b/crates/subgraph/src/raindex_client/mod.rs @@ -28,7 +28,7 @@ mod vault; pub const ALL_PAGES_QUERY_PAGE_SIZE: u16 = 200; #[derive(Error, Debug)] -pub enum OrderbookSubgraphClientError { +pub enum RaindexSubgraphClientError { #[error(transparent)] CynicClientError(#[from] CynicClientError), #[error("Subgraph query returned no data")] @@ -50,25 +50,25 @@ pub enum OrderbookSubgraphClientError { OrderDetailExtendError, } -impl From for JsValue { - fn from(value: OrderbookSubgraphClientError) -> Self { +impl From for JsValue { + fn from(value: RaindexSubgraphClientError) -> Self { JsError::new(&value.to_string()).into() } } #[derive(Debug)] -pub struct OrderbookSubgraphClient { +pub struct RaindexSubgraphClient { url: Url, } -impl CynicClient for OrderbookSubgraphClient { +impl CynicClient for RaindexSubgraphClient { fn get_base_url(&self) -> &Url { &self.url } } -impl PaginationClient for OrderbookSubgraphClient {} +impl PaginationClient for RaindexSubgraphClient {} -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { pub fn new(url: Url) -> Self { Self { url } } diff --git a/crates/subgraph/src/orderbook_client/order.rs b/crates/subgraph/src/raindex_client/order.rs similarity index 94% rename from crates/subgraph/src/orderbook_client/order.rs rename to crates/subgraph/src/raindex_client/order.rs index d0ee69ece8..ff9a750fa4 100644 --- a/crates/subgraph/src/orderbook_client/order.rs +++ b/crates/subgraph/src/raindex_client/order.rs @@ -1,12 +1,12 @@ use super::*; -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { /// Fetch single order - pub async fn order_detail(&self, id: &Id) -> Result { + pub async fn order_detail(&self, id: &Id) -> Result { let data = self .query::(SgIdQueryVariables { id }) .await?; - let order = data.order.ok_or(OrderbookSubgraphClientError::Empty)?; + let order = data.order.ok_or(RaindexSubgraphClientError::Empty)?; Ok(order) } @@ -15,7 +15,7 @@ impl OrderbookSubgraphClient { pub async fn batch_order_detail( &self, id_list: Vec, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { if id_list.is_empty() { return Ok(vec![]); } @@ -35,13 +35,13 @@ impl OrderbookSubgraphClient { &self, filter_args: SgOrdersListFilterArgs, pagination_args: SgPaginationArgs, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let pagination_variables = Self::parse_pagination_args(pagination_args); let has_basic_filters = !filter_args.owners.is_empty() || filter_args.active.is_some() || filter_args.order_hash.is_some() - || !filter_args.orderbooks.is_empty(); + || !filter_args.raindexes.is_empty(); let tokens = filter_args.tokens.as_ref(); let has_input_tokens = tokens.is_some_and(|tokens| !tokens.inputs.is_empty()); let has_output_tokens = tokens.is_some_and(|tokens| !tokens.outputs.is_empty()); @@ -54,7 +54,7 @@ impl OrderbookSubgraphClient { order_hash: filter_args.order_hash.clone(), inputs_: None, outputs_: None, - orderbook_in: filter_args.orderbooks.clone(), + raindex_in: filter_args.raindexes.clone(), }; let or_filters = if has_input_tokens && has_output_tokens { @@ -114,7 +114,7 @@ impl OrderbookSubgraphClient { async fn fetch_all_orders_pages( &self, filter_args: SgOrdersListFilterArgs, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let mut all_pages_merged = vec![]; let mut page: u16 = 1; @@ -138,13 +138,13 @@ impl OrderbookSubgraphClient { Ok(all_pages_merged) } - pub async fn orders_list_all(&self) -> Result, OrderbookSubgraphClientError> { + pub async fn orders_list_all(&self) -> Result, RaindexSubgraphClientError> { self.fetch_all_orders_pages(SgOrdersListFilterArgs { owners: vec![], active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], }) .await } @@ -152,7 +152,7 @@ impl OrderbookSubgraphClient { pub async fn orders_count( &self, filter_args: SgOrdersListFilterArgs, - ) -> Result { + ) -> Result { Ok(self.fetch_all_orders_pages(filter_args).await?.len() as u32) } @@ -160,7 +160,7 @@ impl OrderbookSubgraphClient { pub async fn order_detail_by_hash( &self, hash: SgBytes, - ) -> Result { + ) -> Result { let data = self .query::( SgOrderDetailByHashQueryVariables { hash }, @@ -169,7 +169,7 @@ impl OrderbookSubgraphClient { let order = data .orders .first() - .ok_or(OrderbookSubgraphClientError::Empty)?; + .ok_or(RaindexSubgraphClientError::Empty)?; Ok(order.clone()) } } @@ -178,7 +178,7 @@ impl OrderbookSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgOrder, SgOrderbook, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, + SgBigInt, SgBytes, SgOrder, SgOrdersListFilterArgs, SgOrdersTokensFilterArgs, SgRaindex, }; use crate::utils::float::*; use cynic::Id; @@ -187,9 +187,9 @@ mod tests { use reqwest::Url; use serde_json::json; - fn setup_client(server: &MockServer) -> OrderbookSubgraphClient { + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { let url = Url::parse(&server.url("")).unwrap(); - OrderbookSubgraphClient::new(url) + RaindexSubgraphClient::new(url) } fn default_sg_order() -> SgOrder { @@ -211,7 +211,7 @@ mod tests { symbol: Some("sFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![SgOrderAsIO { @@ -237,7 +237,7 @@ mod tests { orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0x0000000000000000000000000000000000000000".to_string()), } } @@ -255,7 +255,7 @@ mod tests { symbol: Some("WFLR".to_string()), decimals: Some(SgBigInt("18".to_string())), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, orders_as_output: vec![], @@ -281,12 +281,12 @@ mod tests { orders_as_output: vec![], orders_as_input: vec![], balance_changes: vec![], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0x0000000000000000000000000000000000000000".to_string()), } } ], - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("0xcee8cd002f151a536394e564b84076c41bbbcd4d".to_string()), }, active: true, @@ -309,7 +309,7 @@ mod tests { assert_eq!(actual.id, expected.id); assert_eq!(actual.owner, expected.owner); assert_eq!(actual.active, expected.active); - assert_eq!(actual.orderbook.id, expected.orderbook.id); + assert_eq!(actual.raindex.id, expected.raindex.id); assert_eq!(actual.inputs.len(), expected.inputs.len()); for (actual_input, expected_input) in actual.inputs.iter().zip(expected.inputs.iter()) { assert_eq!(actual_input.id, expected_input.id); @@ -321,7 +321,7 @@ mod tests { assert_eq!(actual_input.token.name, expected_input.token.name); assert_eq!(actual_input.token.symbol, expected_input.token.symbol); assert_eq!(actual_input.token.decimals, expected_input.token.decimals); - assert_eq!(actual_input.orderbook.id, expected_input.orderbook.id); + assert_eq!(actual_input.raindex.id, expected_input.raindex.id); } assert_eq!(actual.outputs.len(), expected.outputs.len()); for (actual_output, expected_output) in actual.outputs.iter().zip(expected.outputs.iter()) { @@ -334,7 +334,7 @@ mod tests { assert_eq!(actual_output.token.name, expected_output.token.name); assert_eq!(actual_output.token.symbol, expected_output.token.symbol); assert_eq!(actual_output.token.decimals, expected_output.token.decimals); - assert_eq!(actual_output.orderbook.id, expected_output.orderbook.id); + assert_eq!(actual_output.raindex.id, expected_output.raindex.id); } } @@ -371,7 +371,7 @@ mod tests { }); let result = client.order_detail(&order_id).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -388,7 +388,7 @@ mod tests { let result = client.order_detail(&order_id).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -490,7 +490,7 @@ mod tests { let result = client.batch_order_detail(id_list_sgbytes).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -504,7 +504,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -538,7 +538,7 @@ mod tests { active: Some(true), order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -570,7 +570,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -596,7 +596,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -611,7 +611,7 @@ mod tests { let result = client.orders_list(filter_args, pagination_args).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -696,7 +696,7 @@ mod tests { let result = client.orders_list_all().await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -706,7 +706,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], } } @@ -813,7 +813,7 @@ mod tests { }); let result = client.order_detail_by_hash(order_hash_sg).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -831,7 +831,7 @@ mod tests { let result = client.order_detail_by_hash(order_hash_sg).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -848,7 +848,7 @@ mod tests { inputs: vec![token_address.clone()], outputs: vec![], }), - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -884,7 +884,7 @@ mod tests { inputs: vec![], outputs: vec![token_address.clone()], }), - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -921,7 +921,7 @@ mod tests { inputs: vec![token1.clone()], outputs: vec![token2.clone()], }), - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -961,7 +961,7 @@ mod tests { inputs: vec![token_address.clone()], outputs: vec![], }), - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -987,16 +987,16 @@ mod tests { } #[tokio::test] - async fn test_orders_list_with_orderbook_filter() { + async fn test_orders_list_with_raindex_filter() { let sg_server = MockServer::start_async().await; let client = setup_client(&sg_server); - let orderbook_address = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string(); + let raindex_address = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string(); let filter_args = SgOrdersListFilterArgs { owners: vec![], active: None, order_hash: None, tokens: None, - orderbooks: vec![orderbook_address.clone()], + raindexes: vec![raindex_address.clone()], }; let pagination_args = SgPaginationArgs { page: 1, @@ -1007,7 +1007,7 @@ mod tests { sg_server.mock(|when, then| { when.method(POST) .path("/") - .body_contains(format!("\"orderbook_in\":[\"{}\"]", orderbook_address)); + .body_contains(format!("\"raindex_in\":[\"{}\"]", raindex_address)); then.status(200) .json_body(json!({"data": {"orders": expected_orders}})); }); @@ -1019,7 +1019,7 @@ mod tests { } #[tokio::test] - async fn test_orders_list_with_multiple_orderbook_filters() { + async fn test_orders_list_with_multiple_raindex_filters() { let sg_server = MockServer::start_async().await; let client = setup_client(&sg_server); let ob1 = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string(); @@ -1029,7 +1029,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![ob1.clone(), ob2.clone()], + raindexes: vec![ob1.clone(), ob2.clone()], }; let pagination_args = SgPaginationArgs { page: 1, @@ -1040,7 +1040,7 @@ mod tests { sg_server.mock(|when, then| { when.method(POST) .path("/") - .body_contains(format!("\"orderbook_in\":[\"{}\",\"{}\"]", ob1, ob2)); + .body_contains(format!("\"raindex_in\":[\"{}\",\"{}\"]", ob1, ob2)); then.status(200) .json_body(json!({"data": {"orders": expected_orders}})); }); @@ -1052,7 +1052,7 @@ mod tests { } #[tokio::test] - async fn test_orders_list_empty_orderbook_filter_omits_field() { + async fn test_orders_list_empty_raindex_filter_omits_field() { let sg_server = MockServer::start_async().await; let client = setup_client(&sg_server); let filter_args = SgOrdersListFilterArgs { @@ -1060,7 +1060,7 @@ mod tests { active: None, order_hash: None, tokens: None, - orderbooks: vec![], + raindexes: vec![], }; let pagination_args = SgPaginationArgs { page: 1, @@ -1074,7 +1074,7 @@ mod tests { .matches(|req: &httpmock::prelude::HttpMockRequest| { if let Some(body) = &req.body { let body_str = String::from_utf8_lossy(body); - !body_str.contains("orderbook_in") + !body_str.contains("raindex_in") } else { true } @@ -1086,7 +1086,7 @@ mod tests { let result = client.orders_list(filter_args, pagination_args).await; assert!( result.is_ok(), - "Request failed - orderbook_in was likely present in request body when it should be omitted" + "Request failed - raindex_in was likely present in request body when it should be omitted" ); mock.assert(); } diff --git a/crates/subgraph/src/orderbook_client/order_trade.rs b/crates/subgraph/src/raindex_client/order_trade.rs similarity index 93% rename from crates/subgraph/src/orderbook_client/order_trade.rs rename to crates/subgraph/src/raindex_client/order_trade.rs index 41e4f6e5bb..20a5700957 100644 --- a/crates/subgraph/src/orderbook_client/order_trade.rs +++ b/crates/subgraph/src/raindex_client/order_trade.rs @@ -1,15 +1,12 @@ use super::*; -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { /// Fetch single order take - pub async fn order_trade_detail( - &self, - id: Id, - ) -> Result { + pub async fn order_trade_detail(&self, id: Id) -> Result { let data = self .query::(SgIdQueryVariables { id: &id }) .await?; - let order_take = data.trade.ok_or(OrderbookSubgraphClientError::Empty)?; + let order_take = data.trade.ok_or(RaindexSubgraphClientError::Empty)?; Ok(order_take) } @@ -21,7 +18,7 @@ impl OrderbookSubgraphClient { pagination_args: SgPaginationArgs, start_timestamp: Option, end_timestamp: Option, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let pagination_variables = Self::parse_pagination_args(pagination_args); let data = self .query::( @@ -50,7 +47,7 @@ impl OrderbookSubgraphClient { order_id: cynic::Id, start_timestamp: Option, end_timestamp: Option, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let mut all_pages_merged = vec![]; let mut page = 1; @@ -80,7 +77,7 @@ impl OrderbookSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTradeEvent, SgTradeEventTypename, SgTradeRef, + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTradeEvent, SgTradeEventTypename, SgTradeRef, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; @@ -90,9 +87,9 @@ mod tests { use reqwest::Url; use serde_json::json; - fn setup_client(server: &MockServer) -> OrderbookSubgraphClient { + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { let url = Url::parse(&server.url("")).unwrap(); - OrderbookSubgraphClient::new(url) + RaindexSubgraphClient::new(url) } fn default_sg_transaction() -> SgTransaction { @@ -104,9 +101,9 @@ mod tests { } } - fn default_sg_orderbook() -> SgOrderbook { - SgOrderbook { - id: SgBytes("0xorderbook_id_default".to_string()), + fn default_sg_raindex() -> SgRaindex { + SgRaindex { + id: SgBytes("0xraindex_id_default".to_string()), } } @@ -150,7 +147,7 @@ mod tests { vault: default_sg_vault_balance_change_vault(), timestamp: SgBigInt("1600000100".to_string()), transaction: default_sg_transaction(), - orderbook: default_sg_orderbook(), + raindex: default_sg_raindex(), trade: default_sg_trade_ref(), } } @@ -177,7 +174,7 @@ mod tests { order: default_sg_trade_struct_partial_order(), input_vault_balance_change: default_sg_trade_vault_balance_change("input"), timestamp: SgBigInt("1600000200".to_string()), - orderbook: default_sg_orderbook(), + raindex: default_sg_raindex(), } } @@ -188,8 +185,8 @@ mod tests { "Trade timestamp mismatch" ); assert_eq!( - actual.orderbook.id, expected.orderbook.id, - "Trade orderbook ID mismatch" + actual.raindex.id, expected.raindex.id, + "Trade raindex ID mismatch" ); // Assert TradeEvent @@ -252,7 +249,7 @@ mod tests { }); let result = client.order_trade_detail(trade_id).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -269,7 +266,7 @@ mod tests { let result = client.order_trade_detail(trade_id).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -371,7 +368,7 @@ mod tests { .await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -502,7 +499,7 @@ mod tests { let result = client.order_trades_list_all(order_id, None, None).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } } diff --git a/crates/subgraph/src/orderbook_client/performance.rs b/crates/subgraph/src/raindex_client/performance.rs similarity index 92% rename from crates/subgraph/src/orderbook_client/performance.rs rename to crates/subgraph/src/raindex_client/performance.rs index 45b185427b..3bc95b2079 100644 --- a/crates/subgraph/src/orderbook_client/performance.rs +++ b/crates/subgraph/src/raindex_client/performance.rs @@ -1,13 +1,13 @@ use super::*; use crate::performance::vol::{get_vaults_vol, VaultVolume}; -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { pub async fn order_vaults_volume( &self, order_id: cynic::Id, start_timestamp: Option, end_timestamp: Option, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let trades = self .order_trades_list_all(order_id, start_timestamp, end_timestamp) .await?; @@ -21,7 +21,7 @@ impl OrderbookSubgraphClient { // order_id: cynic::Id, // start_timestamp: Option, // end_timestamp: Option, - // ) -> Result { + // ) -> Result { // let order = self.order_detail(&order_id).await?; // let trades = self // .order_trades_list_all(order_id, start_timestamp, end_timestamp) @@ -38,9 +38,9 @@ impl OrderbookSubgraphClient { #[cfg(test)] mod tests { use super::*; - use crate::orderbook_client::OrderbookSubgraphClientError; + use crate::raindex_client::RaindexSubgraphClientError; use crate::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderbook, SgTrade, SgTradeEvent, SgTradeEventTypename, + SgBigInt, SgBytes, SgErc20, SgRaindex, SgTrade, SgTradeEvent, SgTradeEventTypename, SgTradeRef, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; @@ -50,9 +50,9 @@ mod tests { use reqwest::Url; use serde_json::json; - fn setup_client(server: &MockServer) -> OrderbookSubgraphClient { + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { let url = Url::parse(&server.url("")).unwrap(); - OrderbookSubgraphClient::new(url) + RaindexSubgraphClient::new(url) } fn default_sg_erc20(id_suffix: &str) -> SgErc20 { @@ -75,8 +75,8 @@ mod tests { id: SgBytes(order_id_str.to_string()), order_hash: SgBytes(format!("0xhash_{}", order_id_str)), }, - orderbook: SgOrderbook { - id: SgBytes("0xorderbook_default".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_default".to_string()), }, trade_event: SgTradeEvent { transaction: SgTransaction { @@ -105,8 +105,8 @@ mod tests { block_number: SgBigInt("1".to_string()), timestamp: SgBigInt(timestamp.to_string()), }, - orderbook: SgOrderbook { - id: SgBytes("0xorderbook_default".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_default".to_string()), }, trade: SgTradeRef { trade_event: SgTradeEventTypename { @@ -132,8 +132,8 @@ mod tests { block_number: SgBigInt("1".to_string()), timestamp: SgBigInt(timestamp.to_string()), }, - orderbook: SgOrderbook { - id: SgBytes("0xorderbook_default".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_default".to_string()), }, trade: SgTradeRef { trade_event: SgTradeEventTypename { @@ -214,7 +214,7 @@ mod tests { let result = client.order_vaults_volume(order_id, None, None).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -231,8 +231,8 @@ mod tests { // order_bytes: SgBytes("0xorderbytes_default".to_string()), // timestamp_added: SgBigInt("1600000000".to_string()), // active: true, - // orderbook: SgOrderbook { - // id: SgBytes("0xorderbook_default".to_string()), + // raindex: SgRaindex { + // id: SgBytes("0xraindex_default".to_string()), // }, // inputs: vec![SgVault { // id: SgBytes("input_vault_id".to_string()), @@ -240,8 +240,8 @@ mod tests { // vault_id: SgBigInt("input_vault_sg_id".to_string()), // balance: SgBigInt("1000".to_string()), // token: default_sg_erc20("input"), - // orderbook: SgOrderbook { - // id: SgBytes("0xorderbook_default".to_string()), + // raindex: SgRaindex { + // id: SgBytes("0xraindex_default".to_string()), // }, // orders_as_output: vec![], // orders_as_input: vec![], @@ -253,8 +253,8 @@ mod tests { // vault_id: SgBigInt("output_vault_sg_id".to_string()), // balance: SgBigInt("0".to_string()), // token: default_sg_erc20("output"), - // orderbook: SgOrderbook { - // id: SgBytes("0xorderbook_default".to_string()), + // raindex: SgRaindex { + // id: SgBytes("0xraindex_default".to_string()), // }, // orders_as_output: vec![], // orders_as_input: vec![], @@ -388,7 +388,7 @@ mod tests { // let result = client.order_performance(order_id, None, None).await; // assert!(result.is_err()); // match result { - // Err(OrderbookSubgraphClientError::PerformanceError(PerformanceError::NoTrades)) => (), + // Err(RaindexSubgraphClientError::PerformanceError(PerformanceError::NoTrades)) => (), // _ => panic!("Expected PerformanceError::NoTrades, got {:?}", result), // } // } @@ -407,7 +407,7 @@ mod tests { // }); // // let result = client.order_performance(order_id, None, None).await; - // assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + // assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); // } // // #[tokio::test] @@ -438,7 +438,7 @@ mod tests { // let result = client.order_performance(order_id, None, None).await; // assert!(matches!( // result, - // Err(OrderbookSubgraphClientError::CynicClientError(_)) + // Err(RaindexSubgraphClientError::CynicClientError(_)) // )); // } } diff --git a/crates/subgraph/src/orderbook_client/token.rs b/crates/subgraph/src/raindex_client/token.rs similarity index 90% rename from crates/subgraph/src/orderbook_client/token.rs rename to crates/subgraph/src/raindex_client/token.rs index f23265ef30..ed607b2315 100644 --- a/crates/subgraph/src/orderbook_client/token.rs +++ b/crates/subgraph/src/raindex_client/token.rs @@ -1,9 +1,9 @@ use super::*; use crate::types::common::SgTokensListAllQuery; -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { /// Fetch all tokens directly from ERC20 entities - pub async fn tokens_list_all(&self) -> Result, OrderbookSubgraphClientError> { + pub async fn tokens_list_all(&self) -> Result, RaindexSubgraphClientError> { let data = self.query::(()).await?; Ok(data.tokens) @@ -18,9 +18,9 @@ mod tests { use reqwest::Url; use serde_json::json; - fn setup_client(server: &MockServer) -> OrderbookSubgraphClient { + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { let url = Url::parse(&server.url("")).unwrap(); - OrderbookSubgraphClient::new(url) + RaindexSubgraphClient::new(url) } #[tokio::test] @@ -94,10 +94,7 @@ mod tests { let result = client.tokens_list_all().await; assert!( - matches!( - result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) - ), + matches!(result, Err(RaindexSubgraphClientError::CynicClientError(_))), "Should return network error when GraphQL request fails" ); } diff --git a/crates/subgraph/src/orderbook_client/transaction.rs b/crates/subgraph/src/raindex_client/transaction.rs similarity index 89% rename from crates/subgraph/src/orderbook_client/transaction.rs rename to crates/subgraph/src/raindex_client/transaction.rs index 34dbcf549e..e0ac9a7c50 100644 --- a/crates/subgraph/src/orderbook_client/transaction.rs +++ b/crates/subgraph/src/raindex_client/transaction.rs @@ -1,16 +1,14 @@ use super::*; -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { pub async fn transaction_detail( &self, id: Id, - ) -> Result { + ) -> Result { let data = self .query::(SgIdQueryVariables { id: &id }) .await?; - let transaction = data - .transaction - .ok_or(OrderbookSubgraphClientError::Empty)?; + let transaction = data.transaction.ok_or(RaindexSubgraphClientError::Empty)?; Ok(transaction) } @@ -18,7 +16,7 @@ impl OrderbookSubgraphClient { pub async fn transaction_add_orders( &self, id: Id, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let data = self .query::( TransactionAddOrdersVariables { @@ -28,7 +26,7 @@ impl OrderbookSubgraphClient { .await?; if data.add_orders.is_empty() { - return Err(OrderbookSubgraphClientError::Empty); + return Err(RaindexSubgraphClientError::Empty); } Ok(data.add_orders) @@ -38,7 +36,7 @@ impl OrderbookSubgraphClient { pub async fn transaction_remove_orders( &self, id: Id, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let data = self .query::( TransactionRemoveOrdersVariables { @@ -48,7 +46,7 @@ impl OrderbookSubgraphClient { .await?; if data.remove_orders.is_empty() { - return Err(OrderbookSubgraphClientError::Empty); + return Err(RaindexSubgraphClientError::Empty); } Ok(data.remove_orders) @@ -59,7 +57,7 @@ impl OrderbookSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgAddOrderWithOrder, SgBigInt, SgBytes, SgErc20, SgOrder, SgOrderbook, + SgAddOrderWithOrder, SgBigInt, SgBytes, SgErc20, SgOrder, SgRaindex, SgRemoveOrderWithOrder, SgTransaction, SgVault, }; use crate::utils::float::*; @@ -68,9 +66,9 @@ mod tests { use reqwest::Url; use serde_json::json; - fn setup_client(server: &MockServer) -> OrderbookSubgraphClient { + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { let url = Url::parse(&server.url("")).unwrap(); - OrderbookSubgraphClient::new(url) + RaindexSubgraphClient::new(url) } fn default_sg_transaction(id_str: &str) -> SgTransaction { @@ -100,8 +98,8 @@ mod tests { order_bytes: SgBytes("0xorderbytes_default_order".to_string()), timestamp_added: SgBigInt("1600000100".to_string()), active: true, - orderbook: SgOrderbook { - id: SgBytes("0xorderbook_default_order".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_default_order".to_string()), }, inputs: vec![SgVault { id: SgBytes("input_vault_id_order".to_string()), @@ -109,8 +107,8 @@ mod tests { vault_id: SgBytes("input_vault_sg_id_order".to_string()), balance: SgBytes(F1000.as_hex()), token: default_sg_erc20("input_order"), - orderbook: SgOrderbook { - id: SgBytes("0xorderbook_default_order".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_default_order".to_string()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -122,8 +120,8 @@ mod tests { vault_id: SgBytes("output_vault_sg_id_order".to_string()), balance: SgBytes(F0.as_hex()), token: default_sg_erc20("output_order"), - orderbook: SgOrderbook { - id: SgBytes("0xorderbook_default_order".to_string()), + raindex: SgRaindex { + id: SgBytes("0xraindex_default_order".to_string()), }, orders_as_output: vec![], orders_as_input: vec![], @@ -222,7 +220,7 @@ mod tests { }); let result = client.transaction_detail(tx_id).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -239,7 +237,7 @@ mod tests { let result = client.transaction_detail(tx_id).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -284,7 +282,7 @@ mod tests { }); let result = client.transaction_add_orders(tx_id).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -301,7 +299,7 @@ mod tests { let result = client.transaction_add_orders(tx_id).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -346,7 +344,7 @@ mod tests { }); let result = client.transaction_remove_orders(tx_id).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -363,7 +361,7 @@ mod tests { let result = client.transaction_remove_orders(tx_id).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } } diff --git a/crates/subgraph/src/orderbook_client/vault.rs b/crates/subgraph/src/raindex_client/vault.rs similarity index 94% rename from crates/subgraph/src/orderbook_client/vault.rs rename to crates/subgraph/src/raindex_client/vault.rs index f09689cac5..b8d059239d 100644 --- a/crates/subgraph/src/orderbook_client/vault.rs +++ b/crates/subgraph/src/raindex_client/vault.rs @@ -2,13 +2,13 @@ use rain_math_float::Float; use super::*; -impl OrderbookSubgraphClient { +impl RaindexSubgraphClient { /// Fetch single vault - pub async fn vault_detail(&self, id: Id) -> Result { + pub async fn vault_detail(&self, id: Id) -> Result { let data = self .query::(SgIdQueryVariables { id: &id }) .await?; - let vault = data.vault.ok_or(OrderbookSubgraphClientError::Empty)?; + let vault = data.vault.ok_or(RaindexSubgraphClientError::Empty)?; Ok(vault) } @@ -18,7 +18,7 @@ impl OrderbookSubgraphClient { &self, filter_args: SgVaultsListFilterArgs, pagination_args: SgPaginationArgs, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let pagination_variables = Self::parse_pagination_args(pagination_args); let balance_not = if filter_args.hide_zero_balance { @@ -34,7 +34,7 @@ impl OrderbookSubgraphClient { order_hash: None, inputs_: None, outputs_: None, - orderbook_in: vec![], + raindex_in: vec![], }; Some(vec![ SgVaultsListQueryFilters { @@ -54,7 +54,7 @@ impl OrderbookSubgraphClient { owner_in: filter_args.owners.clone(), balance_not, token_in: filter_args.tokens.clone(), - orderbook_in: filter_args.orderbooks.clone(), + raindex_in: filter_args.raindexes.clone(), orders_as_input_: None, orders_as_output_: None, or, @@ -63,7 +63,7 @@ impl OrderbookSubgraphClient { let has_filters = !filter_args.owners.is_empty() || filter_args.hide_zero_balance || !filter_args.tokens.is_empty() - || !filter_args.orderbooks.is_empty() + || !filter_args.raindexes.is_empty() || filter_args.only_active_orders; let variables = SgVaultsListQueryVariables { @@ -80,7 +80,7 @@ impl OrderbookSubgraphClient { } /// Fetch all pages of vaults_list query - pub async fn vaults_list_all(&self) -> Result, OrderbookSubgraphClientError> { + pub async fn vaults_list_all(&self) -> Result, RaindexSubgraphClientError> { let mut all_pages_merged = vec![]; let mut page = 1; @@ -91,7 +91,7 @@ impl OrderbookSubgraphClient { owners: vec![], hide_zero_balance: true, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }, SgPaginationArgs { @@ -118,7 +118,7 @@ impl OrderbookSubgraphClient { id: cynic::Id, pagination_args: SgPaginationArgs, filter_typenames: Option<&[&str]>, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let pagination_vars = Self::parse_pagination_args(pagination_args); let res = self .query_paginated( @@ -150,7 +150,7 @@ impl OrderbookSubgraphClient { &self, id: cynic::Id, filter_typenames: Option<&[&str]>, - ) -> Result, OrderbookSubgraphClientError> { + ) -> Result, RaindexSubgraphClientError> { let mut all_pages_merged = vec![]; let mut page = 1; @@ -179,7 +179,7 @@ impl OrderbookSubgraphClient { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgOrderbook, SgVault, SgVaultsListFilterArgs, + SgBigInt, SgBytes, SgErc20, SgOrderAsIO, SgRaindex, SgVault, SgVaultsListFilterArgs, }; use crate::utils::float::*; use cynic::Id; @@ -187,9 +187,9 @@ mod tests { use reqwest::Url; use serde_json::json; - fn setup_client(server: &MockServer) -> OrderbookSubgraphClient { + fn setup_client(server: &MockServer) -> RaindexSubgraphClient { let url = Url::parse(&server.url("")).unwrap(); - OrderbookSubgraphClient::new(url) + RaindexSubgraphClient::new(url) } fn default_sg_erc20() -> SgErc20 { @@ -202,9 +202,9 @@ mod tests { } } - fn default_sg_orderbook() -> SgOrderbook { - SgOrderbook { - id: SgBytes("0xOrderbookId".to_string()), + fn default_sg_raindex() -> SgRaindex { + SgRaindex { + id: SgBytes("0xRaindexId".to_string()), } } @@ -223,7 +223,7 @@ mod tests { vault_id: SgBytes("1234567890".to_string()), balance: SgBytes(F1.as_hex()), token: default_sg_erc20(), - orderbook: default_sg_orderbook(), + raindex: default_sg_raindex(), orders_as_output: vec![default_sg_order_as_io()], orders_as_input: vec![], balance_changes: vec![], @@ -256,8 +256,8 @@ mod tests { "Token decimals mismatch" ); assert_eq!( - actual.orderbook.id, expected.orderbook.id, - "Orderbook ID mismatch" + actual.raindex.id, expected.raindex.id, + "Raindex ID mismatch" ); assert_eq!( actual.orders_as_output.len(), @@ -314,8 +314,8 @@ mod tests { "blockNumber": "100", "timestamp": "1700000000" }, - "orderbook": { - "id": "0xOrderbookId" + "raindex": { + "id": "0xRaindexId" } }) } @@ -353,7 +353,7 @@ mod tests { }); let result = client.vault_detail(vault_id).await; - assert!(matches!(result, Err(OrderbookSubgraphClientError::Empty))); + assert!(matches!(result, Err(RaindexSubgraphClientError::Empty))); } #[tokio::test] @@ -370,7 +370,7 @@ mod tests { let result = client.vault_detail(vault_id).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -382,7 +382,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -418,7 +418,7 @@ mod tests { owners: vec![owner_address.clone()], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -449,7 +449,7 @@ mod tests { owners: vec![], hide_zero_balance: true, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -479,7 +479,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -509,7 +509,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -535,7 +535,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -551,7 +551,7 @@ mod tests { let result = client.vaults_list(filter_args, pagination_args).await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -639,7 +639,7 @@ mod tests { let result = client.vaults_list_all().await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::CynicClientError(_)) + Err(RaindexSubgraphClientError::CynicClientError(_)) )); } @@ -718,7 +718,7 @@ mod tests { .await; assert!(matches!( result, - Err(OrderbookSubgraphClientError::PaginationClientError(_)) + Err(RaindexSubgraphClientError::PaginationClientError(_)) )); } @@ -836,7 +836,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![token_address.clone()], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -869,7 +869,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![token1.clone(), token2.clone()], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -902,7 +902,7 @@ mod tests { owners: vec![owner_address.clone()], hide_zero_balance: true, tokens: vec![token_address.clone()], - orderbooks: vec![], + raindexes: vec![], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -927,15 +927,15 @@ mod tests { } #[tokio::test] - async fn test_vaults_list_with_orderbook_filter() { + async fn test_vaults_list_with_raindex_filter() { let sg_server = MockServer::start_async().await; let client = setup_client(&sg_server); - let orderbook_address = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string(); + let raindex_address = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".to_string(); let filter_args = SgVaultsListFilterArgs { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![orderbook_address.clone()], + raindexes: vec![raindex_address.clone()], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -947,7 +947,7 @@ mod tests { sg_server.mock(|when, then| { when.method(POST) .path("/") - .body_contains(format!("\"orderbook_in\":[\"{}\"]", orderbook_address)); + .body_contains(format!("\"raindex_in\":[\"{}\"]", raindex_address)); then.status(200) .json_body(json!({"data": {"vaults": expected_vaults}})); }); @@ -959,7 +959,7 @@ mod tests { } #[tokio::test] - async fn test_vaults_list_with_multiple_orderbook_filters() { + async fn test_vaults_list_with_multiple_raindex_filters() { let sg_server = MockServer::start_async().await; let client = setup_client(&sg_server); let ob1 = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".to_string(); @@ -968,7 +968,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![ob1.clone(), ob2.clone()], + raindexes: vec![ob1.clone(), ob2.clone()], only_active_orders: false, }; let pagination_args = SgPaginationArgs { @@ -980,7 +980,7 @@ mod tests { sg_server.mock(|when, then| { when.method(POST) .path("/") - .body_contains(format!("\"orderbook_in\":[\"{}\",\"{}\"]", ob1, ob2)); + .body_contains(format!("\"raindex_in\":[\"{}\",\"{}\"]", ob1, ob2)); then.status(200) .json_body(json!({"data": {"vaults": expected_vaults}})); }); @@ -999,7 +999,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: true, }; let pagination_args = SgPaginationArgs { @@ -1034,7 +1034,7 @@ mod tests { owners: vec![owner_address.clone()], hide_zero_balance: true, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: true, }; let pagination_args = SgPaginationArgs { @@ -1070,7 +1070,7 @@ mod tests { owners: vec![], hide_zero_balance: false, tokens: vec![], - orderbooks: vec![], + raindexes: vec![], only_active_orders: true, }; let pagination_args = SgPaginationArgs { diff --git a/crates/subgraph/src/types/common.rs b/crates/subgraph/src/types/common.rs index d3d6e72e1b..e5e1cb68d1 100644 --- a/crates/subgraph/src/types/common.rs +++ b/crates/subgraph/src/types/common.rs @@ -26,7 +26,7 @@ pub struct SgOrdersListFilterArgs { pub order_hash: Option, #[cfg_attr(target_family = "wasm", tsify(optional))] pub tokens: Option, - pub orderbooks: Vec, + pub raindexes: Vec, } impl_wasm_traits!(SgOrdersListFilterArgs); @@ -51,8 +51,8 @@ pub struct SgOrdersListQueryFilters { pub inputs_: Option, #[cynic(rename = "outputs_", skip_serializing_if = "Option::is_none")] pub outputs_: Option, - #[cynic(rename = "orderbook_in", skip_serializing_if = "Vec::is_empty")] - pub orderbook_in: Vec, + #[cynic(rename = "raindex_in", skip_serializing_if = "Vec::is_empty")] + pub raindex_in: Vec, } #[derive(cynic::InputObject, Debug, Clone, Tsify)] @@ -103,8 +103,8 @@ pub struct SgPaginationWithTimestampQueryVariables { } #[derive(cynic::QueryFragment, Debug, Serialize, Clone, Tsify)] -#[cynic(graphql_type = "Orderbook")] -pub struct SgOrderbook { +#[cynic(graphql_type = "Raindex")] +pub struct SgRaindex { pub id: SgBytes, } @@ -121,7 +121,7 @@ pub struct SgOrder { pub owner: SgBytes, pub outputs: Vec, pub inputs: Vec, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, pub active: bool, pub timestamp_added: SgBigInt, #[cfg_attr(target_family = "wasm", tsify(optional))] @@ -163,7 +163,7 @@ pub struct SgVaultsListFilterArgs { pub owners: Vec, pub hide_zero_balance: bool, pub tokens: Vec, - pub orderbooks: Vec, + pub raindexes: Vec, pub only_active_orders: bool, } impl_wasm_traits!(SgVaultsListFilterArgs); @@ -178,8 +178,8 @@ pub struct SgVaultsListQueryFilters { pub balance_not: Option, #[cynic(rename = "token_in", skip_serializing_if = "Vec::is_empty")] pub token_in: Vec, - #[cynic(rename = "orderbook_in", skip_serializing_if = "Vec::is_empty")] - pub orderbook_in: Vec, + #[cynic(rename = "raindex_in", skip_serializing_if = "Vec::is_empty")] + pub raindex_in: Vec, #[cynic(rename = "ordersAsInput_", skip_serializing_if = "Option::is_none")] #[cfg_attr(target_family = "wasm", tsify(optional))] pub orders_as_input_: Option>, @@ -211,7 +211,7 @@ pub struct SgVault { pub vault_id: SgBytes, pub balance: SgBytes, pub token: SgErc20, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, // latest orders #[arguments(orderBy: timestampAdded, orderDirection: desc)] pub orders_as_output: Vec, @@ -250,7 +250,7 @@ pub struct SgVaultBalanceChangeUnwrapped { pub vault: SgVaultBalanceChangeVault, pub timestamp: SgBigInt, pub transaction: SgTransaction, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, } #[derive(cynic::InlineFragments, Debug, Clone, Serialize, Tsify)] @@ -331,7 +331,7 @@ pub struct SgDeposit { pub vault: SgVaultBalanceChangeVault, pub timestamp: SgBigInt, pub transaction: SgTransaction, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, } #[derive(cynic::QueryFragment, Debug, Clone, Serialize, Tsify)] @@ -347,7 +347,7 @@ pub struct SgWithdrawal { pub vault: SgVaultBalanceChangeVault, pub timestamp: SgBigInt, pub transaction: SgTransaction, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, } #[derive(cynic::QueryFragment, Debug, Clone, Serialize, Tsify)] @@ -363,7 +363,7 @@ pub struct SgTradeVaultBalanceChange { pub vault: SgVaultBalanceChangeVault, pub timestamp: SgBigInt, pub transaction: SgTransaction, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, pub trade: SgTradeRef, } @@ -380,7 +380,7 @@ pub struct SgClearBounty { pub vault: SgVaultBalanceChangeVault, pub timestamp: SgBigInt, pub transaction: SgTransaction, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, pub sender: SgBytes, } @@ -416,7 +416,7 @@ pub struct SgTrade { pub order: SgTradeStructPartialOrder, pub input_vault_balance_change: SgTradeVaultBalanceChange, pub timestamp: SgBigInt, - pub orderbook: SgOrderbook, + pub raindex: SgRaindex, } #[derive(cynic::QueryFragment, Debug, Clone, Serialize, Tsify)] @@ -513,12 +513,12 @@ pub enum SgOrderOrderBy { #[cynic(rename = "id")] #[cfg_attr(target_family = "wasm", serde(rename = "id"))] Id, - #[cynic(rename = "orderbook")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook"))] - Orderbook, - #[cynic(rename = "orderbook__id")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook__id"))] - OrderbookId, + #[cynic(rename = "raindex")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex"))] + Raindex, + #[cynic(rename = "raindex__id")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex__id"))] + RaindexId, #[cynic(rename = "active")] #[cfg_attr(target_family = "wasm", serde(rename = "active"))] Active, @@ -591,12 +591,12 @@ pub enum SgAddOrderOrderBy { #[cynic(rename = "order__timestampAdded")] #[cfg_attr(target_family = "wasm", serde(rename = "order__timestampAdded"))] OrderTimestampAdded, - #[cynic(rename = "orderbook")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook"))] - Orderbook, - #[cynic(rename = "orderbook__id")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook__id"))] - OrderbookId, + #[cynic(rename = "raindex")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex"))] + Raindex, + #[cynic(rename = "raindex__id")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex__id"))] + RaindexId, #[cynic(rename = "transaction")] #[cfg_attr(target_family = "wasm", serde(rename = "transaction"))] Transaction, @@ -624,12 +624,12 @@ pub enum SgTradeOrderBy { #[cynic(rename = "id")] #[cfg_attr(target_family = "wasm", serde(rename = "id"))] Id, - #[cynic(rename = "orderbook")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook"))] - Orderbook, - #[cynic(rename = "orderbook__id")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook__id"))] - OrderbookId, + #[cynic(rename = "raindex")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex"))] + Raindex, + #[cynic(rename = "raindex__id")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex__id"))] + RaindexId, #[cynic(rename = "order")] #[cfg_attr(target_family = "wasm", serde(rename = "order"))] Order, @@ -738,12 +738,12 @@ pub enum SgVaultOrderBy { #[cynic(rename = "id")] #[cfg_attr(target_family = "wasm", serde(rename = "id"))] Id, - #[cynic(rename = "orderbook")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook"))] - Orderbook, - #[cynic(rename = "orderbook__id")] - #[cfg_attr(target_family = "wasm", serde(rename = "orderbook__id"))] - OrderbookId, + #[cynic(rename = "raindex")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex"))] + Raindex, + #[cynic(rename = "raindex__id")] + #[cfg_attr(target_family = "wasm", serde(rename = "raindex__id"))] + RaindexId, #[cynic(rename = "token")] #[cfg_attr(target_family = "wasm", serde(rename = "token"))] Token, diff --git a/crates/subgraph/src/types/impls.rs b/crates/subgraph/src/types/impls.rs index 5013ce50c9..c99d0ea543 100644 --- a/crates/subgraph/src/types/impls.rs +++ b/crates/subgraph/src/types/impls.rs @@ -51,7 +51,7 @@ impl SgTrade { mod tests { use super::*; use crate::types::common::{ - SgBigInt, SgBytes, SgOrderbook, SgTradeEvent, SgTradeStructPartialOrder, + SgBigInt, SgBytes, SgRaindex, SgTradeEvent, SgTradeStructPartialOrder, SgTradeVaultBalanceChange, SgTransaction, SgVaultBalanceChangeVault, }; use crate::utils::float::*; @@ -185,7 +185,7 @@ mod tests { block_number: SgBigInt("".to_string()), timestamp: SgBigInt("".to_string()), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("".to_string()), }, trade: SgTradeRef { @@ -213,7 +213,7 @@ mod tests { block_number: SgBigInt("".to_string()), timestamp: SgBigInt("".to_string()), }, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("".to_string()), }, trade: SgTradeRef { @@ -241,7 +241,7 @@ mod tests { order_hash: SgBytes("".to_string()), }, timestamp: SgBigInt("".to_string()), - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("".to_string()), }, } diff --git a/crates/subgraph/src/types/order_detail_traits.rs b/crates/subgraph/src/types/order_detail_traits.rs index 10e0e32578..915f4cb192 100644 --- a/crates/subgraph/src/types/order_detail_traits.rs +++ b/crates/subgraph/src/types/order_detail_traits.rs @@ -5,7 +5,7 @@ use alloy::primitives::{ Address, B256, }; use alloy::sol_types::SolValue; -use rain_orderbook_bindings::IRaindexV6::{OrderV4, IOV2}; +use raindex_bindings::IRaindexV6::{OrderV4, IOV2}; use std::{num::TryFromIntError, str::FromStr}; use thiserror::Error; @@ -49,7 +49,7 @@ impl TryFrom for OrderV4 { mod tests { use alloy::hex; use alloy::primitives::{bytes, B256}; - use rain_orderbook_bindings::IRaindexV6::EvaluableV4; + use raindex_bindings::IRaindexV6::EvaluableV4; use std::vec; use super::*; @@ -96,7 +96,7 @@ mod tests { inputs: vec![], outputs: vec![], meta: None, - orderbook: SgOrderbook { + raindex: SgRaindex { id: SgBytes("1".into()), }, // Only the order_bytes field is used for the conversion diff --git a/crates/subgraph/src/utils/order_id.rs b/crates/subgraph/src/utils/order_id.rs index 37f7097fc0..de20127f2a 100644 --- a/crates/subgraph/src/utils/order_id.rs +++ b/crates/subgraph/src/utils/order_id.rs @@ -1,10 +1,10 @@ use alloy::primitives::{keccak256, Address, B256, U256}; -/// Builds the subgraph represented order ID, given an orderbook address and an order hash -/// An order ID on subgraph is keccak256 of concated orderbook address + order hash -pub fn make_order_id(orderbook: Address, order_hash: U256) -> B256 { +/// Builds the subgraph represented order ID, given a raindex address and an order hash +/// An order ID on subgraph is keccak256 of concated raindex address + order hash +pub fn make_order_id(raindex: Address, order_hash: U256) -> B256 { let mut id_bytes = vec![]; - id_bytes.extend_from_slice(orderbook.as_ref()); + id_bytes.extend_from_slice(raindex.as_ref()); id_bytes.extend_from_slice(&B256::from(order_hash).0); keccak256(id_bytes) } diff --git a/crates/subgraph/src/validate.rs b/crates/subgraph/src/validate.rs index 75287f351d..c124ed34a1 100644 --- a/crates/subgraph/src/validate.rs +++ b/crates/subgraph/src/validate.rs @@ -19,7 +19,7 @@ pub enum SchemaValidationError { /// checks if a schema is equal to this crate's schema fn check_schema(schema: String) -> Result { - let main_schema = read_to_string("./schema/orderbook.graphql")?; + let main_schema = read_to_string("./schema/raindex.graphql")?; Ok(main_schema == schema) } @@ -126,7 +126,7 @@ mod test { #[test] fn test_check_schema_happy() { - let schema = read_to_string("./schema/orderbook.graphql").unwrap(); + let schema = read_to_string("./schema/raindex.graphql").unwrap(); let result = check_schema(schema).unwrap(); assert!(result); } diff --git a/crates/subgraph/src/vault_balance_changes_query.rs b/crates/subgraph/src/vault_balance_changes_query.rs index 4de852e012..1460ecafa1 100644 --- a/crates/subgraph/src/vault_balance_changes_query.rs +++ b/crates/subgraph/src/vault_balance_changes_query.rs @@ -68,7 +68,7 @@ mod tests { use super::*; use crate::cynic_client::CynicClientError; use crate::types::common::{ - SgBigInt, SgBytes, SgDeposit, SgErc20, SgOrderbook, SgPaginationWithIdQueryVariables, + SgBigInt, SgBytes, SgDeposit, SgErc20, SgPaginationWithIdQueryVariables, SgRaindex, SgTransaction, SgVaultBalanceChangeVault, SgWithdrawal, }; use httpmock::prelude::*; @@ -98,9 +98,9 @@ mod tests { } } - fn default_sg_orderbook() -> SgOrderbook { - SgOrderbook { - id: default_sg_bytes("0xOrderbookId"), + fn default_sg_raindex() -> SgRaindex { + SgRaindex { + id: default_sg_bytes("0xRaindexId"), } } @@ -134,7 +134,7 @@ mod tests { id: default_sg_bytes(&format!("0xTransactionId{}", id_suffix)), ..default_sg_transaction() }, - orderbook: default_sg_orderbook(), + raindex: default_sg_raindex(), }) } @@ -151,7 +151,7 @@ mod tests { id: default_sg_bytes(&format!("0xTransactionId{}", id_suffix)), ..default_sg_transaction() }, - orderbook: default_sg_orderbook(), + raindex: default_sg_raindex(), }) } diff --git a/crates/subgraph/tests/batch_order_test.rs b/crates/subgraph/tests/batch_order_test.rs index bc5e06ea6b..cf670968f0 100644 --- a/crates/subgraph/tests/batch_order_test.rs +++ b/crates/subgraph/tests/batch_order_test.rs @@ -1,6 +1,6 @@ use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order::{ +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order::{ SgBatchOrderDetailQuery, SgBatchOrderDetailQueryVariables, SgOrderIdList, }; diff --git a/crates/subgraph/tests/order_test.rs b/crates/subgraph/tests/order_test.rs index a75027a371..503f45bb81 100644 --- a/crates/subgraph/tests/order_test.rs +++ b/crates/subgraph/tests/order_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order::SgOrderDetailByIdQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order::SgOrderDetailByIdQuery; #[test] fn orders_query_gql_output() { diff --git a/crates/subgraph/tests/order_trade_test.rs b/crates/subgraph/tests/order_trade_test.rs index 6e6c1b6b1f..258cca3299 100644 --- a/crates/subgraph/tests/order_trade_test.rs +++ b/crates/subgraph/tests/order_trade_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order_trade::SgOrderTradeDetailQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order_trade::SgOrderTradeDetailQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/subgraph/tests/order_trades_test.rs b/crates/subgraph/tests/order_trades_test.rs index 3216621cf3..1f09873ce7 100644 --- a/crates/subgraph/tests/order_trades_test.rs +++ b/crates/subgraph/tests/order_trades_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order_trade::SgOrderTradesListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order_trade::SgOrderTradesListQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/subgraph/tests/orders_test.rs b/crates/subgraph/tests/orders_test.rs index ac138d6847..903253602d 100644 --- a/crates/subgraph/tests/orders_test.rs +++ b/crates/subgraph/tests/orders_test.rs @@ -1,6 +1,6 @@ use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::order::SgOrdersListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::order::SgOrdersListQuery; #[test] fn orders_query_gql_output() { diff --git a/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap b/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap index 51d9da6174..c28cd6dce8 100644 --- a/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/batch_order_test__batch_order_query_gql_output.snap @@ -21,7 +21,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -60,7 +60,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -88,7 +88,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -121,7 +121,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -149,7 +149,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } sender @@ -168,7 +168,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -207,7 +207,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -235,7 +235,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -268,7 +268,7 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -296,14 +296,14 @@ query SgBatchOrderDetailQuery($id_list: Order_filter!) { blockNumber timestamp } - orderbook { + raindex { id } sender } } } - orderbook { + raindex { id } active diff --git a/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap b/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap index a8e357fb7b..6f4e4f65c1 100644 --- a/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/order_test__orders_query_gql_output.snap @@ -21,7 +21,7 @@ query SgOrderDetailByIdQuery($id: ID!) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -60,7 +60,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -88,7 +88,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -121,7 +121,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -149,7 +149,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } sender @@ -168,7 +168,7 @@ query SgOrderDetailByIdQuery($id: ID!) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -207,7 +207,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -235,7 +235,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -268,7 +268,7 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -296,14 +296,14 @@ query SgOrderDetailByIdQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } sender } } } - orderbook { + raindex { id } active diff --git a/crates/subgraph/tests/snapshots/order_trade_test__vaults_query_gql_output.snap b/crates/subgraph/tests/snapshots/order_trade_test__vaults_query_gql_output.snap index b3d715895f..e52071d8e3 100644 --- a/crates/subgraph/tests/snapshots/order_trade_test__vaults_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/order_trade_test__vaults_query_gql_output.snap @@ -39,7 +39,7 @@ query SgOrderTradeDetailQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -76,7 +76,7 @@ query SgOrderTradeDetailQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -86,7 +86,7 @@ query SgOrderTradeDetailQuery($id: ID!) { } } timestamp - orderbook { + raindex { id } } diff --git a/crates/subgraph/tests/snapshots/order_trades_test__vaults_query_gql_output.snap b/crates/subgraph/tests/snapshots/order_trades_test__vaults_query_gql_output.snap index c2c056004d..22c3a24ede 100644 --- a/crates/subgraph/tests/snapshots/order_trades_test__vaults_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/order_trades_test__vaults_query_gql_output.snap @@ -39,7 +39,7 @@ query SgOrderTradesListQuery($first: Int, $id: Bytes!, $skip: Int, $timestampGte blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -76,7 +76,7 @@ query SgOrderTradesListQuery($first: Int, $id: Bytes!, $skip: Int, $timestampGte blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -86,7 +86,7 @@ query SgOrderTradesListQuery($first: Int, $id: Bytes!, $skip: Int, $timestampGte } } timestamp - orderbook { + raindex { id } } diff --git a/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap b/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap index 90f505a304..cb4578020e 100644 --- a/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/orders_test__orders_query_gql_output.snap @@ -21,7 +21,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -60,7 +60,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -88,7 +88,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -121,7 +121,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -149,7 +149,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } sender @@ -168,7 +168,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -207,7 +207,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -235,7 +235,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -268,7 +268,7 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -296,14 +296,14 @@ query SgOrdersListQuery($first: Int, $skip: Int, $filters: Order_filter) { blockNumber timestamp } - orderbook { + raindex { id } sender } } } - orderbook { + raindex { id } active diff --git a/crates/subgraph/tests/snapshots/vault_balance_changes_test__vault_balance_changes_list_query_gql_output.snap b/crates/subgraph/tests/snapshots/vault_balance_changes_test__vault_balance_changes_list_query_gql_output.snap index c6c246ed56..7dc6a085c3 100644 --- a/crates/subgraph/tests/snapshots/vault_balance_changes_test__vault_balance_changes_list_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/vault_balance_changes_test__vault_balance_changes_list_query_gql_output.snap @@ -30,7 +30,7 @@ query SgVaultBalanceChangesListQuery($first: Int, $id: Bytes!, $skip: Int) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -58,7 +58,7 @@ query SgVaultBalanceChangesListQuery($first: Int, $id: Bytes!, $skip: Int) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -91,7 +91,7 @@ query SgVaultBalanceChangesListQuery($first: Int, $id: Bytes!, $skip: Int) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -119,7 +119,7 @@ query SgVaultBalanceChangesListQuery($first: Int, $id: Bytes!, $skip: Int) { blockNumber timestamp } - orderbook { + raindex { id } sender diff --git a/crates/subgraph/tests/snapshots/vault_test__vaults_query_gql_output.snap b/crates/subgraph/tests/snapshots/vault_test__vaults_query_gql_output.snap index cc154e2af3..186961574a 100644 --- a/crates/subgraph/tests/snapshots/vault_test__vaults_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/vault_test__vaults_query_gql_output.snap @@ -16,7 +16,7 @@ query SgVaultDetailQuery($id: ID!) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -55,7 +55,7 @@ query SgVaultDetailQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -83,7 +83,7 @@ query SgVaultDetailQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -116,7 +116,7 @@ query SgVaultDetailQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -144,7 +144,7 @@ query SgVaultDetailQuery($id: ID!) { blockNumber timestamp } - orderbook { + raindex { id } sender diff --git a/crates/subgraph/tests/snapshots/vaults_test__vaults_query_gql_output.snap b/crates/subgraph/tests/snapshots/vaults_test__vaults_query_gql_output.snap index 72b0fcae73..62c289ad84 100644 --- a/crates/subgraph/tests/snapshots/vaults_test__vaults_query_gql_output.snap +++ b/crates/subgraph/tests/snapshots/vaults_test__vaults_query_gql_output.snap @@ -16,7 +16,7 @@ query SgVaultsListQuery($first: Int, $skip: Int, $filters: Vault_filter) { symbol decimals } - orderbook { + raindex { id } ordersAsOutput(orderBy: timestampAdded, orderDirection: desc) { @@ -55,7 +55,7 @@ query SgVaultsListQuery($first: Int, $skip: Int, $filters: Vault_filter) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -83,7 +83,7 @@ query SgVaultsListQuery($first: Int, $skip: Int, $filters: Vault_filter) { blockNumber timestamp } - orderbook { + raindex { id } trade { @@ -116,7 +116,7 @@ query SgVaultsListQuery($first: Int, $skip: Int, $filters: Vault_filter) { blockNumber timestamp } - orderbook { + raindex { id } } @@ -144,7 +144,7 @@ query SgVaultsListQuery($first: Int, $skip: Int, $filters: Vault_filter) { blockNumber timestamp } - orderbook { + raindex { id } sender diff --git a/crates/subgraph/tests/vault_balance_changes_test.rs b/crates/subgraph/tests/vault_balance_changes_test.rs index 5c52c548c8..ac0a6ddcab 100644 --- a/crates/subgraph/tests/vault_balance_changes_test.rs +++ b/crates/subgraph/tests/vault_balance_changes_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::vault::SgVaultBalanceChangesListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::vault::SgVaultBalanceChangesListQuery; #[test] fn vault_balance_changes_list_query_gql_output() { diff --git a/crates/subgraph/tests/vault_test.rs b/crates/subgraph/tests/vault_test.rs index 6ca690b1c9..cacdfd9dd4 100644 --- a/crates/subgraph/tests/vault_test.rs +++ b/crates/subgraph/tests/vault_test.rs @@ -1,7 +1,7 @@ use cynic::Id; use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::vault::SgVaultDetailQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::vault::SgVaultDetailQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/subgraph/tests/vaults_test.rs b/crates/subgraph/tests/vaults_test.rs index d70917243f..d697c8c62b 100644 --- a/crates/subgraph/tests/vaults_test.rs +++ b/crates/subgraph/tests/vaults_test.rs @@ -1,6 +1,6 @@ use insta::assert_snapshot; -use rain_orderbook_subgraph_client::types::common::*; -use rain_orderbook_subgraph_client::types::vault::SgVaultsListQuery; +use raindex_subgraph_client::types::common::*; +use raindex_subgraph_client::types::vault::SgVaultsListQuery; #[test] fn vaults_query_gql_output() { diff --git a/crates/test_fixtures/Cargo.toml b/crates/test_fixtures/Cargo.toml index 404446079c..9971db1027 100644 --- a/crates/test_fixtures/Cargo.toml +++ b/crates/test_fixtures/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rain_orderbook_test_fixtures" +name = "raindex_test_fixtures" version.workspace = true edition.workspace = true license.workspace = true diff --git a/crates/test_fixtures/src/lib.rs b/crates/test_fixtures/src/lib.rs index a4382875eb..d16030cb62 100644 --- a/crates/test_fixtures/src/lib.rs +++ b/crates/test_fixtures/src/lib.rs @@ -23,12 +23,12 @@ use rain_math_float::Float; sol!( #![sol(all_derives = true, rpc = true)] - Orderbook, "../../out/OrderBookV6.sol/OrderBookV6.json" + Raindex, "../../out/RaindexV6.sol/RaindexV6.json" ); sol!( #![sol(all_derives = true, rpc = true)] - OrderbookSubParser, "../../out/OrderBookV6SubParser.sol/OrderBookV6SubParser.json" + RaindexSubParser, "../../out/RaindexV6SubParser.sol/RaindexV6SubParser.json" ); sol!( @@ -52,12 +52,11 @@ pub struct LocalEvm { /// The alloy provider instance of this local blockchain pub provider: LocalEvmProvider, - /// Alloy orderbook contract instance deployed on this blockchain - pub orderbook: Orderbook::OrderbookInstance, + /// Alloy raindex contract instance deployed on this blockchain + pub raindex: Raindex::RaindexInstance, - /// Alloy orderbook subparser contract instance deployed on this blockchain - pub orderbook_subparser: - OrderbookSubParser::OrderbookSubParserInstance, + /// Alloy raindex subparser contract instance deployed on this blockchain + pub raindex_subparser: RaindexSubParser::RaindexSubParserInstance, /// Alloy interpreter contract instance deployed on this blockchain pub interpreter: Interpreter::InterpreterInstance, @@ -152,9 +151,9 @@ impl LocalEvm { .await .unwrap(); - // deploy orderbook contracts - let orderbook = Orderbook::deploy(provider.clone()).await.unwrap(); - let orderbook_subparser = OrderbookSubParser::deploy(provider.clone()).await.unwrap(); + // deploy raindex contracts + let raindex = Raindex::deploy(provider.clone()).await.unwrap(); + let raindex_subparser = RaindexSubParser::deploy(provider.clone()).await.unwrap(); // set the multicall 3 contract at its official address provider @@ -174,8 +173,8 @@ impl LocalEvm { Self { anvil, provider, - orderbook, - orderbook_subparser, + raindex, + raindex_subparser, interpreter, store, parser, @@ -292,7 +291,7 @@ impl LocalEvm { decimals: u8, vault_id: B256, ) -> ( - Orderbook::AddOrderV3, + Raindex::AddOrderV3, AnyTransactionReceipt, AnyTransactionReceipt, ) { @@ -310,11 +309,11 @@ impl LocalEvm { &self, add_order_calldata: &[u8], from: Address, - ) -> (Orderbook::AddOrderV3, AnyTransactionReceipt) { + ) -> (Raindex::AddOrderV3, AnyTransactionReceipt) { let tx_req = WithOtherFields::new( TransactionRequest::default() .with_input(add_order_calldata.to_vec()) - .with_to(*self.orderbook.address()) + .with_to(*self.raindex.address()) .with_from(from), ); @@ -326,7 +325,7 @@ impl LocalEvm { .inner .logs() .iter() - .find_map(|v| v.log_decode::().ok()) + .find_map(|v| v.log_decode::().ok()) .unwrap() .inner .data; @@ -351,7 +350,7 @@ impl LocalEvm { .expect("Token with given address is not deployed"); let tx = token_contract - .approve(*self.orderbook.address(), deposit_amount) + .approve(*self.raindex.address(), deposit_amount) .from(from) .into_transaction_request(); @@ -362,7 +361,7 @@ impl LocalEvm { .get_inner(); let tx = self - .orderbook + .raindex .deposit4(token, vault_id, raw_deposit_amount, vec![]) .from(from) .into_transaction_request(); diff --git a/flake.nix b/flake.nix index c3a5f1f4ad..9a96005901 100644 --- a/flake.nix +++ b/flake.nix @@ -23,26 +23,26 @@ mkdir -p meta; forge script --silent ./script/BuildAuthoringMeta.sol; rain meta build \ - -i <(cat ./meta/OrderBookV6SubParserAuthoringMeta.rain.meta) \ + -i <(cat ./meta/RaindexV6SubParserAuthoringMeta.rain.meta) \ -m authoring-meta-v2 \ -t cbor \ -e deflate \ -l none \ - -o meta/OrderBookV6SubParser.rain.meta \ + -o meta/RaindexV6SubParser.rain.meta \ ; ''; }; - ob-rs-test = rainix.mkTask.${system} { - name = "ob-rs-test"; + raindex-rs-test = rainix.mkTask.${system} { + name = "raindex-rs-test"; body = '' set -euxo pipefail cargo test --workspace ''; }; - ob-ui-components-prelude = rainix.mkTask.${system} { - name = "ob-ui-components-prelude"; + raindex-ui-components-prelude = rainix.mkTask.${system} { + name = "raindex-ui-components-prelude"; body = '' set -euxo pipefail @@ -56,23 +56,23 @@ ]; }; - rainix-ob-cli-artifact = rainix.mkTask.${system} { - name = "rainix-ob-cli-artifact"; + raindex-cli-artifact = rainix.mkTask.${system} { + name = "raindex-cli-artifact"; body = '' set -euxo pipefail OUTPUT_DIR=crates/cli/bin - ARCHIVE_NAME=rain-orderbook-cli.tar.gz - BINARY_NAME=rain-orderbook-cli + ARCHIVE_NAME=raindex-cli.tar.gz + BINARY_NAME=raindex-cli TARGET_TRIPLE=x86_64-unknown-linux-gnu - cargo build --release -p rain_orderbook_cli --target "$TARGET_TRIPLE" + cargo build --release -p raindex_cli --target "$TARGET_TRIPLE" mkdir -p "$OUTPUT_DIR" rm -f "$OUTPUT_DIR/$ARCHIVE_NAME" - cp "target/$TARGET_TRIPLE/release/rain_orderbook_cli" "$OUTPUT_DIR/$BINARY_NAME" + cp "target/$TARGET_TRIPLE/release/raindex_cli" "$OUTPUT_DIR/$BINARY_NAME" chmod 755 "$OUTPUT_DIR/$BINARY_NAME" strip "$OUTPUT_DIR/$BINARY_NAME" || true @@ -87,7 +87,7 @@ body = '' set -euxo pipefail - cargo build --profile release-wasm --target wasm32-unknown-unknown --lib -p rain_orderbook_js_api + cargo build --profile release-wasm --target wasm32-unknown-unknown --lib -p raindex_js_api ''; }; @@ -96,7 +96,7 @@ body = '' set -euxo pipefail - CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner' cargo test --target wasm32-unknown-unknown --lib -p rain_orderbook_quote -p rain_orderbook_bindings -p rain_orderbook_js_api -p rain_orderbook_common + CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER='wasm-bindgen-test-runner' cargo test --target wasm32-unknown-unknown --lib -p raindex_quote -p raindex_bindings -p raindex_js_api -p raindex_common ''; }; @@ -121,7 +121,7 @@ name = "js-install"; body = '' set -euxo pipefail - cd packages/orderbook + cd packages/raindex npm install --no-check ''; }; @@ -130,7 +130,7 @@ name = "build-js-bindings"; body = '' set -euxo pipefail - cd packages/orderbook + cd packages/raindex npm run build ''; }; @@ -139,7 +139,7 @@ name = "test-js-bindings"; body = '' set -euxo pipefail - cd packages/orderbook + cd packages/raindex npm install --no-check npm run build npm test @@ -151,7 +151,7 @@ devShells.default = pkgs.mkShell { packages = [ packages.raindex-prelude - packages.ob-rs-test + packages.raindex-rs-test packages.rainix-wasm-artifacts packages.rainix-wasm-test packages.rainix-wasm-browser-test @@ -159,8 +159,8 @@ packages.build-js-bindings packages.test-js-bindings rain.defaultPackage.${system} - packages.ob-ui-components-prelude - packages.rainix-ob-cli-artifact + packages.raindex-ui-components-prelude + packages.raindex-cli-artifact ]; shellHook = rainix.devShells.${system}.default.shellHook; diff --git a/foundry.lock b/foundry.lock index f0d37918b3..0e9c2b06f0 100644 --- a/foundry.lock +++ b/foundry.lock @@ -3,10 +3,10 @@ "rev": "43a6ed3a98f0141e1963b4b9136e8c80e2889bd1" }, "lib/rain.interpreter": { - "rev": "2780cdd642398ce4eee4e699363ce100cdc4ef60" + "rev": "1ea41cd004a926e3a964ba5498654f3cd538f139" }, "lib/rain.raindex.interface": { - "rev": "ad4427dcb07e6df95def94999799470db89321b3" + "rev": "9e2da33b477e16bb2c2dc16b29de98d4cbe9dd94" }, "lib/sushixswap-v2": { "rev": "ca38c64cf7c3042f6427414d7bff61c54293da51" diff --git a/foundry.toml b/foundry.toml index 5f0694e3f1..57fc4ef680 100644 --- a/foundry.toml +++ b/foundry.toml @@ -18,7 +18,7 @@ evm_version = "cancun" # optimizer settings for snapshotting. optimizer = true # Lowered from 1000000 → 1000 → 800 to stay under the EIP-170 24KB contract -# size limit. At 1000 runs OrderBookV6 was 24,650 bytes (74 over); at 800 it +# size limit. At 1000 runs RaindexV6 was 24,650 bytes (74 over); at 800 it # is 23,437 bytes (1,139 under). optimizer_runs = 800 @@ -33,7 +33,7 @@ fs_permissions = [ { access = "read", path = "./lib/rain.interpreter/deployments/latest/RainterpreterStoreNPE2" }, { access = "read", path = "./lib/rain.interpreter/deployments/latest/RainterpreterNPE2" }, { access = "read", path = "./lib/rain.interpreter/deployments/latest/RainterpreterExpressionDeployerNPE2" }, - { access = "read-write", path = "./meta/OrderBookV6SubParserAuthoringMeta.rain.meta"}, + { access = "read-write", path = "./meta/RaindexV6SubParserAuthoringMeta.rain.meta"}, { access = "read-write", path = "src/generated" }, { access = "read", path = "./subgraph" }, ] diff --git a/lib/rain.interpreter b/lib/rain.interpreter index 96608b8023..1ea41cd004 160000 --- a/lib/rain.interpreter +++ b/lib/rain.interpreter @@ -1 +1 @@ -Subproject commit 96608b8023a564eed2e96c69cfb3255cb2bbfdb7 +Subproject commit 1ea41cd004a926e3a964ba5498654f3cd538f139 diff --git a/lib/rain.raindex.interface b/lib/rain.raindex.interface index ad4427dcb0..9e2da33b47 160000 --- a/lib/rain.raindex.interface +++ b/lib/rain.raindex.interface @@ -1 +1 @@ -Subproject commit ad4427dcb07e6df95def94999799470db89321b3 +Subproject commit 9e2da33b477e16bb2c2dc16b29de98d4cbe9dd94 diff --git a/package-lock.json b/package-lock.json index 1373c977af..bc267ef199 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,7 @@ ], "dependencies": { "@fast-check/vitest": "0.2.0", - "@rainlanguage/orderbook": "workspace:*", + "@rainlanguage/raindex": "workspace:*", "@rainlanguage/sqlite-web": "^0.0.2", "@rainlanguage/ui-components": "workspace:*", "@reown/appkit": "1.6.4", @@ -2980,8 +2980,8 @@ "node": ">=22" } }, - "node_modules/@rainlanguage/orderbook": { - "resolved": "packages/orderbook", + "node_modules/@rainlanguage/raindex": { + "resolved": "packages/raindex", "link": true }, "node_modules/@rainlanguage/sqlite-web": { @@ -8281,9 +8281,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", - "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -10470,12 +10470,12 @@ } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -17675,8 +17675,8 @@ } } }, - "packages/orderbook": { - "name": "@rainlanguage/orderbook", + "packages/raindex": { + "name": "@rainlanguage/raindex", "version": "0.0.1-alpha.229", "license": "LicenseRef-DCL-1.0", "dependencies": { @@ -17690,22 +17690,50 @@ "node": ">=22" } }, - "packages/orderbook/node_modules/brace-expansion": { - "version": "2.0.1", + "packages/raindex/node_modules/@isaacs/cliui": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", + "integrity": "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "packages/raindex/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "packages/raindex/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" } }, - "packages/orderbook/node_modules/glob": { - "version": "11.0.0", + "packages/raindex/node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" @@ -17720,12 +17748,14 @@ "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/jackspeak": { - "version": "4.0.2", + "packages/raindex/node_modules/jackspeak": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.2.3.tgz", + "integrity": "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "@isaacs/cliui": "^9.0.0" }, "engines": { "node": "20 || >=22" @@ -17734,30 +17764,36 @@ "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/lru-cache": { - "version": "11.0.2", + "packages/raindex/node_modules/lru-cache": { + "version": "11.2.7", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.7.tgz", + "integrity": "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" } }, - "packages/orderbook/node_modules/minimatch": { - "version": "10.0.1", + "packages/raindex/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^5.0.5" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/path-scurry": { - "version": "2.0.0", + "packages/raindex/node_modules/path-scurry": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.2.tgz", + "integrity": "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==", "dev": true, "license": "BlueOak-1.0.0", "dependencies": { @@ -17765,14 +17801,16 @@ "minipass": "^7.1.2" }, "engines": { - "node": "20 || >=22" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "packages/orderbook/node_modules/rimraf": { + "packages/raindex/node_modules/rimraf": { "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", + "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", "dev": true, "license": "ISC", "dependencies": { @@ -17798,7 +17836,7 @@ "@fontsource/dm-sans": "5.1.0", "@imask/svelte": "7.6.1", "@observablehq/plot": "0.6.16", - "@rainlanguage/orderbook": "0.0.1-alpha.229", + "@rainlanguage/raindex": "0.0.1-alpha.229", "@reown/appkit": "1.6.4", "@reown/appkit-adapter-wagmi": "1.6.4", "@sentry/sveltekit": "7.120.0", diff --git a/package.json b/package.json index 17107eeb38..d6b06a623a 100644 --- a/package.json +++ b/package.json @@ -5,19 +5,19 @@ "private": true, "repository": { "type": "git", - "url": "https://github.com/rainlanguage/rain.orderbook.git" + "url": "https://github.com/rainlanguage/raindex.git" }, "keywords": [], "bugs": { - "url": "https://github.com/rainlanguage/rain.orderbook/issues" + "url": "https://github.com/rainlanguage/raindex/issues" }, - "homepage": "https://github.com/rainlanguage/rain.orderbook#readme", + "homepage": "https://github.com/rainlanguage/raindex#readme", "engines": { "node": ">=18" }, "scripts": { "build": "npm run build --workspaces", - "build:orderbook": "npm run build -w @rainlanguage/orderbook", + "build:raindex": "npm run build -w @rainlanguage/raindex", "build:ui": "npm run build -w @rainlanguage/ui-components && npm run build -w @rainlanguage/webapp", "dev": "npm run dev --workspaces", "test": "npm run test --workspaces", @@ -74,7 +74,7 @@ ], "dependencies": { "@fast-check/vitest": "0.2.0", - "@rainlanguage/orderbook": "workspace:*", + "@rainlanguage/raindex": "workspace:*", "@rainlanguage/sqlite-web": "^0.0.2", "@rainlanguage/ui-components": "workspace:*", "@reown/appkit": "1.6.4", diff --git a/packages/orderbook/.gitignore b/packages/raindex/.gitignore similarity index 100% rename from packages/orderbook/.gitignore rename to packages/raindex/.gitignore diff --git a/packages/orderbook/.prettierrc b/packages/raindex/.prettierrc similarity index 100% rename from packages/orderbook/.prettierrc rename to packages/raindex/.prettierrc diff --git a/packages/orderbook/ARCHITECTURE.md b/packages/raindex/ARCHITECTURE.md similarity index 52% rename from packages/orderbook/ARCHITECTURE.md rename to packages/raindex/ARCHITECTURE.md index 9294432a70..a05dc20790 100644 --- a/packages/orderbook/ARCHITECTURE.md +++ b/packages/raindex/ARCHITECTURE.md @@ -1,6 +1,6 @@ -# @rainlanguage/orderbook — Architecture +# @rainlanguage/raindex — Architecture -This package is the JavaScript/TypeScript SDK that exposes Rain Orderbook functionality to web and Node.js consumers. It packages the Rust WASM crate surface (primarily `rain_orderbook_js_api`, plus re‑exports from sibling crates) into a single, installable NPM module with CJS and ESM entry points. +This package is the JavaScript/TypeScript SDK that exposes Raindex functionality to web and Node.js consumers. It packages the Rust WASM crate surface (primarily `raindex_js_api`, plus re-exports from sibling crates) into a single, installable NPM module with CJS and ESM entry points. The SDK is designed to work in browsers, Node.js, and hybrid runtimes. It embeds the compiled `.wasm` bytes directly in the published bundle so consumers do not need network fetches or filesystem access at runtime. @@ -8,17 +8,17 @@ The SDK is designed to work in browsers, Node.js, and hybrid runtimes. It embeds ## Overview - Purpose - - Provide a WASM‑backed API for: YAML parsing/validation, orderbook queries (subgraph), quoting, vault management, transaction calldata generation (add/remove, deposit/withdraw), GUI helpers to deploy orders from dotrain, and low‑level hashing/ABI helpers. + - Provide a WASM-backed API for: YAML parsing/validation, raindex queries (subgraph), quoting, vault management, transaction calldata generation (add/remove, deposit/withdraw), GUI helpers to deploy orders from dotrain, and low-level hashing/ABI helpers. - Targets - ESM (browser) and CJS (Node.js) builds are both published. - - The WASM is base64‑embedded to avoid runtime `fetch`/`fs` requirements. + - The WASM is base64-embedded to avoid runtime `fetch`/`fs` requirements. - Upstream crates - - Backed by `rain_orderbook_js_api` (WASM cdylib) which re‑exports `rain_orderbook_app_settings`, `rain_orderbook_common`, and `rain_orderbook_subgraph_client` for a unified JS surface. + - Backed by `raindex_js_api` (WASM cdylib) which re-exports `raindex_app_settings`, `raindex_common`, and `raindex_subgraph_client` for a unified JS surface. Typical import ```ts -import { RaindexClient, DotrainOrderGui, parseYaml, getOrderHash } from "@rainlanguage/orderbook"; +import { RaindexClient, DotrainOrderGui, parseYaml, getOrderHash } from "@rainlanguage/raindex"; ``` @@ -27,19 +27,19 @@ import { RaindexClient, DotrainOrderGui, parseYaml, getOrderHash } from "@rainla All builds should be run inside a Nix shell to ensure toolchain parity (`nix develop -c `). - Entry generation (`scripts/build.js`) - - Writes thin top‑level entry files: `cjs.js` (CommonJS re‑export), `esm.js` (ESM re‑export), plus `.d.ts` stubs. + - Writes thin top-level entry files: `cjs.js` (CommonJS re-export), `esm.js` (ESM re-export), plus `.d.ts` stubs. - Creates `dist/cjs` and `dist/esm` directories. - Invokes `npm run build-wasm` to compile the Rust workspace to `wasm32-unknown-unknown` in release mode (excludes CLI and integration tests). - For each package (currently just `js_api`), calls `scripts/buildPackage.js` to produce JS bindings and package artifacts. - WASM binding & embedding (`scripts/buildPackage.js`) - Runs `wasm-bindgen` twice to generate Node (CJS) and Web (ESM) wrappers from the compiled `.wasm`. The `wasm-bindgen` binary comes from the Nix environment. - - Reads the generated `.wasm` files and writes `dist/cjs/orderbook_wbg.json` and `dist/esm/orderbook_wbg.json` containing base64‑encoded bytes. + - Reads the generated `.wasm` files and writes `dist/cjs/raindex_wbg.json` and `dist/esm/raindex_wbg.json` containing base64-encoded bytes. - Rewrites the generated JS to: - CJS: read bytes from the embedded JSON via `Buffer.from(base64)` and initialize the module without touching the filesystem. - - ESM: import the embedded JSON and use top‑level `await __wbg_init(bytes)` to initialize the WASM before exporting symbols. - - Copies type declarations to `dist/*/index.d.ts` and prefixes generated files with a note that they are auto‑generated. + - ESM: import the embedded JSON and use top-level `await __wbg_init(bytes)` to initialize the WASM before exporting symbols. + - Copies type declarations to `dist/*/index.d.ts` and prefixes generated files with a note that they are auto-generated. - Prepublish bootstrap (`scripts/setup.js`) - - If `./dist` exists, exits early (supporting installs from already‑built tarballs). + - If `./dist` exists, exits early (supporting installs from already-built tarballs). - Otherwise, cleans temp/outputs and runs the full build inside Nix: `nix develop -c node scripts/build`. - Type checking & tests - `npm run check` runs `tsc` over the built JS to validate the emitted types. @@ -54,52 +54,52 @@ Key commands ## Directory Layout -- `cjs.js`, `esm.js` — Top‑level re‑exports pointing at `dist/` (published files). -- `cjs.d.ts`, `esm.d.ts` — Type re‑export stubs for consumers. +- `cjs.js`, `esm.js` — Top-level re-exports pointing at `dist/` (published files). +- `cjs.d.ts`, `esm.d.ts` — Type re-export stubs for consumers. - `dist/` — Build output (published) - `cjs/` - - `index.js` — Auto‑generated CommonJS glue that initializes WASM from `orderbook_wbg.json`. + - `index.js` — Auto-generated CommonJS glue that initializes WASM from `raindex_wbg.json`. - `index.d.ts` — Type declarations. - - `orderbook_wbg.json` — Base64‑encoded WASM bytes. + - `raindex_wbg.json` — Base64-encoded WASM bytes. - `esm/` - - `index.js` — Auto‑generated ESM glue with top‑level `await` for WASM init. + - `index.js` — Auto-generated ESM glue with top-level `await` for WASM init. - `index.d.ts` — Type declarations. - - `orderbook_wbg.json` — Base64‑encoded WASM bytes. + - `raindex_wbg.json` — Base64-encoded WASM bytes. - `scripts/` - `build.js` — Orchestrates the full build. - `buildPackage.js` — Runs `wasm-bindgen`, embeds WASM, writes JS/TS outputs. - `setup.js` — Prepublish bootstrap inside Nix. - `test/` — Vitest suites exercising bindings (bindings/common/js_api). - `typedoc.json`, `tsconfig.json` — Documentation and TS settings for the published surface. -- `README.md` — End‑user SDK guide with examples. +- `README.md` — End-user SDK guide with examples. ## Exports & API Surface -The package re‑exports the WASM‑bound API from the Rust crates. Representative items: +The package re-exports the WASM-bound API from the Rust crates. Representative items: - Functions - `parseYaml`, `getOrderHash`, `getTakeOrders3Calldata`, `keccak256`, `keccak256HexString`. -- High‑level classes (selected) - - `RaindexClient` — orderbook queries (orders, trades, vaults, quotes, transactions) across configured networks/subgraphs. Constructor is async (`await RaindexClient.new(...)`) and accepts optional `queryCallback` (for applying fetched records to the local DB), `wipeCallback` (for cleaning up stale data during full re-sync), and `statusCallback` (for reporting sync progress/errors to the caller) args for local DB sync when the YAML has `local-db-sync` sections. The sync scheduler starts automatically when configured and shuts down via Drop. +- High-level classes (selected) + - `RaindexClient` — raindex queries (orders, trades, vaults, quotes, transactions) across configured networks/subgraphs. Constructor is async (`await RaindexClient.new(...)`) and accepts optional `queryCallback` (for applying fetched records to the local DB), `wipeCallback` (for cleaning up stale data during full re-sync), and `statusCallback` (for reporting sync progress/errors to the caller) args for local DB sync when the YAML has `local-db-sync` sections. The sync scheduler starts automatically when configured and shuts down via Drop. - `RaindexOrder`, `RaindexVault`, `RaindexTrade`, `RaindexTransaction`, `RaindexVaultsList`, etc. - - `DotrainOrder`, `DotrainOrderGui`, `DotrainRegistry` — dotrain parsing, GUI orchestration, registry fetching (including `getOrderbookYaml()` for token queries), and deployment calldata. - - `OrderbookYaml` — typed access to networks, tokens (via `getTokens()`), orderbooks, subgraphs, deployers, accounts, metaboards. - - `Float` — arbitrary‑precision float utilities used across the API. + - `DotrainOrder`, `DotrainOrderGui`, `DotrainRegistry` — dotrain parsing, GUI orchestration, registry fetching (including `getRaindexYaml()` for token queries), and deployment calldata. + - `RaindexYaml` — typed access to networks, tokens (via `getTokens()`), raindexes, subgraphs, deployers, accounts, metaboards. + - `Float` — arbitrary-precision float utilities used across the API. - Errors & results - - Most methods return `WasmEncodedResult` with either `{ value }` or `{ error: { msg, readableMsg } }` for ergonomic, user‑readable error handling in JS. + - Most methods return `WasmEncodedResult` with either `{ value }` or `{ error: { msg, readableMsg } }` for ergonomic, user-readable error handling in JS. Notes on runtime behavior -- ESM builds use top‑level `await` to initialize the WASM module before exports are used. Ensure your bundler/runtime supports top‑level await. +- ESM builds use top-level `await` to initialize the WASM module before exports are used. Ensure your bundler/runtime supports top-level await. - No network fetches are performed to load the WASM bytes; they are embedded via JSON. ## How It Fits The Workspace -- Rust crates under `crates/*` implement the core logic. `rain_orderbook_js_api` compiles to WASM and re‑exports pieces of `common`, `settings`, `subgraph`, and others for a cohesive JS surface. +- Rust crates under `crates/*` implement the core logic. `raindex_js_api` compiles to WASM and re-exports pieces of `common`, `settings`, `subgraph`, and others for a cohesive JS surface. - This package is the NPM wrapper that compiles those crates for WASM, generates JS glue, and publishes the resulting SDK. -- Consumers use only `@rainlanguage/orderbook`; no direct interaction with the Rust build is required. +- Consumers use only `@rainlanguage/raindex`; no direct interaction with the Rust build is required. ## Testing & Documentation @@ -110,7 +110,7 @@ Notes on runtime behavior ## Publishing & Versioning -- The `prepublish` script ensures the package is fully rebuilt within a Nix shell and includes the embedded WASM. Tarballs contain `dist/` and thin top‑level entry points. +- The `prepublish` script ensures the package is fully rebuilt within a Nix shell and includes the embedded WASM. Tarballs contain `dist/` and thin top-level entry points. - Node.js >= 22 is required (see `package.json#engines`). A small `buffer` dependency is bundled for ESM environments that lack a native `Buffer`. @@ -118,7 +118,6 @@ Notes on runtime behavior - Always run build/test inside `nix develop` so `wasm-bindgen`, Rust toolchains, and targets are available. - If you add new WASM crates/exports in the workspace, extend the `packages` array in `scripts/build.js` and mirror any binding tweaks in `scripts/buildPackage.js`. -- If you see initialization issues in the browser, confirm your bundler supports top‑level await and that `orderbook_wbg.json` is included in the bundle. - -This document explains what the `packages/orderbook` directory is for, how the WASM artifacts are produced and embedded, what gets exported to consumers, and how it connects to the rest of the Rain Orderbook workspace. +- If you see initialization issues in the browser, confirm your bundler supports top-level await and that `raindex_wbg.json` is included in the bundle. +This document explains what the `packages/raindex` directory is for, how the WASM artifacts are produced and embedded, what gets exported to consumers, and how it connects to the rest of the Raindex workspace. diff --git a/packages/orderbook/README.md b/packages/raindex/README.md similarity index 88% rename from packages/orderbook/README.md rename to packages/raindex/README.md index c2f3a05c0c..308853ae8c 100644 --- a/packages/orderbook/README.md +++ b/packages/raindex/README.md @@ -1,14 +1,14 @@ # Raindex SDK -A TypeScript/JavaScript SDK for interacting with Raindex orderbook contracts, providing comprehensive functionality for order management, configuration parsing, and blockchain interactions. +A TypeScript/JavaScript SDK for interacting with Raindex contracts, providing comprehensive functionality for order management, configuration parsing, and blockchain interactions. ## What is Raindex? -Raindex is an **onchain orderbook contract** that enables users to deploy complex, perpetual trading algorithms using **Rainlang**, a domain-specific language interpreted onchain. Learn more about Rainlang in the [official documentation](https://docs.rainlang.xyz/intro). +Raindex is an **onchain contract** that enables users to deploy complex, perpetual trading algorithms using **Rainlang**, a domain-specific language interpreted onchain. Learn more about Rainlang in the [official documentation](https://docs.rainlang.xyz/intro). ### How It Works -- **Dynamic Orders**: Unlike traditional orderbooks, Raindex orders contain algorithms that determine token movements based on real-time conditions +- **Dynamic Orders**: Unlike traditional order books, Raindex orders contain algorithms that determine token movements based on real-time conditions - **Vault System**: Users deposit tokens into vaults (virtual accounts) instead of using token approvals - **Multi-Token Strategies**: Orders can reference multiple input/output vaults for sophisticated trading scenarios - **Perpetual Execution**: Strategies remain active until explicitly removed by the owner @@ -16,13 +16,13 @@ Raindex is an **onchain orderbook contract** that enables users to deploy comple ## SDK Overview -This SDK provides Rust-powered WebAssembly bindings for orderbook functionality, enabling developers to: +This SDK provides Rust-powered WebAssembly bindings for Raindex functionality, enabling developers to: - **Query Orders & Trades**: Search orders across multiple networks, fetch order details, and track trade history - **Execute Quotes**: Get real-time quotes for trading pairs with maximum output amounts and IO ratios - **Take Orders**: Generate calldata for executing trades against orders, with auto-discovery by token pair or targeting specific orders - **Manage Vaults**: Query vault balances, generate deposit/withdraw calldata, and track vault activity -- **Parse Configurations**: Validate YAML files defining networks, tokens, orderbooks, and subgraph endpoints +- **Parse Configurations**: Validate YAML files defining networks, tokens, raindexes, and subgraph endpoints - **Generate Transactions**: Create ABI-encoded calldata for adding/removing orders and vault operations - **Track Performance**: Monitor order volume, vault balance changes, and trading metrics over time @@ -37,20 +37,20 @@ Before using this SDK, ensure you have: ## Installation ```bash -npm install @rainlanguage/orderbook +npm install @rainlanguage/raindex ``` ## Quick Start ### Example configuration used in this guide -All of the code snippets below reuse the same fixed-limit dotrain/settings source. The portion before `---` represents the shared orderbook and dotrain YAML, and Rainlang lives after the separator. +All of the code snippets below reuse the same fixed-limit dotrain/settings source. The portion before `---` represents the shared raindex and dotrain YAML, and Rainlang lives after the separator. > **Heads-up:** These values are purely illustrative. Before deploying anything, pull the canonical strategies and settings from [rainlanguage/rain.strategies](https://github.com/rainlanguage/rain.strategies) to mirror what our web apps run in production. ```ts const FIXED_LIMIT_SOURCE = ` -version: 5 +version: 6 networks: base: @@ -69,7 +69,7 @@ subgraphs: local-db-remotes: raindex: https://example.com/subgraph -orderbooks: +raindexes: base: network: base address: 0x52CEB8eBEf648744fFDDE89F7Bc9C3aC35944775 @@ -98,7 +98,7 @@ rainlangs: orders: fixed-limit: - orderbook: base + raindex: base inputs: - token: usdc vault-id: 1 @@ -109,7 +109,7 @@ orders: scenarios: base: - orderbook: base + raindex: base runs: 1 bindings: raindex-subparser: 0x22839F16281E67E5Fd395fAFd1571e820CbD46cB @@ -185,7 +185,7 @@ io: if( :; `; -const ORDERBOOK_SETTINGS = FIXED_LIMIT_SOURCE.split('---')[0]; +const RAINDEX_SETTINGS = FIXED_LIMIT_SOURCE.split('---')[0]; ``` ### 1. Create a raindex client @@ -193,9 +193,9 @@ const ORDERBOOK_SETTINGS = FIXED_LIMIT_SOURCE.split('---')[0]; This first snippet does three things: (1) load one or more settings YAML strings (these describe networks, accounts, and subgraph URLs), (2) feed those sources into `RaindexClient.new` so the WASM layer can parse and validate them, and (3) unwrap the resulting `WasmEncodedResult` so downstream samples can call the client with standard JS error handling expectations. The constructor is **async** — use `await`. ```ts -import { RaindexClient } from '@rainlanguage/orderbook'; +import { RaindexClient } from '@rainlanguage/raindex'; -const clientResult = await RaindexClient.new([ORDERBOOK_SETTINGS]); +const clientResult = await RaindexClient.new([RAINDEX_SETTINGS]); if (clientResult.error) throw new Error(clientResult.error.readableMsg); const client = clientResult.value; ``` @@ -206,7 +206,7 @@ When the YAML includes `local-db-sync` sections, pass optional callbacks to wire ```ts const clientResult = await RaindexClient.new( - [ORDERBOOK_SETTINGS], + [RAINDEX_SETTINGS], undefined, localDb.query.bind(localDb), localDb.wipeAndRecreate.bind(localDb), @@ -221,7 +221,7 @@ The client will automatically start the sync scheduler and route queries to the Here we scope the query by chain IDs and typical filters (owner, token, activity flag), ask the client to hydrate matching orders, and then walk the richer helpers on a single `RaindexOrder`—vault listings, trades, quotes, and detail lookups—to show how pagination + follow-up queries hang together. ```ts -import type { ChainIds, GetOrdersFilters } from '@rainlanguage/orderbook'; +import type { ChainIds, GetOrdersFilters } from '@rainlanguage/raindex'; const chainIds: ChainIds = [8453]; const filters: GetOrdersFilters = { @@ -250,16 +250,16 @@ if (quotesResult.error) throw new Error(quotesResult.error.readableMsg); Additional helpers worth wiring up: -- `client.getOrderByHash(chainId, orderbookAddress, orderHash)` – fetch a single order with full vault metadata. +- `client.getOrderByHash(chainId, raindexAddress, orderHash)` – fetch a single order with full vault metadata. - `client.getAddOrdersForTransaction(...)` / `client.getRemoveOrdersForTransaction(...)` – diff deployments and removals by transaction hash. -- `client.getTransaction(orderbookAddress, txHash)` – inspect who sent a transaction, the block number, and timestamp. +- `client.getTransaction(raindexAddress, txHash)` – inspect who sent a transaction, the block number, and timestamp. #### Poll for newly deployed orders After you submit an `execute`/`addOrders` transaction you immediately have the transaction hash, but the subgraph still needs a few blocks to index the resulting order. Rather than re-querying every order and diffing manually, poll `client.getAddOrdersForTransaction` with that hash until it returns at least one `RaindexOrder`. ```ts -import type { RaindexClient } from '@rainlanguage/orderbook'; +import type { RaindexClient } from '@rainlanguage/raindex'; const POLL_INTERVAL_MS = 5_000; const MAX_ATTEMPTS = 12; @@ -268,16 +268,16 @@ async function waitForOrderFromTx( client: RaindexClient, { chainId, - orderbookAddress, + raindexAddress, txHash }: { chainId: number; - orderbookAddress: string; + raindexAddress: string; txHash: string; } ) { for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) { - const result = await client.getAddOrdersForTransaction(chainId, orderbookAddress, txHash); + const result = await client.getAddOrdersForTransaction(chainId, raindexAddress, txHash); if (result.error) throw new Error(result.error.readableMsg); if (result.value.length) { @@ -291,7 +291,7 @@ async function waitForOrderFromTx( const txReceipt = await executeOrder(...); const raindexOrder = await waitForOrderFromTx(client, { chainId: 8453, - orderbookAddress: '0x52CEB8eBEf648744fFDDE89F7Bc9C3aC35944775', + raindexAddress: '0x52CEB8eBEf648744fFDDE89F7Bc9C3aC35944775', txHash: txReceipt.transactionHash }); ``` @@ -317,7 +317,7 @@ if (removeCalldataResult.error) throw new Error(removeCalldataResult.error.reada Vault workflows usually require combining filters, inspecting the returned `RaindexVaultsList`, and then producing calldata or math-heavy amounts. This example chains those steps: fetch vaults, narrow the list to withdrawable entries, pull history, parse human inputs with `Float`, and finally build deposit/withdraw/approval payloads while checking allowances. ```ts -import { Float, type GetVaultsFilters } from '@rainlanguage/orderbook'; +import { Float, type GetVaultsFilters } from '@rainlanguage/raindex'; const vaultFilters: GetVaultsFilters = { owners: ['0x1234...'], @@ -376,7 +376,7 @@ if (balanceChangesResult.error) throw new Error(balanceChangesResult.error.reada Once you have hydrated orders, you typically need deterministic hashes plus calldata builders. The snippet below hashes an order struct, generates take-orders calldata, asks an order for its removal calldata, and fetches quotes—mirroring the usual "inspect -> prepare transaction -> submit" flow. ```ts -import { getOrderHash, getTakeOrders3Calldata } from '@rainlanguage/orderbook'; +import { getOrderHash, getTakeOrders3Calldata } from '@rainlanguage/raindex'; const orderHashResult = getOrderHash(orderV4Struct); if (orderHashResult.error) throw new Error(orderHashResult.error.readableMsg); @@ -403,7 +403,7 @@ The SDK provides two approaches for executing `takeOrders4` transactions: auto-d Use `client.getTakeOrdersCalldata()` to discover and aggregate liquidity across all active orders for a given token pair: ```ts -import type { TakeOrdersRequest } from '@rainlanguage/orderbook'; +import type { TakeOrdersRequest } from '@rainlanguage/raindex'; const request: TakeOrdersRequest = { chainId: 137, @@ -419,7 +419,7 @@ const takeResult = await client.getTakeOrdersCalldata(request); if (takeResult.error) throw new Error(takeResult.error.readableMsg); const { - orderbook, // Contract address to call + raindex, // Contract address to call calldata, // ABI-encoded takeOrders4 calldata effectivePrice, // Blended price from simulation prices, // Per-leg ratios (best to worst) @@ -451,7 +451,7 @@ const takeResult = await order.getTakeCalldata( ); if (takeResult.error) throw new Error(takeResult.error.readableMsg); -const { calldata, orderbook, effectivePrice, expectedSell, maxSellCap } = takeResult.value; +const { calldata, raindex, effectivePrice, expectedSell, maxSellCap } = takeResult.value; ``` #### Estimate take order amounts @@ -482,7 +482,7 @@ const { Use directional token filters to find orders matching specific trading pairs: ```ts -import type { GetOrdersFilters, GetOrdersTokenFilter } from '@rainlanguage/orderbook'; +import type { GetOrdersFilters, GetOrdersTokenFilter } from '@rainlanguage/raindex'; const tokenFilter: GetOrdersTokenFilter = { inputs: ['0xUSDC...'], // Orders that accept USDC as input @@ -504,7 +504,7 @@ const ordersResult = await client.getOrders([137], filters, 1); If you maintain a hosted registry, instantiate the helper, inspect what it exposes, and pull down any dotrain/GUI definitions you need: ```ts -import { DotrainRegistry } from '@rainlanguage/orderbook'; +import { DotrainRegistry } from '@rainlanguage/raindex'; const registryResult = await DotrainRegistry.new('https://example.com/registry.txt'); if (registryResult.error) throw new Error(registryResult.error.readableMsg); @@ -532,21 +532,21 @@ The SDK merges the shared settings YAML with each order's `.rain` content before #### Access tokens from registry settings -Use `getOrderbookYaml()` to access the shared settings as an `OrderbookYaml` instance, then query tokens, networks, or orderbooks: +Use `getRaindexYaml()` to access the shared settings as an `RaindexYaml` instance, then query tokens, networks, or raindexes: ```ts -const orderbookYamlResult = registry.getOrderbookYaml(); -if (orderbookYamlResult.error) throw new Error(orderbookYamlResult.error.readableMsg); -const orderbookYaml = orderbookYamlResult.value; +const raindexYamlResult = registry.getRaindexYaml(); +if (raindexYamlResult.error) throw new Error(raindexYamlResult.error.readableMsg); +const raindexYaml = raindexYamlResult.value; -const tokensResult = await orderbookYaml.getTokens(); +const tokensResult = await raindexYaml.getTokens(); if (tokensResult.error) throw new Error(tokensResult.error.readableMsg); const tokens = tokensResult.value; // TokenInfo[] with chain_id, address, decimals, symbol, name ``` #### Get a RaindexClient from registry settings -Use `getRaindexClient()` to create a `RaindexClient` directly from the registry's shared settings, without manually bridging through `OrderbookYaml`: +Use `getRaindexClient()` to create a `RaindexClient` directly from the registry's shared settings, without manually bridging through `RaindexYaml`: ```ts const clientResult = registry.getRaindexClient(); @@ -564,7 +564,7 @@ Any dotrain file that includes a `gui:` block plus the usual settings YAML is en With that single source string (read from disk or built dynamically) you can drive the full GUI workflow: ```ts -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; const dotrainWithGui = FIXED_LIMIT_SOURCE; const SAMPLE_YAML = ` @@ -573,8 +573,8 @@ rainlangs: rainlang1: network: mainnet address: 0x... -orderbooks: - orderbook1: +raindexes: + raindex1: address: 0x... network: mainnet ... @@ -630,7 +630,7 @@ if (depositCalldatasResult.error) throw new Error(depositCalldatasResult.error.r const deploymentArgsResult = await gui.getDeploymentTransactionArgs('0xOwner'); if (deploymentArgsResult.error) throw new Error(deploymentArgsResult.error.readableMsg); -const { approvals, deploymentCalldata, orderbookAddress, chainId } = deploymentArgsResult.value; +const { approvals, deploymentCalldata, raindexAddress, chainId } = deploymentArgsResult.value; const rainlangResult = await gui.getComposedRainlang(); if (rainlangResult.error) throw new Error(rainlangResult.error.readableMsg); @@ -650,7 +650,7 @@ Serialize the GUI state and later revive it with `DotrainOrderGui.newFromState(d - `approvals: ExtendedApprovalCalldata[]` (each item contains `token`, `calldata`, and the token `symbol` for UX) - `deploymentCalldata: Hex` – a multicall that performs deposits (if required) and adds the order in one transaction -- `orderbookAddress: string` – destination for the multicall +- `raindexAddress: string` – destination for the multicall - `chainId: number` – network you must connect your wallet to A typical deployment flow is: @@ -661,11 +661,11 @@ A typical deployment flow is: 4. Poll `client.getAddOrdersForTransaction` (the helper shown earlier) with the deployment hash until the subgraph surfaces your `RaindexOrder` ```ts -import type { RaindexClient } from '@rainlanguage/orderbook'; +import type { RaindexClient } from '@rainlanguage/raindex'; const deploymentArgsResult = await gui.getDeploymentTransactionArgs(owner); if (deploymentArgsResult.error) throw new Error(deploymentArgsResult.error.readableMsg); -const { approvals, deploymentCalldata, orderbookAddress, chainId } = deploymentArgsResult.value; +const { approvals, deploymentCalldata, raindexAddress, chainId } = deploymentArgsResult.value; // Assume sendTransaction({ to, data }) and waitForReceipt(hash) come from your wallet stack. for (const approval of approvals) { @@ -673,12 +673,12 @@ for (const approval of approvals) { await waitForReceipt(approvalHash); } -const deploymentHash = await sendTransaction({ to: orderbookAddress, data: deploymentCalldata }); +const deploymentHash = await sendTransaction({ to: raindexAddress, data: deploymentCalldata }); await waitForReceipt(deploymentHash); const raindexOrder = await waitForOrderFromTx(client as RaindexClient, { chainId, - orderbookAddress, + raindexAddress, txHash: deploymentHash }); ``` @@ -686,7 +686,7 @@ const raindexOrder = await waitForOrderFromTx(client as RaindexClient, { After you have a local GUI-aware dotrain source, you can also fetch equivalent sources from a registry and run the same flow: ```ts -import { DotrainRegistry } from '@rainlanguage/orderbook'; +import { DotrainRegistry } from '@rainlanguage/raindex'; const registryResult = await DotrainRegistry.new('https://example.com/registry.txt'); if (registryResult.error) throw new Error(registryResult.error.readableMsg); @@ -705,9 +705,9 @@ const guiFromRegistry = guiSourceResult.value; If you just need Rainlang composition (no GUI state), read the dotrain text plus shared settings yourself, instantiate a `DotrainOrder`, and then ask it to compose scenario/deployment/post-task Rainlang. The example below reuses `FIXED_LIMIT_SOURCE`, but you can replace it with the contents of any `.rain` file. ```ts -import { DotrainOrder } from '@rainlanguage/orderbook'; +import { DotrainOrder } from '@rainlanguage/raindex'; -const dotrainResult = await DotrainOrder.create(FIXED_LIMIT_SOURCE, [ORDERBOOK_SETTINGS]); +const dotrainResult = await DotrainOrder.create(FIXED_LIMIT_SOURCE, [RAINDEX_SETTINGS]); if (dotrainResult.error) throw new Error(dotrainResult.error.readableMsg); const dotrain = dotrainResult.value; @@ -725,7 +725,7 @@ if (!postTaskResult.error) console.log(postTaskResult.value); - `getOrderHash`, `keccak256`, `keccak256HexString` – deterministic hashing helpers for Rain orders or arbitrary payloads. - `Float` – arbitrary-precision arithmetic with parsing, formatting, comparisons, math ops, fixed-decimal conversions, and helpers like `Float.zero()` or `.formatWithRange(...)`. -- `OrderbookYaml.getTokens()` – async method returning all tokens from YAML configuration with `chain_id`, `address`, `decimals`, `symbol`, and `name`. Automatically fetches remote tokens from `using-tokens-from` URLs. +- `RaindexYaml.getTokens()` – async method returning all tokens from YAML configuration with `chain_id`, `address`, `decimals`, `symbol`, and `name`. Automatically fetches remote tokens from `using-tokens-from` URLs. - `RaindexClient.getAllAccounts()` / `getAllVaultTokens()` – introspect accounts and ERC20 metadata defined in your YAML or discovered via subgraphs. - Local DB sync – pass `queryCallback`, `wipeCallback`, and `statusCallback` to `RaindexClient.new()` when YAML has `local-db-sync` sections to enable an offline-capable persistent cache. The scheduler starts automatically and queries route to the local DB once the first sync cycle completes. - `RaindexVaultsList.getWithdrawCalldata()` – multicall builder that withdraws every vault with a balance. @@ -742,7 +742,7 @@ type WasmEncodedResult = | { value: T; error: undefined } | { value: undefined; error: { msg: string; readableMsg: string } }; -const result = await client.getVault(14, '0xOrderbook', '0x01'); +const result = await client.getVault(14, '0xRaindex', '0x01'); if (result.error) { console.error('Vault lookup failed:', result.error.readableMsg); return; @@ -752,4 +752,4 @@ console.log(result.value); ## Contributing -This SDK is part of the Rain Language ecosystem. For contributions and issues, please visit the [GitHub repository](https://github.com/rainlanguage/rain.orderbook). +This SDK is part of the Rain Language ecosystem. For contributions and issues, please visit the [GitHub repository](https://github.com/rainlanguage/raindex). diff --git a/packages/orderbook/package.json b/packages/raindex/package.json similarity index 75% rename from packages/orderbook/package.json rename to packages/raindex/package.json index 74002175d5..8c930504d9 100644 --- a/packages/orderbook/package.json +++ b/packages/raindex/package.json @@ -1,18 +1,18 @@ { - "name": "@rainlanguage/orderbook", - "description": "Provides RainLanguage Orderbook rust crates' functionalities in typescript through wasm bindgen", + "name": "@rainlanguage/raindex", + "description": "Provides RainLanguage Raindex rust crates' functionalities in typescript through wasm bindgen", "version": "0.0.1-alpha.229", "license": "LicenseRef-DCL-1.0", "author": "Rain Open Source Software Ltd", "repository": { "type": "git", - "url": "https://github.com/rainlanguage/rain.orderbook.git" + "url": "https://github.com/rainlanguage/raindex.git" }, "keywords": [], "bugs": { - "url": "https://github.com/rainlanguage/rain.orderbook/issues" + "url": "https://github.com/rainlanguage/raindex/issues" }, - "homepage": "https://github.com/rainlanguage/rain.orderbook#readme", + "homepage": "https://github.com/rainlanguage/raindex#readme", "main": "./dist/cjs/index.js", "module": "./dist/esm/index.js", "browser": { @@ -32,7 +32,7 @@ "scripts": { "prepublish": "node ./scripts/setup", "build": "npm run rm-dist && npm run rm-temp && npm run build-wasm && node ./scripts/build && npm run check", - "build-wasm": "cargo build --target wasm32-unknown-unknown --lib --profile release-wasm -p rain_orderbook_js_api", + "build-wasm": "cargo build --target wasm32-unknown-unknown --lib --profile release-wasm -p raindex_js_api", "rm-dist": "rimraf ./dist", "rm-temp": "rimraf ./temp", "test": "npm run check && vitest run --dir test", diff --git a/packages/orderbook/scripts/build.js b/packages/raindex/scripts/build.js similarity index 100% rename from packages/orderbook/scripts/build.js rename to packages/raindex/scripts/build.js diff --git a/packages/orderbook/scripts/buildPackage.js b/packages/raindex/scripts/buildPackage.js similarity index 95% rename from packages/orderbook/scripts/buildPackage.js rename to packages/raindex/scripts/buildPackage.js index 1e96dd55ed..7ba3821985 100644 --- a/packages/orderbook/scripts/buildPackage.js +++ b/packages/raindex/scripts/buildPackage.js @@ -1,7 +1,7 @@ const fs = require('fs'); const { execSync } = require('child_process'); -const packagePrefix = 'rain_orderbook_'; +const packagePrefix = 'raindex_'; // after using opt-level on wasm build, WasmEncodedResult and WasmEncodedError // are duplicated in the dts so we need to dedupe them @@ -26,7 +26,7 @@ module.exports.buildCjs = function (pkg) { // in js modules in order to avoid using fetch or fs operations const wasmCjsBytes = fs.readFileSync(`./temp/node/${pkg}/${pkg}_bg.wasm`); fs.writeFileSync( - "./dist/cjs/orderbook_wbg.json", + "./dist/cjs/raindex_wbg.json", JSON.stringify({ wasm: Buffer.from(wasmCjsBytes, 'binary').toString('base64') }) @@ -62,7 +62,7 @@ module.exports.buildCjs = function (pkg) { const bytes = require('fs').readFileSync(path);`, ` const { Buffer } = require('buffer'); -const wasmB64 = require('./orderbook_wbg.json'); +const wasmB64 = require('./raindex_wbg.json'); const bytes = Buffer.from(wasmB64.wasm, 'base64');` ); cjs = cjs.replace('const { TextEncoder, TextDecoder } = require(`util`);', ''); @@ -83,7 +83,7 @@ module.exports.buildEsm = function (pkg) { // in js modules in order to avoid using fetch or fs operations const wasmEsmBytes = fs.readFileSync(`./temp/web/${pkg}/${pkg}_bg.wasm`); fs.writeFileSync( - `./dist/esm/orderbook_wbg.json`, + `./dist/esm/raindex_wbg.json`, JSON.stringify({ wasm: Buffer.from(wasmEsmBytes, 'binary').toString('base64') }) @@ -121,7 +121,7 @@ module.exports.buildEsm = function (pkg) { esm = esm.replace(`export { initSync }; export default __wbg_init;`, `import { Buffer } from 'buffer'; -import wasmB64 from './orderbook_wbg.json'; +import wasmB64 from './raindex_wbg.json'; const bytes = Buffer.from(wasmB64.wasm, 'base64');\n initSync(bytes);` ); diff --git a/packages/orderbook/scripts/setup.js b/packages/raindex/scripts/setup.js similarity index 100% rename from packages/orderbook/scripts/setup.js rename to packages/raindex/scripts/setup.js diff --git a/packages/orderbook/scripts/sizeCheck.js b/packages/raindex/scripts/sizeCheck.js similarity index 100% rename from packages/orderbook/scripts/sizeCheck.js rename to packages/raindex/scripts/sizeCheck.js diff --git a/packages/orderbook/test/bindings/test.test.ts b/packages/raindex/test/bindings/test.test.ts similarity index 98% rename from packages/orderbook/test/bindings/test.test.ts rename to packages/raindex/test/bindings/test.test.ts index b06cacb6d6..5d07c228e0 100644 --- a/packages/orderbook/test/bindings/test.test.ts +++ b/packages/raindex/test/bindings/test.test.ts @@ -3,7 +3,7 @@ import { describe, it } from 'vitest'; import { getOrderHash, OrderV4 } from '../../dist/cjs'; import { expect } from 'chai'; -describe('Rain Orderbook Bindings Package Bindgen Tests', async function () { +describe('Rain Raindex Bindings Package Bindgen Tests', async function () { it('should get correct order hash', async () => { const order: OrderV4 = { owner: '0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba', diff --git a/packages/orderbook/test/common/test.test.ts b/packages/raindex/test/common/test.test.ts similarity index 90% rename from packages/orderbook/test/common/test.test.ts rename to packages/raindex/test/common/test.test.ts index c8de506546..e015211c9f 100644 --- a/packages/orderbook/test/common/test.test.ts +++ b/packages/raindex/test/common/test.test.ts @@ -1,10 +1,10 @@ import { describe, it } from 'vitest'; -import { DotrainOrder, OrderbookYaml } from '../../dist/cjs'; +import { DotrainOrder, RaindexYaml } from '../../dist/cjs'; import { assert } from 'chai'; -const SPEC_VERSION = OrderbookYaml.getCurrentSpecVersion().value; +const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; -describe('Rain Orderbook Common Package Bindgen Tests', async function () { +describe('Rain Raindex Common Package Bindgen Tests', async function () { const dotrain = ` version: ${SPEC_VERSION} networks: @@ -23,8 +23,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -60,7 +60,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: diff --git a/packages/orderbook/test/js_api/dotrainRainlang.test.ts b/packages/raindex/test/js_api/dotrainRainlang.test.ts similarity index 94% rename from packages/orderbook/test/js_api/dotrainRainlang.test.ts rename to packages/raindex/test/js_api/dotrainRainlang.test.ts index cb3d0b28ae..5969cc3968 100644 --- a/packages/orderbook/test/js_api/dotrainRainlang.test.ts +++ b/packages/raindex/test/js_api/dotrainRainlang.test.ts @@ -1,9 +1,9 @@ import assert from 'assert'; import { afterAll, beforeAll, beforeEach, describe, it } from 'vitest'; -import { WasmEncodedResult, DotrainRainlang, OrderbookYaml, RaindexClient } from '../../dist/cjs'; +import { WasmEncodedResult, DotrainRainlang, RaindexYaml, RaindexClient } from '../../dist/cjs'; import { getLocal } from 'mockttp'; -const SPEC_VERSION = OrderbookYaml.getCurrentSpecVersion().value; +const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; const extractWasmEncodedData = (result: WasmEncodedResult, errorMessage?: string): T => { if (result.error) { @@ -34,7 +34,7 @@ subgraphs: metaboards: flare: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-flare-0x893BBFB7/0.1/gn base: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-base-0x59401C93/0.1/gn -orderbooks: +raindexes: flare: address: 0xCEe8Cd002F151A536394E564b84076c41bBBcD4d network: flare @@ -107,13 +107,13 @@ scenarios: runs: 1 orders: flare: - orderbook: flare + raindex: flare inputs: - token: token1 outputs: - token: token1 base: - orderbook: base + raindex: base inputs: - token: token2 outputs: @@ -146,7 +146,7 @@ _ _: 1 1; #handle-add-order :;`; -describe('Rain Orderbook JS API Package Bindgen Tests - Dotrain Rainlang', async function () { +describe('Rain Raindex JS API Package Bindgen Tests - Dotrain Rainlang', async function () { const mockServer = getLocal(); beforeAll(async () => { await mockServer.start(8231); @@ -407,7 +407,7 @@ tokens: decimals: 6 label: USD Coin symbol: USDC -orderbooks: +raindexes: mainnet: address: 0x1234567890123456789012345678901234567890 network: mainnet @@ -440,7 +440,7 @@ scenarios: runs: 1 orders: mainnet: - orderbook: mainnet + raindex: mainnet inputs: - token: weth outputs: @@ -456,9 +456,9 @@ _ _: 0 0; :; `; - describe('DotrainRainlang getOrderbookYaml', () => { + describe('DotrainRainlang getRaindexYaml', () => { - it('should return OrderbookYaml instance from settings', async () => { + it('should return RaindexYaml instance from settings', async () => { const rainlangContent = `http://localhost:8231/settings.yaml test-order http://localhost:8231/order.rain`; @@ -470,12 +470,12 @@ test-order http://localhost:8231/order.rain`; await DotrainRainlang.new('http://localhost:8231/registry.txt') ); - const orderbookYamlResult = registry.getOrderbookYaml(); - const orderbookYaml = extractWasmEncodedData(orderbookYamlResult); + const raindexYamlResult = registry.getRaindexYaml(); + const raindexYaml = extractWasmEncodedData(raindexYamlResult); - assert.ok(orderbookYaml, 'OrderbookYaml instance should be returned'); - assert.strictEqual(typeof orderbookYaml.getTokens, 'function'); - assert.strictEqual(typeof orderbookYaml.getOrderbookByAddress, 'function'); + assert.ok(raindexYaml, 'RaindexYaml instance should be returned'); + assert.strictEqual(typeof raindexYaml.getTokens, 'function'); + assert.strictEqual(typeof raindexYaml.getRaindexByAddress, 'function'); }); }); diff --git a/packages/orderbook/test/js_api/gui.test.ts b/packages/raindex/test/js_api/gui.test.ts similarity index 99% rename from packages/orderbook/test/js_api/gui.test.ts rename to packages/raindex/test/js_api/gui.test.ts index 4799f0aa90..d6fad4e54a 100644 --- a/packages/orderbook/test/js_api/gui.test.ts +++ b/packages/raindex/test/js_api/gui.test.ts @@ -18,10 +18,10 @@ import { AllGuiConfig, WasmEncodedResult, FieldValue, - OrderbookYaml + RaindexYaml } from '../../dist/cjs'; -const SPEC_VERSION = OrderbookYaml.getCurrentSpecVersion().value; +const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; // Rainlang contract function selectors const EXPRESSION_DEPLOYER_ADDRESS_SELECTOR = toFunctionSelector('function expressionDeployerAddress() external view returns (address)'); @@ -167,8 +167,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -207,7 +207,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: @@ -247,8 +247,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -281,7 +281,7 @@ orders: outputs: - token: token2 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: @@ -319,8 +319,8 @@ rainlangs: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -339,7 +339,7 @@ orders: outputs: - token: token2 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: @@ -409,14 +409,14 @@ rainlangs: other-rainlang: network: some-network address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: remote-network subgraph: some-sg local-db-remote: remote deployment-block: 12345 - other-orderbook: + other-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: other-sg @@ -455,14 +455,14 @@ orders: outputs: - token: token2 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex other-order: inputs: - token: token3 outputs: - token: token3 rainlang: other-rainlang - orderbook: other-orderbook + raindex: other-raindex deployments: test-deployment: scenario: some-scenario @@ -480,7 +480,7 @@ ${guiConfig} ${dotrain} `; -describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () { +describe('Rain Raindex JS API Package Bindgen Tests - Gui', async function () { const mockServer = getLocal(); beforeAll(async () => { await mockServer.start(8085); @@ -1027,7 +1027,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Gui', async function () describe('state management tests', async () => { let serializedState = - 'H4sIAAAAAAAA_21QzUrEMBBuqiiIBxGvguDV2GxCy-6yXpSVQlFQi38X6bZhu26a1DZViw_h0asvsPgEXr35POJNi0ndsjuHfJP5vsnMF2D8xapCSXMJByMejfgQqBoyVqbZ-4AV1FSVJc2IMeUtQ8eiQhvtOg0JriULClsIgXmP4eZNL5iLhEJO5YPIxrpvU2EsZdq1LCbCgMUil902attWloawyNhTpQDVCfTovu9uqPS59zXZ_uxN3l_st-9LE3c-XkOwDpYV7Vc7bGGgbfu_PkzjP5rfUA9wHAfM-KpZQsiOSml5FHj9m9I9ZHeDW37qnYcH-Mx2OyfXBRtGJDnehx7BF_Dxam9N9QgZ0wxGNGWiTCiXP9NL3cfLAQAA'; + 'H4sIAAAAAAAA_21Qu07DMBSNAwIJMSDEioTESojrNKZUZQC1AsRjSSqFsU3dpNS1jePwEB_ByMoPVHwBKxvfg9ggwg5E7R18ru851_ceA-s3VjUqkimnP2KDEUuArkFr5T9726M5sXVlyTB8TFjNMrGo0Ye7uCJBpWRBYw1CMO8xVL2ZBTM-IQ4j6o7Lsenb1JgqJZquS3ncoynPVLMBG74rRezkkj4WClCcwIzuhCcbOn1qfU63P1rTt2f_9Suy0f77SwzWwbKmw2KHLQSM7fDHh239RfUbygEYYzDjq2Q9z9vRKTodJkfX8VDuBe0ooFF6DLsi6bdF9z64wZeH51d10rk4S3JSP1jTPVylRDoDIih_mBCmvgEOtPhuywEAAA=='; let dotrain3: string; let gui: DotrainOrderGui; beforeAll(async () => { @@ -1957,7 +1957,7 @@ ${dotrainWithoutVaultIds}`; ); assert.equal(result.approvals[0].symbol, 'T2'); assert.equal(result.deploymentCalldata.length, 3594); - assert.equal(result.orderbookAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.raindexAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); assert.equal(result.chainId, 123); const emitMetaCall = result.emitMetaCall; @@ -1982,7 +1982,7 @@ ${dotrainWithoutVaultIds}`; assert.equal(result.approvals.length, 0); assert.equal(result.deploymentCalldata.length, 2954); - assert.equal(result.orderbookAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(result.raindexAddress, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); assert.equal(result.chainId, 123); const emitMetaCallAfterUnset = result.emitMetaCall; diff --git a/packages/orderbook/test/js_api/raindexClient.test.ts b/packages/raindex/test/js_api/raindexClient.test.ts similarity index 94% rename from packages/orderbook/test/js_api/raindexClient.test.ts rename to packages/raindex/test/js_api/raindexClient.test.ts index d777a9461d..5508bd65c6 100644 --- a/packages/orderbook/test/js_api/raindexClient.test.ts +++ b/packages/raindex/test/js_api/raindexClient.test.ts @@ -14,14 +14,14 @@ import { SgRemoveOrderWithOrder, Hex, Float, - OrderbookYaml + RaindexYaml } from '../../dist/cjs'; import { getLocal } from 'mockttp'; -const SPEC_VERSION = OrderbookYaml.getCurrentSpecVersion().value; +const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; -const CHAIN_ID_1_ORDERBOOK_ADDRESS = '0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6'; -const CHAIN_ID_2_ORDERBOOK_ADDRESS = '0xbeedbeedbeedbeedbeedbeedbeedbeedbeedbeed'; +const CHAIN_ID_1_RAINDEX_ADDRESS = '0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6'; +const CHAIN_ID_2_RAINDEX_ADDRESS = '0xbeedbeedbeedbeedbeedbeedbeedbeedbeedbeed'; const YAML = ` version: ${SPEC_VERSION} @@ -51,15 +51,15 @@ accounts: alice: 0x742d35Cc6634C0532925a3b8D4Fd2d3dB2d4D7fA bob: 0x8ba1f109551bD432803012645aac136c0c8D2e80 -orderbooks: - some-orderbook: - address: ${CHAIN_ID_1_ORDERBOOK_ADDRESS} +raindexes: + some-raindex: + address: ${CHAIN_ID_1_RAINDEX_ADDRESS} network: some-network subgraph: some-sg local-db-remote: remote deployment-block: 12345 - other-orderbook: - address: ${CHAIN_ID_2_ORDERBOOK_ADDRESS} + other-raindex: + address: ${CHAIN_ID_2_RAINDEX_ADDRESS} deployment-block: 12345 network: other-network subgraph: other-sg @@ -95,7 +95,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: scenario: some-scenario @@ -119,7 +119,7 @@ const extractWasmEncodedData = (result: WasmEncodedResult, errorMessage?: return result.value; }; -describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async function () { +describe('Rain Raindex JS API Package Bindgen Tests - Raindex Client', async function () { const mockServer = getLocal(); beforeAll(async () => { await mockServer.start(8230); @@ -159,8 +159,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } }, { @@ -178,8 +178,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ], @@ -199,8 +199,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } }, { @@ -218,8 +218,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ], @@ -236,8 +236,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ], meta: '0xff0a89c674ee7874a3005902252f2a20302e2063616c63756c6174652d696f202a2f200a7573696e672d776f7264732d66726f6d203078466532343131434461313933443945346538334135633233344337466433323031303138383361430a616d743a203130302c0a696f3a2063616c6c3c323e28293b0a0a2f2a20312e2068616e646c652d696f202a2f200a3a63616c6c3c333e28292c0a3a656e7375726528657175616c2d746f286f75747075742d7661756c742d64656372656173652829203130302920226d7573742074616b652066756c6c20616d6f756e7422293b0a0a2f2a20322e206765742d696f2d726174696f2d6e6f77202a2f200a656c61707365643a2063616c6c3c343e28292c0a696f3a2073617475726174696e672d73756228302e3031373733353620646976286d756c28656c61707365642073756228302e3031373733353620302e30313733383434292920363029293b0a0a2f2a20332e206f6e652d73686f74202a2f200a3a656e737572652869732d7a65726f286765742868617368286f726465722d68617368282920226861732d657865637574656422292929202268617320657865637574656422292c0a3a7365742868617368286f726465722d68617368282920226861732d657865637574656422292031293b0a0a2f2a20342e206765742d656c6170736564202a2f200a5f3a20737562286e6f772829206765742868617368286f726465722d68617368282920226465706c6f792d74696d65222929293b011bff13109e41336ff20278186170706c69636174696f6e2f6f637465742d73747265616d', timestampAdded: '0', - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, trades: [], removeEvents: [] @@ -265,8 +265,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_2_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_2_RAINDEX_ADDRESS } } ], @@ -286,8 +286,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_2_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_2_RAINDEX_ADDRESS } } ], @@ -304,8 +304,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ], meta: null, timestampAdded: '0', - orderbook: { - id: CHAIN_ID_2_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_2_RAINDEX_ADDRESS }, trades: [], removeEvents: [] @@ -338,8 +338,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ], @@ -359,8 +359,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ], @@ -377,8 +377,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ], meta: null, timestampAdded: '0', - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, trades: [], removeEvents: [] @@ -421,7 +421,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_ORDERBOOK_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, order: { @@ -452,11 +452,11 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_ORDERBOOK_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ] as unknown as SgTrade[]; @@ -498,7 +498,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_ORDERBOOK_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, order: { @@ -529,11 +529,11 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f timestamp: '1632000000', blockNumber: '0' }, - orderbook: { id: CHAIN_ID_1_ORDERBOOK_ADDRESS }, + raindex: { id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ] as unknown as SgTrade[]; @@ -554,8 +554,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f } }, timestamp: '0', - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, outputVaultBalanceChange: { id: '0x0123', @@ -581,8 +581,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '0', timestamp: '0' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } }, @@ -610,8 +610,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '0', timestamp: '0' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, trade: { tradeEvent: { __typename: 'TakeOrder' } } } @@ -646,11 +646,11 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); assert.equal(typeof order, 'object'); assert.equal(order.id, order1.id); - assert.equal(order.orderbook, order1.orderbook.id); + assert.equal(order.raindex, order1.raindex.id); assert.equal(order.owner, order1.owner); assert.equal(order.active, order1.active); assert.equal(order.timestampAdded, order1.timestampAdded); @@ -736,7 +736,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_VOL_ORDER) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_VOL_ORDER) ); const result = extractWasmEncodedData(await order.getVaultsVolume()); assert.equal(result.length, 2); @@ -804,7 +804,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f // const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); // const order = extractWasmEncodedData( - // await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + // await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') // ); // const result = await order.getPerformance(BigInt(1632000000), BigInt(1734571449)); // if (result.error) assert.fail('expected to resolve, but failed'); @@ -812,7 +812,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f // const expected: OrderPerformance = { // orderId: '0x0123', // orderHash: '0x0123', - // orderbook: CHAIN_ID_1_ORDERBOOK_ADDRESS, + // raindex: CHAIN_ID_1_RAINDEX_ADDRESS, // denominatedPerformance: { // token: { // id: '0x0234', @@ -891,7 +891,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f .thenReply(200, JSON.stringify({ data: { orders: [order1] } })); const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); const calldata = extractWasmEncodedData(order.getRemoveCalldata()); @@ -914,7 +914,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); const result = extractWasmEncodedData(await order.getQuotes()); @@ -955,7 +955,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); const orders = new RaindexOrders(); @@ -1025,14 +1025,14 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); const result = extractWasmEncodedData(await order.getTradesList()); assert.equal(result.length, 1); assert.equal(result[0].id, mockOrderTradesList[0].id); assert.equal(result[0].orderHash, mockOrderTradesList[0].order.orderHash); assert.equal(result[0].timestamp, BigInt(mockOrderTradesList[0].timestamp)); - assert.equal(result[0].orderbook, mockOrderTradesList[0].orderbook.id.toLowerCase()); + assert.equal(result[0].raindex, mockOrderTradesList[0].raindex.id.toLowerCase()); assert.equal( result[0].outputVaultBalanceChange.amount, mockOrderTradesList[0].outputVaultBalanceChange.amount @@ -1115,7 +1115,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); const result = extractWasmEncodedData(await order.getTradeDetail(mockTrade.id as Hex)); assert.equal(result.id, mockTrade.id); @@ -1186,7 +1186,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f result.transaction.timestamp, BigInt(mockTrade.tradeEvent.transaction.timestamp) ); - assert.equal(result.orderbook, mockTrade.orderbook.id.toLowerCase()); + assert.equal(result.raindex, mockTrade.raindex.id.toLowerCase()); }); it('should get trade count', async function () { @@ -1217,7 +1217,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const order = extractWasmEncodedData( - await raindexClient.getOrderByHash(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getOrderByHash(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); const result = extractWasmEncodedData(await order.getTradeCount()); assert.equal(result, 1); @@ -1253,8 +1253,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f symbol: 'sFLR', decimals: '18' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, ordersAsOutput: [ { @@ -1294,8 +1294,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37432554', timestamp: '1739448802' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } }, @@ -1328,8 +1328,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37439233', timestamp: '1739460802' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } }, @@ -1362,8 +1362,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37439219', timestamp: '1739460777' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } }, @@ -1396,8 +1396,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37439068', timestamp: '1739460481' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } } @@ -1418,8 +1418,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f symbol: 'WFLR', decimals: '18' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, ordersAsOutput: [], ordersAsInput: [ @@ -1459,8 +1459,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37439221', timestamp: '1739460781' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } }, @@ -1493,8 +1493,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37439034', timestamp: '1739460415' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } }, @@ -1527,8 +1527,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37439143', timestamp: '1739460627' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } }, @@ -1561,16 +1561,16 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '37438849', timestamp: '1739460078' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } } ] } ], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, active: true, timestampAdded: '1739448802', @@ -1601,13 +1601,13 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const result = extractWasmEncodedData( await raindexClient.getAddOrdersForTransaction( 1, - CHAIN_ID_1_ORDERBOOK_ADDRESS, + CHAIN_ID_1_RAINDEX_ADDRESS, mockOrder.transaction.id ) ); assert.equal(result[0].id, mockAddOrder.order.id); assert.equal(result[0].chainId, BigInt(1)); - assert.equal(result[0].orderbook, mockAddOrder.order.orderbook.id); + assert.equal(result[0].raindex, mockAddOrder.order.raindex.id); assert.equal(result[0].transaction?.id, mockAddOrder.transaction.id); }); @@ -1620,13 +1620,13 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const result = extractWasmEncodedData( await raindexClient.getRemoveOrdersForTransaction( 1, - CHAIN_ID_1_ORDERBOOK_ADDRESS, + CHAIN_ID_1_RAINDEX_ADDRESS, mockOrder.transaction.id ) ); assert.equal(result[0].id, mockRemoveOrder.order.id); assert.equal(result[0].chainId, BigInt(1)); - assert.equal(result[0].orderbook, mockRemoveOrder.order.orderbook.id); + assert.equal(result[0].raindex, mockRemoveOrder.order.raindex.id); assert.equal(result[0].transaction?.id, mockRemoveOrder.transaction.id); }); }); @@ -1644,8 +1644,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f symbol: 'TKN1', decimals: '18' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, ordersAsOutput: [], ordersAsInput: [], @@ -1663,8 +1663,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f symbol: 'TKN2', decimals: '18' }, - orderbook: { - id: CHAIN_ID_2_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_2_RAINDEX_ADDRESS }, ordersAsOutput: [], ordersAsInput: [], @@ -1715,7 +1715,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const result = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); assert.equal(result.vaultId, BigInt(vault1.vaultId)); @@ -1726,7 +1726,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f assert.equal(result.token.name, vault1.token.name); assert.equal(result.token.symbol, vault1.token.symbol); assert.equal(result.token.decimals, BigInt(vault1.token.decimals ?? 0)); - assert.equal(result.orderbook, vault1.orderbook.id); + assert.equal(result.raindex, vault1.raindex.id); }); it('should fetch vault balance changes', async () => { @@ -1755,8 +1755,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f blockNumber: '34407047', timestamp: '1734054063' }, - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ]; @@ -1771,7 +1771,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const result = extractWasmEncodedData(await vault.getBalanceChanges()); @@ -1787,7 +1787,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f assert.equal(result[0].transaction.from, '0x7177b9d00bB5dbcaaF069CC63190902763783b09'); assert.equal(result[0].transaction.blockNumber, BigInt('34407047')); assert.equal(result[0].transaction.timestamp, BigInt('1734054063')); - assert.equal(result[0].orderbook, CHAIN_ID_1_ORDERBOOK_ADDRESS); + assert.equal(result[0].raindex, CHAIN_ID_1_RAINDEX_ADDRESS); }); const order = { @@ -1812,8 +1812,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ], @@ -1833,8 +1833,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ordersAsOutput: [], ordersAsInput: [], balanceChanges: [], - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS } } ], @@ -1851,8 +1851,8 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f ], meta: null, timestampAdded: '0', - orderbook: { - id: CHAIN_ID_1_ORDERBOOK_ADDRESS + raindex: { + id: CHAIN_ID_1_RAINDEX_ADDRESS }, trades: [], removeEvents: [] @@ -1870,7 +1870,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const res = extractWasmEncodedData( await vault.getDepositCalldata(Float.parse('500').value as Float) @@ -1887,7 +1887,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); let res = await vault.getDepositCalldata(Float.parse('0').value as Float); @@ -1908,7 +1908,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); let res = await vault.getWithdrawCalldata(Float.parse('500').value as Float); @@ -1942,7 +1942,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const res = extractWasmEncodedData(await vault.getAllowance()); assert.equal(res, '0x64'); @@ -1964,7 +1964,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const res = extractWasmEncodedData( @@ -1991,7 +1991,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const res = await vault.getApprovalCalldata(Float.parse('100').value as Float); @@ -2016,7 +2016,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const res = await vault.getApprovalCalldata(Float.parse('90').value as Float); @@ -2125,7 +2125,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const vault = extractWasmEncodedData( - await raindexClient.getVault(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, '0x0123') + await raindexClient.getVault(1, CHAIN_ID_1_RAINDEX_ADDRESS, '0x0123') ); const res = extractWasmEncodedData(await vault.getOwnerBalance()); @@ -2147,7 +2147,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const result = extractWasmEncodedData( - await raindexClient.getTransaction(1, CHAIN_ID_1_ORDERBOOK_ADDRESS, BYTES32_0123) + await raindexClient.getTransaction(1, CHAIN_ID_1_RAINDEX_ADDRESS, BYTES32_0123) ); assert.equal(result.id, transaction.id); assert.equal(result.from, transaction.from); @@ -2156,7 +2156,7 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f }); }); - describe('Orderbook yaml', () => { + describe('Raindex yaml', () => { it('should get unique chain ids', async () => { const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); const result = extractWasmEncodedData(raindexClient.getUniqueChainIds()); @@ -2179,18 +2179,18 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Raindex Client', async f assert.equal(result.chainId, 1); }); - it('should get orderbook by address', async () => { + it('should get raindex by address', async () => { const raindexClient = extractWasmEncodedData(await RaindexClient.new([YAML])); let result = extractWasmEncodedData( - raindexClient.getOrderbookByAddress(CHAIN_ID_1_ORDERBOOK_ADDRESS) + raindexClient.getRaindexByAddress(CHAIN_ID_1_RAINDEX_ADDRESS) ); - assert.equal(result.address.toLowerCase(), CHAIN_ID_1_ORDERBOOK_ADDRESS.toLowerCase()); + assert.equal(result.address.toLowerCase(), CHAIN_ID_1_RAINDEX_ADDRESS.toLowerCase()); result = extractWasmEncodedData( - raindexClient.getOrderbookByAddress(CHAIN_ID_2_ORDERBOOK_ADDRESS) + raindexClient.getRaindexByAddress(CHAIN_ID_2_RAINDEX_ADDRESS) ); - assert.equal(result.address.toLowerCase(), CHAIN_ID_2_ORDERBOOK_ADDRESS.toLowerCase()); + assert.equal(result.address.toLowerCase(), CHAIN_ID_2_RAINDEX_ADDRESS.toLowerCase()); }); it('should check if sentry is enabled', async () => { diff --git a/packages/orderbook/test/js_api/orderbookYaml.test.ts b/packages/raindex/test/js_api/raindexYaml.test.ts similarity index 82% rename from packages/orderbook/test/js_api/orderbookYaml.test.ts rename to packages/raindex/test/js_api/raindexYaml.test.ts index 7c904550dd..e16060a092 100644 --- a/packages/orderbook/test/js_api/orderbookYaml.test.ts +++ b/packages/raindex/test/js_api/raindexYaml.test.ts @@ -1,11 +1,11 @@ import assert from 'assert'; import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'; -import { OrderbookYaml, OrderbookCfg, WasmEncodedResult } from '../../dist/cjs'; +import { RaindexYaml, RaindexCfg, WasmEncodedResult } from '../../dist/cjs'; import { getLocal } from 'mockttp'; -const SPEC_VERSION = OrderbookYaml.getCurrentSpecVersion().value; +const SPEC_VERSION = RaindexYaml.getCurrentSpecVersion().value; -const YAML_WITHOUT_ORDERBOOK = ` +const YAML_WITHOUT_RAINDEX = ` version: ${SPEC_VERSION} networks: @@ -28,10 +28,10 @@ rainlangs: address: 0xF14E09601A47552De6aBd3A0B165607FaFd2B5Ba local-db-remotes: - some-orderbook: http://example.com + some-raindex: http://example.com local-db-sync: - some-orderbook: + some-raindex: batch-size: 2000 max-concurrent-batches: 10 retry-attempts: 3 @@ -41,8 +41,8 @@ local-db-sync: bootstrap-block-threshold: 1000 sync-interval-ms: 5000 -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: some-network subgraph: some-sg @@ -81,7 +81,7 @@ orders: - token: token2 vault-id: 1 rainlang: some-rainlang - orderbook: some-orderbook + raindex: some-raindex deployments: some-deployment: @@ -104,14 +104,14 @@ const extractWasmEncodedData = (result: WasmEncodedResult, errorMessage?: return result.value; }; -const buildYaml = (source: string, validate?: boolean): OrderbookYaml => { - const result = OrderbookYaml.new([source], validate); - return extractWasmEncodedData(result); +const buildYaml = (source: string, validate?: boolean): RaindexYaml => { + const result = RaindexYaml.new([source], validate); + return extractWasmEncodedData(result); }; -describe('Rain Orderbook JS API Package Bindgen Tests - Settings', async function () { +describe('Raindex JS API Package Bindgen Tests - Settings', async function () { it('should return current spec version', async function () { - const result = OrderbookYaml.getCurrentSpecVersion(); + const result = RaindexYaml.getCurrentSpecVersion(); if (result.error) assert.fail(result.error.msg); const version = result.value; assert.ok(version); @@ -120,35 +120,35 @@ describe('Rain Orderbook JS API Package Bindgen Tests - Settings', async functio }); it('should create a new settings object', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); + assert.ok(raindexYaml); }); - describe('orderbook tests', async function () { - it('should get the orderbook', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); + describe('raindex tests', async function () { + it('should get the raindex', async function () { + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); - const orderbook = extractWasmEncodedData( - orderbookYaml.getOrderbookByAddress('0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6') + const raindexCfg = extractWasmEncodedData( + raindexYaml.getRaindexByAddress('0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6') ); - assert.equal(orderbook.address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); - assert.equal(orderbook.network.chainId, 123); - assert.equal(orderbook.subgraph.url, 'https://www.some-sg.com/'); + assert.equal(raindexCfg.address, '0xc95a5f8efe14d7a20bd2e5bafec4e71f8ce0b9a6'); + assert.equal(raindexCfg.network.chainId, 123); + assert.equal(raindexCfg.subgraph.url, 'https://www.some-sg.com/'); - let result = orderbookYaml.getOrderbookByAddress('invalid-address'); + let result = raindexYaml.getRaindexByAddress('invalid-address'); if (!result.error) expect.fail('Expected error'); expect(result.error.msg).toBe('Invalid address: odd number of digits'); expect(result.error.readableMsg).toBe( 'The provided address is invalid. Please ensure the address is in the correct hexadecimal format. Error: "odd number of digits"' ); - result = orderbookYaml.getOrderbookByAddress('0x0000000000000000000000000000000000000000'); + result = raindexYaml.getRaindexByAddress('0x0000000000000000000000000000000000000000'); if (!result.error) expect.fail('Expected error'); expect(result.error.msg).toBe( - 'Orderbook yaml error: orderbook with address: 0x0000000000000000000000000000000000000000 not found' + 'Raindex yaml error: raindex with address: 0x0000000000000000000000000000000000000000 not found' ); expect(result.error.readableMsg).toBe( - 'There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: "orderbook with address: 0x0000000000000000000000000000000000000000 not found"' + 'There was an error processing the YAML configuration. Please check the YAML file for any issues. Error: "raindex with address: 0x0000000000000000000000000000000000000000 not found"' ); }); }); @@ -164,8 +164,8 @@ networks: network-id: 123 currency: ETH -orderbooks: - some-orderbook: +raindexes: + some-raindex: address: 0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6 network: nonexistent-network subgraph: nonexistent-subgraph @@ -173,36 +173,36 @@ orderbooks: `; it('should succeed with valid YAML and validation enabled', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK, true); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX, true); + assert.ok(raindexYaml); }); it('should succeed with valid YAML and validation disabled', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK, false); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX, false); + assert.ok(raindexYaml); }); it('should succeed with valid YAML and default validation', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); - assert.ok(orderbookYaml); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); + assert.ok(raindexYaml); }); it('should fail with invalid YAML and validation enabled', async function () { - const result = OrderbookYaml.new([INVALID_YAML], true); + const result = RaindexYaml.new([INVALID_YAML], true); if (!result.error) expect.fail('Expected validation error with invalid YAML'); - expect(result.error.msg).toContain('Orderbook yaml error'); + expect(result.error.msg).toContain('Raindex yaml error'); expect(result.error.readableMsg).toContain( 'There was an error processing the YAML configuration' ); }); it('should succeed construction but fail usage with invalid YAML when validation is disabled', async function () { - const orderbookYaml = buildYaml(INVALID_YAML, false); - const orderbookResult = orderbookYaml.getOrderbookByAddress( + const raindexYaml = buildYaml(INVALID_YAML, false); + const raindexResult = raindexYaml.getRaindexByAddress( '0xc95A5f8eFe14d7a20BD2E5BAFEC4E71f8Ce0B9A6' ); - if (!orderbookResult.error) expect.fail('Expected error when using invalid YAML'); - expect(orderbookResult.error.msg).toContain('Orderbook yaml error'); + if (!raindexResult.error) expect.fail('Expected error when using invalid YAML'); + expect(raindexResult.error.msg).toContain('Raindex yaml error'); }); }); @@ -222,8 +222,8 @@ orderbooks: }); it('should return local tokens with chainId', async function () { - const orderbookYaml = buildYaml(YAML_WITHOUT_ORDERBOOK); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(YAML_WITHOUT_RAINDEX); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -263,8 +263,8 @@ tokens: // No mock set up - RPC call will fail // This tests that when token fields are missing, the code attempts to fetch from RPC // (rather than immediately returning a "missing field" error) - const orderbookYaml = buildYaml(YAML_MISSING_FIELDS); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(YAML_MISSING_FIELDS); + const tokensResult = await raindexYaml.getTokens(); assert.ok(tokensResult.error, 'Expected error when RPC fetch fails'); expect(tokensResult.error.readableMsg).toContain('Failed to fetch token information'); @@ -296,8 +296,8 @@ tokens: label: USD Coin PoS symbol: USDC `; - const orderbookYaml = buildYaml(MULTI_NETWORK_YAML); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(MULTI_NETWORK_YAML); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -366,8 +366,8 @@ networks: using-tokens-from: - http://localhost:8232/tokens.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -421,8 +421,8 @@ tokens: label: Wrapped Ether symbol: WETH `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -484,8 +484,8 @@ using-tokens-from: - http://localhost:8232/tokens1.json - http://localhost:8232/tokens2.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); @@ -540,8 +540,8 @@ networks: using-tokens-from: - http://localhost:8232/tokens-ext.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); const usdc = tokens.find((t: { symbol: string }) => t.symbol === 'USDC'); @@ -596,8 +596,8 @@ networks: using-tokens-from: - http://localhost:8232/tokens.json `; - const orderbookYaml = buildYaml(yaml); - const tokensResult = await orderbookYaml.getTokens(); + const raindexYaml = buildYaml(yaml); + const tokensResult = await raindexYaml.getTokens(); const tokens = extractWasmEncodedData(tokensResult); assert.strictEqual(tokens.length, 2); diff --git a/packages/orderbook/test/tsconfig.json b/packages/raindex/test/tsconfig.json similarity index 100% rename from packages/orderbook/test/tsconfig.json rename to packages/raindex/test/tsconfig.json diff --git a/packages/orderbook/tsconfig.json b/packages/raindex/tsconfig.json similarity index 100% rename from packages/orderbook/tsconfig.json rename to packages/raindex/tsconfig.json diff --git a/packages/orderbook/typedoc.json b/packages/raindex/typedoc.json similarity index 80% rename from packages/orderbook/typedoc.json rename to packages/raindex/typedoc.json index d8143b8bde..692fad6260 100644 --- a/packages/orderbook/typedoc.json +++ b/packages/raindex/typedoc.json @@ -14,8 +14,8 @@ "hideGenerator": true, "theme": "default", "navigationLinks": { - "GitHub": "https://github.com/rainlanguage/rain.orderbook", - "NPM": "https://www.npmjs.com/package/@rainlanguage/orderbook" + "GitHub": "https://github.com/rainlanguage/raindex", + "NPM": "https://www.npmjs.com/package/@rainlanguage/raindex" }, "kindSortOrder": [ "Class", diff --git a/packages/ui-components/ARCHITECTURE.md b/packages/ui-components/ARCHITECTURE.md index 309f9ec228..8eea2a006c 100644 --- a/packages/ui-components/ARCHITECTURE.md +++ b/packages/ui-components/ARCHITECTURE.md @@ -1,18 +1,18 @@ # @rainlanguage/ui-components — Architecture -This package is the reusable Svelte component library for building Rain Orderbook UIs. It composes the WASM‑backed SDK `@rainlanguage/orderbook` with UI primitives, domain components, providers, hooks, and utilities to implement common flows: listing and inspecting orders and vaults, showing charts, handling wallet connection and transactions, and guiding users through deploying algorithmic orders from a dotrain registry. +This package is the reusable Svelte component library for building Rain Raindex UIs. It composes the WASM‑backed SDK `@rainlanguage/raindex` with UI primitives, domain components, providers, hooks, and utilities to implement common flows: listing and inspecting orders and vaults, showing charts, handling wallet connection and transactions, and guiding users through deploying algorithmic orders from a dotrain registry. ## Overview - Purpose - - Provide a cohesive, app‑ready set of Svelte components and helpers for Orderbook features: tables, detail views, charts, deployment GUI, toasts, and transaction UX. + - Provide a cohesive, app‑ready set of Svelte components and helpers for Raindex features: tables, detail views, charts, deployment GUI, toasts, and transaction UX. - Ship provider and hook contexts so apps can wire wallet, client, registry, toasts, and transaction state consistently. - Targets - Svelte 4 components, packaged with `svelte-package` for consumption in SvelteKit/Vite apps. - Single `dist/index.js` entry (ESM) with `svelte` and `types` fields; no SSR‑specific code required. - Upstream libraries - - SDK: `@rainlanguage/orderbook` (WASM) + - SDK: `@rainlanguage/raindex` (WASM) - State/query: `@tanstack/svelte-query` - Wallet: `wagmi`, `viem`, `@reown/appkit` + `@reown/appkit-adapter-wagmi` - UI: `flowbite-svelte` (+ icons), `tailwindcss`, `lightweight-charts`, `svelte-markdown`, `svelte-codemirror-editor`, `codemirror-rainlang` @@ -30,7 +30,7 @@ nix develop -c npm run dev The library exposes lightweight provider components that set Svelte contexts, plus hooks to access them: - Raindex client - - `RaindexClientProvider` — sets a `RaindexClient` from `@rainlanguage/orderbook` in context. + - `RaindexClientProvider` — sets a `RaindexClient` from `@rainlanguage/raindex` in context. - `useRaindexClient()` — retrieves the client and reports a user‑facing error if missing. - Wallet - `WalletProvider` — injects a Svelte `Readable` account store into context. @@ -150,9 +150,9 @@ export default { ## How It Fits The Workspace -- Rust crates under `crates/*` implement core logic and compile to a WASM surface consumed by `@rainlanguage/orderbook`. +- Rust crates under `crates/*` implement core logic and compile to a WASM surface consumed by `@rainlanguage/raindex`. - `@rainlanguage/ui-components` provides the reusable Svelte UI and provider layer that apps compose. -- The `packages/webapp` project consumes this library directly to implement the full Orderbook UI. +- The `packages/webapp` project consumes this library directly to implement the full Raindex UI. ## Caveats & Tips @@ -163,5 +163,5 @@ export default { - Include this package in Tailwind `content` globs to avoid missing styles. - For deployment flows, pass a `DotrainOrderGui` via `GuiProvider` and use the registry helpers to load/validate dotrain entries. -This document explains what `packages/ui-components` is for, how providers and components are organized, how to build and test the package, and how it integrates with the rest of the Rain Orderbook workspace. +This document explains what `packages/ui-components` is for, how providers and components are organized, how to build and test the package, and how it integrates with the rest of the Rain Raindex workspace. diff --git a/packages/ui-components/package.json b/packages/ui-components/package.json index 844ee6a995..96f02d6b39 100644 --- a/packages/ui-components/package.json +++ b/packages/ui-components/package.json @@ -6,7 +6,7 @@ "author": "Rain Open Source Software Ltd", "repository": { "type": "git", - "url": "https://github.com/rainlanguage/rain.orderbook.git" + "url": "https://github.com/rainlanguage/raindex.git" }, "main": "dist/index.js", "module": "dist/index.js", @@ -57,7 +57,7 @@ "@fontsource/dm-sans": "5.1.0", "@imask/svelte": "7.6.1", "@observablehq/plot": "0.6.16", - "@rainlanguage/orderbook": "0.0.1-alpha.229", + "@rainlanguage/raindex": "0.0.1-alpha.229", "@reown/appkit": "1.6.4", "@reown/appkit-adapter-wagmi": "1.6.4", "@sentry/sveltekit": "7.120.0", diff --git a/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts b/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts index c183ce81a4..9dff7fa6c0 100644 --- a/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts +++ b/packages/ui-components/src/__tests__/ButtonVaultLink.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from 'vitest'; import { render, screen } from '@testing-library/svelte'; import ButtonVaultLink from '../lib/components/ButtonVaultLink.svelte'; -import type { RaindexVault } from '@rainlanguage/orderbook'; +import type { RaindexVault } from '@rainlanguage/raindex'; describe('ButtonVaultLink', () => { const mockVault = { @@ -20,7 +20,7 @@ describe('ButtonVaultLink', () => { props: { tokenVault: mockVault, chainId: 1, - orderbookAddress: '0x00' + raindexAddress: '0x00' } }); @@ -35,7 +35,7 @@ describe('ButtonVaultLink', () => { props: { tokenVault: mockVault, chainId: 1, - orderbookAddress: '0x00' + raindexAddress: '0x00' } }); diff --git a/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts b/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts index 693bbc03af..4b87b107d5 100644 --- a/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts +++ b/packages/ui-components/src/__tests__/CodeMirrorRainlang.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, waitFor } from '@testing-library/svelte'; import CodeMirrorRainlang from '../lib/components/CodeMirrorRainlang.svelte'; -import type { RaindexOrder } from '@rainlanguage/orderbook'; +import type { RaindexOrder } from '@rainlanguage/raindex'; import { writable } from 'svelte/store'; vi.mock('codemirror-rainlang', () => ({ diff --git a/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts b/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts index f281496fc9..314102b5eb 100644 --- a/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts +++ b/packages/ui-components/src/__tests__/ComposedRainlangModal.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { render, fireEvent, waitFor } from '@testing-library/svelte'; import ComposedRainlangModal from '../lib/components/deployment/ComposedRainlangModal.svelte'; -import type { DotrainOrderGui } from '@rainlanguage/orderbook'; +import type { DotrainOrderGui } from '@rainlanguage/raindex'; import { useGui } from '$lib/hooks/useGui'; vi.mock('svelte-codemirror-editor', async () => { diff --git a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts index 9b60495838..66a0e72289 100644 --- a/packages/ui-components/src/__tests__/DeploymentSteps.test.ts +++ b/packages/ui-components/src/__tests__/DeploymentSteps.test.ts @@ -1,18 +1,18 @@ import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { render, screen, waitFor } from '@testing-library/svelte'; import DeploymentSteps from '../lib/components/deployment/DeploymentSteps.svelte'; -import { DotrainOrderGui, type ScenarioCfg } from '@rainlanguage/orderbook'; +import { DotrainOrderGui, type ScenarioCfg } from '@rainlanguage/raindex'; import type { ComponentProps } from 'svelte'; import { readable, writable } from 'svelte/store'; import type { AppKit } from '@reown/appkit'; -import type { GuiDeploymentCfg, RaindexClient } from '@rainlanguage/orderbook'; +import type { GuiDeploymentCfg, RaindexClient } from '@rainlanguage/raindex'; import userEvent from '@testing-library/user-event'; import { useGui } from '$lib/hooks/useGui'; import { useAccount } from '$lib/providers/wallet/useAccount'; import type { Account } from '$lib/types/account'; import { useRaindexClient } from '$lib/hooks/useRaindexClient'; -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ DotrainOrderGui: vi.fn() })); @@ -71,7 +71,7 @@ const mockDeployment = { }, address: '0x0' }, - orderbook: { + raindex: { id: 'flare', address: '0x0' }, diff --git a/packages/ui-components/src/__tests__/DepositInput.test.ts b/packages/ui-components/src/__tests__/DepositInput.test.ts index 80b6defc89..187a388a78 100644 --- a/packages/ui-components/src/__tests__/DepositInput.test.ts +++ b/packages/ui-components/src/__tests__/DepositInput.test.ts @@ -1,13 +1,13 @@ import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { render, fireEvent, waitFor } from '@testing-library/svelte'; import DepositInput from '../lib/components/deployment/DepositInput.svelte'; -import type { GuiDepositCfg } from '@rainlanguage/orderbook'; +import type { GuiDepositCfg } from '@rainlanguage/raindex'; import type { ComponentProps } from 'svelte'; -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; import { useGui } from '$lib/hooks/useGui'; type DepositInputProps = ComponentProps; -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ DotrainOrderGui: vi.fn() })); diff --git a/packages/ui-components/src/__tests__/DotrainRainlangProvider.test.ts b/packages/ui-components/src/__tests__/DotrainRainlangProvider.test.ts index 2ef789533a..4be8acfb2e 100644 --- a/packages/ui-components/src/__tests__/DotrainRainlangProvider.test.ts +++ b/packages/ui-components/src/__tests__/DotrainRainlangProvider.test.ts @@ -30,7 +30,7 @@ describe('DotrainRainlangProvider', () => { getOrderKeys: vi.fn(() => ({ value: [], error: undefined })), getDeploymentDetails: vi.fn(() => wasmErrorResult), getGui: vi.fn(async () => wasmErrorResult), - getOrderbookYaml: vi.fn(() => wasmErrorResult), + getRaindexYaml: vi.fn(() => wasmErrorResult), getRaindexClient: vi.fn(async () => wasmErrorResult), rainlangUrl, rainlang: 'rainlang-content', diff --git a/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts b/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts index 6dfbde533b..e3f256e94e 100644 --- a/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts +++ b/packages/ui-components/src/__tests__/DropdownActiveNetworks.test.ts @@ -3,7 +3,7 @@ import { get, writable, type Writable } from 'svelte/store'; import { beforeEach, expect, test, describe, type Mock } from 'vitest'; import DropdownActiveNetworks from '../lib/components/dropdown/DropdownActiveNetworks.svelte'; import { useRaindexClient } from '$lib/hooks/useRaindexClient'; -import type { NetworkCfg } from '@rainlanguage/orderbook'; +import type { NetworkCfg } from '@rainlanguage/raindex'; vi.mock('$lib/hooks/useRaindexClient', () => ({ useRaindexClient: vi.fn() diff --git a/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts b/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts deleted file mode 100644 index ea8c0c0238..0000000000 --- a/packages/ui-components/src/__tests__/DropdownOrderbooksFilter.test.ts +++ /dev/null @@ -1,498 +0,0 @@ -import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; -import { get, writable } from 'svelte/store'; -import DropdownOrderbooksFilter from '../lib/components/dropdown/DropdownOrderbooksFilter.svelte'; -import { expect, test, describe, beforeEach, vi, type Mock } from 'vitest'; -import type { Address } from '@rainlanguage/orderbook'; -import { useRaindexClient } from '$lib/hooks/useRaindexClient'; - -vi.mock('$lib/hooks/useRaindexClient', () => ({ - useRaindexClient: vi.fn() -})); - -const mockOrderbooksData = new Map([ - [ - 'orderbook1', - { - key: 'orderbook1', - address: '0x1234567890123456789012345678901234567890', - label: 'Orderbook One', - network: { chainId: 1 } - } - ], - [ - 'orderbook2', - { - key: 'orderbook2', - address: '0x2345678901234567890123456789012345678901', - label: 'Orderbook Two', - network: { chainId: 1 } - } - ], - [ - 'orderbook3', - { - key: 'orderbook3', - address: '0x3456789012345678901234567890123456789012', - label: null, - network: { chainId: 137 } - } - ] -]); - -describe('DropdownOrderbooksFilter', () => { - let activeOrderbookAddresses: ReturnType>; - - beforeEach(() => { - activeOrderbookAddresses = writable([]); - - (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ - value: mockOrderbooksData, - error: undefined - })) - }); - }); - - describe('Empty state', () => { - test('displays empty message when no orderbooks available', async () => { - (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ - value: new Map(), - error: undefined - })) - }); - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect(screen.getByText('No orderbooks available')).toBeInTheDocument(); - }); - }); - - test('displays custom empty message', async () => { - (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ - value: new Map(), - error: undefined - })) - }); - - const customEmptyMessage = 'Orderbook list is empty'; - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [], - emptyMessage: customEmptyMessage - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect(screen.getByText(customEmptyMessage)).toBeInTheDocument(); - }); - }); - }); - - describe('Error state', () => { - test('displays error message when getAllOrderbooks returns error', async () => { - const errorMessage = 'Failed to load orderbooks'; - (useRaindexClient as Mock).mockReturnValue({ - getAllOrderbooks: vi.fn(() => ({ - value: undefined, - error: { readableMsg: errorMessage } - })) - }); - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect( - screen.getByText(`Cannot load orderbooks list: ${errorMessage}`) - ).toBeInTheDocument(); - }); - }); - }); - - describe('Selected orderbooks display', () => { - test('displays "Select orderbooks" when no orderbooks are selected', () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - expect(screen.getByText('Select orderbooks')).toBeInTheDocument(); - }); - - test('displays "All orderbooks" when all orderbooks are selected', () => { - const allAddresses = Array.from(mockOrderbooksData.values()).map( - (ob) => ob.address - ) as Address[]; - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: allAddresses, - selectedChainIds: [] - } - }); - - expect(screen.getByText('All orderbooks')).toBeInTheDocument(); - }); - - test('displays custom all label when all orderbooks are selected', () => { - const allAddresses = Array.from(mockOrderbooksData.values()).map( - (ob) => ob.address - ) as Address[]; - const customAllLabel = 'Everything selected'; - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: allAddresses, - selectedChainIds: [], - allLabel: customAllLabel - } - }); - - expect(screen.getByText(customAllLabel)).toBeInTheDocument(); - }); - - test('displays count when one orderbook is selected', () => { - const selectedAddress = Array.from(mockOrderbooksData.values())[0].address as Address; - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [selectedAddress], - selectedChainIds: [] - } - }); - - expect(screen.getByText('1 orderbook')).toBeInTheDocument(); - }); - - test('displays plural count when multiple orderbooks are selected', () => { - const selectedAddresses = Array.from(mockOrderbooksData.values()) - .slice(0, 2) - .map((ob) => ob.address) as Address[]; - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: selectedAddresses, - selectedChainIds: [] - } - }); - - expect(screen.getByText('2 orderbooks')).toBeInTheDocument(); - }); - - test('updates selected orderbooks when checkbox is clicked', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const checkboxes = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - await fireEvent.click(checkboxes[0]); - - await waitFor(() => { - const selected = get(activeOrderbookAddresses); - expect(selected.length).toBe(1); - }); - }); - - test('shows selected orderbooks as checked', async () => { - const selectedAddress = Array.from(mockOrderbooksData.values())[0].address as Address; - - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [selectedAddress], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect(screen.getByText('1 orderbook')).toBeInTheDocument(); - }); - }); - }); - - describe('Chain filtering', () => { - test('shows all orderbooks when selectedChainIds is empty', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - expect(checkboxes.length).toBe(3); - }); - }); - - test('filters orderbooks by selected chain ID', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [1] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - expect(checkboxes.length).toBe(2); - }); - }); - - test('shows orderbooks from multiple selected chains', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [1, 137] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - const checkboxes = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - expect(checkboxes.length).toBe(3); - }); - }); - }); - - describe('Display format', () => { - test('displays label with truncated address when label exists', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect(screen.getByText(/Orderbook One/)).toBeInTheDocument(); - expect(screen.getByText(/0x1234\.\.\.7890/)).toBeInTheDocument(); - }); - }); - - test('displays only truncated address when no label', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [137] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect(screen.getByText(/0x3456\.\.\.9012/)).toBeInTheDocument(); - }); - }); - - test('displays network name next to each orderbook', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - await waitFor(() => { - expect(screen.getAllByText('Ethereum').length).toBeGreaterThan(0); - expect(screen.getByText('Polygon')).toBeInTheDocument(); - }); - }); - }); - - describe('Search and keyboard navigation', () => { - test('filters orderbooks based on search term (label)', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const searchInput = screen.getByTestId('orderbooks-filter-search'); - await fireEvent.input(searchInput, { target: { value: 'One' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - expect(options).toHaveLength(1); - expect(screen.getByText(/Orderbook One/)).toBeInTheDocument(); - }); - }); - - test('filters orderbooks based on search term (address)', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const searchInput = screen.getByTestId('orderbooks-filter-search'); - await fireEvent.input(searchInput, { target: { value: '0x1234' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - expect(options).toHaveLength(1); - }); - }); - - test('shows "No orderbooks match your search" when search yields no results', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const searchInput = screen.getByTestId('orderbooks-filter-search'); - await fireEvent.input(searchInput, { target: { value: 'NONEXISTENT' } }); - - await waitFor(() => { - expect(screen.getByText('No orderbooks match your search')).toBeInTheDocument(); - }); - }); - - test('keyboard navigation works correctly (ArrowDown/ArrowUp)', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const searchInput = screen.getByTestId('orderbooks-filter-search'); - - await fireEvent.keyDown(searchInput, { key: 'ArrowDown' }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - const secondItemLabel = options[1].closest('label'); - expect(secondItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - - await fireEvent.keyDown(searchInput, { key: 'ArrowUp' }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - const firstItemLabel = options[0].closest('label'); - expect(firstItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); - }); - }); - - test('Enter key selects highlighted orderbook', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const searchInput = screen.getByTestId('orderbooks-filter-search'); - - await fireEvent.input(searchInput, { target: { value: 'One' } }); - - await waitFor(() => { - const options = screen.getAllByTestId('dropdown-orderbooks-filter-option'); - expect(options).toHaveLength(1); - }); - - await fireEvent.keyDown(searchInput, { key: 'Enter' }); - - await waitFor(() => { - const selected = get(activeOrderbookAddresses); - expect(selected).toContain('0x1234567890123456789012345678901234567890'.toLowerCase()); - }); - }); - - test('Escape key clears search', async () => { - render(DropdownOrderbooksFilter, { - props: { - activeOrderbookAddresses, - selectedOrderbookAddresses: [], - selectedChainIds: [] - } - }); - - await fireEvent.click(screen.getByTestId('dropdown-orderbooks-filter-button')); - - const searchInput = screen.getByTestId('orderbooks-filter-search') as HTMLInputElement; - - await fireEvent.input(searchInput, { target: { value: 'One' } }); - expect(searchInput.value).toBe('One'); - - await fireEvent.keyDown(searchInput, { key: 'Escape' }); - - await waitFor(() => { - expect(searchInput.value).toBe(''); - }); - }); - }); -}); diff --git a/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts new file mode 100644 index 0000000000..75a63d5e60 --- /dev/null +++ b/packages/ui-components/src/__tests__/DropdownRaindexesFilter.test.ts @@ -0,0 +1,496 @@ +import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; +import { get, writable } from 'svelte/store'; +import DropdownRaindexesFilter from '../lib/components/dropdown/DropdownRaindexesFilter.svelte'; +import { expect, test, describe, beforeEach, vi, type Mock } from 'vitest'; +import type { Address } from '@rainlanguage/raindex'; +import { useRaindexClient } from '$lib/hooks/useRaindexClient'; + +vi.mock('$lib/hooks/useRaindexClient', () => ({ + useRaindexClient: vi.fn() +})); + +const mockRaindexesData = new Map([ + [ + 'raindex1', + { + key: 'raindex1', + address: '0x1234567890123456789012345678901234567890', + label: 'Raindex One', + network: { chainId: 1 } + } + ], + [ + 'raindex2', + { + key: 'raindex2', + address: '0x2345678901234567890123456789012345678901', + label: 'Raindex Two', + network: { chainId: 1 } + } + ], + [ + 'raindex3', + { + key: 'raindex3', + address: '0x3456789012345678901234567890123456789012', + label: null, + network: { chainId: 137 } + } + ] +]); + +describe('DropdownRaindexesFilter', () => { + let activeRaindexAddresses: ReturnType>; + + beforeEach(() => { + activeRaindexAddresses = writable([]); + + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: mockRaindexesData, + error: undefined + })) + }); + }); + + describe('Empty state', () => { + test('displays empty message when no raindexes available', async () => { + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: new Map(), + error: undefined + })) + }); + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getByText('No raindexes available')).toBeInTheDocument(); + }); + }); + + test('displays custom empty message', async () => { + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: new Map(), + error: undefined + })) + }); + + const customEmptyMessage = 'Raindex list is empty'; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [], + emptyMessage: customEmptyMessage + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getByText(customEmptyMessage)).toBeInTheDocument(); + }); + }); + }); + + describe('Error state', () => { + test('displays error message when getAllRaindexes returns error', async () => { + const errorMessage = 'Failed to load raindexes'; + (useRaindexClient as Mock).mockReturnValue({ + getAllRaindexes: vi.fn(() => ({ + value: undefined, + error: { readableMsg: errorMessage } + })) + }); + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getByText(`Cannot load raindexes list: ${errorMessage}`)).toBeInTheDocument(); + }); + }); + }); + + describe('Selected raindexes display', () => { + test('displays "Select raindexes" when no raindexes are selected', () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + expect(screen.getByText('Select raindexes')).toBeInTheDocument(); + }); + + test('displays "All raindexes" when all raindexes are selected', () => { + const allAddresses = Array.from(mockRaindexesData.values()).map( + (raindex) => raindex.address + ) as Address[]; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: allAddresses, + selectedChainIds: [] + } + }); + + expect(screen.getByText('All raindexes')).toBeInTheDocument(); + }); + + test('displays custom all label when all raindexes are selected', () => { + const allAddresses = Array.from(mockRaindexesData.values()).map( + (raindex) => raindex.address + ) as Address[]; + const customAllLabel = 'Everything selected'; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: allAddresses, + selectedChainIds: [], + allLabel: customAllLabel + } + }); + + expect(screen.getByText(customAllLabel)).toBeInTheDocument(); + }); + + test('displays count when one raindex is selected', () => { + const selectedAddress = Array.from(mockRaindexesData.values())[0].address as Address; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [selectedAddress], + selectedChainIds: [] + } + }); + + expect(screen.getByText('1 raindex')).toBeInTheDocument(); + }); + + test('displays plural count when multiple raindexes are selected', () => { + const selectedAddresses = Array.from(mockRaindexesData.values()) + .slice(0, 2) + .map((raindex) => raindex.address) as Address[]; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: selectedAddresses, + selectedChainIds: [] + } + }); + + expect(screen.getByText('2 raindexes')).toBeInTheDocument(); + }); + + test('updates selected raindexes when checkbox is clicked', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); + await fireEvent.click(checkboxes[0]); + + await waitFor(() => { + const selected = get(activeRaindexAddresses); + expect(selected.length).toBe(1); + }); + }); + + test('shows selected raindexes as checked', async () => { + const selectedAddress = Array.from(mockRaindexesData.values())[0].address as Address; + + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [selectedAddress], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getByText('1 raindex')).toBeInTheDocument(); + }); + }); + }); + + describe('Chain filtering', () => { + test('shows all raindexes when selectedChainIds is empty', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); + expect(checkboxes.length).toBe(3); + }); + }); + + test('filters raindexes by selected chain ID', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [1] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); + expect(checkboxes.length).toBe(2); + }); + }); + + test('shows raindexes from multiple selected chains', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [1, 137] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + const checkboxes = screen.getAllByTestId('dropdown-raindexes-filter-option'); + expect(checkboxes.length).toBe(3); + }); + }); + }); + + describe('Display format', () => { + test('displays label with truncated address when label exists', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); + expect(screen.getByText(/0x1234\.\.\.7890/)).toBeInTheDocument(); + }); + }); + + test('displays only truncated address when no label', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [137] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getByText(/0x3456\.\.\.9012/)).toBeInTheDocument(); + }); + }); + + test('displays network name next to each raindex', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + await waitFor(() => { + expect(screen.getAllByText('Ethereum').length).toBeGreaterThan(0); + expect(screen.getByText('Polygon')).toBeInTheDocument(); + }); + }); + }); + + describe('Search and keyboard navigation', () => { + test('filters raindexes based on search term (label)', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const searchInput = screen.getByTestId('raindexes-filter-search'); + await fireEvent.input(searchInput, { target: { value: 'One' } }); + + await waitFor(() => { + const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); + expect(options).toHaveLength(1); + expect(screen.getByText(/Raindex One/)).toBeInTheDocument(); + }); + }); + + test('filters raindexes based on search term (address)', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const searchInput = screen.getByTestId('raindexes-filter-search'); + await fireEvent.input(searchInput, { target: { value: '0x1234' } }); + + await waitFor(() => { + const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); + expect(options).toHaveLength(1); + }); + }); + + test('shows "No raindexes match your search" when search yields no results', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const searchInput = screen.getByTestId('raindexes-filter-search'); + await fireEvent.input(searchInput, { target: { value: 'NONEXISTENT' } }); + + await waitFor(() => { + expect(screen.getByText('No raindexes match your search')).toBeInTheDocument(); + }); + }); + + test('keyboard navigation works correctly (ArrowDown/ArrowUp)', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const searchInput = screen.getByTestId('raindexes-filter-search'); + + await fireEvent.keyDown(searchInput, { key: 'ArrowDown' }); + + await waitFor(() => { + const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); + const secondItemLabel = options[1].closest('label'); + expect(secondItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); + }); + + await fireEvent.keyDown(searchInput, { key: 'ArrowUp' }); + + await waitFor(() => { + const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); + const firstItemLabel = options[0].closest('label'); + expect(firstItemLabel).toHaveClass('bg-blue-100', 'dark:bg-blue-900'); + }); + }); + + test('Enter key selects highlighted raindex', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const searchInput = screen.getByTestId('raindexes-filter-search'); + + await fireEvent.input(searchInput, { target: { value: 'One' } }); + + await waitFor(() => { + const options = screen.getAllByTestId('dropdown-raindexes-filter-option'); + expect(options).toHaveLength(1); + }); + + await fireEvent.keyDown(searchInput, { key: 'Enter' }); + + await waitFor(() => { + const selected = get(activeRaindexAddresses); + expect(selected).toContain('0x1234567890123456789012345678901234567890'.toLowerCase()); + }); + }); + + test('Escape key clears search', async () => { + render(DropdownRaindexesFilter, { + props: { + activeRaindexAddresses, + selectedRaindexAddresses: [], + selectedChainIds: [] + } + }); + + await fireEvent.click(screen.getByTestId('dropdown-raindexes-filter-button')); + + const searchInput = screen.getByTestId('raindexes-filter-search') as HTMLInputElement; + + await fireEvent.input(searchInput, { target: { value: 'One' } }); + expect(searchInput.value).toBe('One'); + + await fireEvent.keyDown(searchInput, { key: 'Escape' }); + + await waitFor(() => { + expect(searchInput.value).toBe(''); + }); + }); + }); +}); diff --git a/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts b/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts index e4a1fc7860..6df8345f2e 100644 --- a/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts +++ b/packages/ui-components/src/__tests__/DropdownTokensFilter.test.ts @@ -2,7 +2,7 @@ import { render, fireEvent, screen, waitFor } from '@testing-library/svelte'; import { get, writable, readable } from 'svelte/store'; import DropdownTokensFilter from '../lib/components/dropdown/DropdownTokensFilter.svelte'; import { expect, test, describe, beforeEach } from 'vitest'; -import type { Address, RaindexVaultToken } from '@rainlanguage/orderbook'; +import type { Address, RaindexVaultToken } from '@rainlanguage/raindex'; import type { QueryObserverResult } from '@tanstack/svelte-query'; describe('DropdownTokensFilter', () => { diff --git a/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts b/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts index aafcec1895..c9a6ac12de 100644 --- a/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts +++ b/packages/ui-components/src/__tests__/FieldDefinitionInput.test.ts @@ -1,14 +1,14 @@ import { render, fireEvent } from '@testing-library/svelte'; import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import FieldDefinitionInput from '../lib/components/deployment/FieldDefinitionInput.svelte'; -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; import userEvent from '@testing-library/user-event'; import { useGui } from '$lib/hooks/useGui'; import type { ComponentProps } from 'svelte'; type FieldDefinitionInputProps = ComponentProps; -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ DotrainOrderGui: vi.fn() })); diff --git a/packages/ui-components/src/__tests__/InputOrderHash.test.ts b/packages/ui-components/src/__tests__/InputOrderHash.test.ts index 2aa4f51180..0c3838380d 100644 --- a/packages/ui-components/src/__tests__/InputOrderHash.test.ts +++ b/packages/ui-components/src/__tests__/InputOrderHash.test.ts @@ -1,7 +1,7 @@ import { render, fireEvent } from '@testing-library/svelte'; import { writable, get } from 'svelte/store'; import InputOrderHash from '../lib/components/input/InputOrderHash.svelte'; -import type { Hex } from '@rainlanguage/orderbook'; +import type { Hex } from '@rainlanguage/raindex'; describe('InputOrderHash', () => { it('renders with initial value', () => { diff --git a/packages/ui-components/src/__tests__/InputTokenAmount.test.ts b/packages/ui-components/src/__tests__/InputTokenAmount.test.ts index 609449c6cb..cce7f7faea 100644 --- a/packages/ui-components/src/__tests__/InputTokenAmount.test.ts +++ b/packages/ui-components/src/__tests__/InputTokenAmount.test.ts @@ -1,9 +1,9 @@ import { render, fireEvent } from '@testing-library/svelte'; import { describe, it, expect } from 'vitest'; import InputTokenAmount from '$lib/components/input/InputTokenAmount.svelte'; -import { Float } from '@rainlanguage/orderbook'; +import { Float } from '@rainlanguage/raindex'; -vi.mock('@rainlanguage/orderbook', async (importOriginal) => ({ +vi.mock('@rainlanguage/raindex', async (importOriginal) => ({ ...(await importOriginal()) })); diff --git a/packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts b/packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts similarity index 74% rename from packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts rename to packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts index fb412402b0..9c75187bda 100644 --- a/packages/ui-components/src/__tests__/ListViewOrderbookFilters.test.ts +++ b/packages/ui-components/src/__tests__/ListViewRaindexFilters.test.ts @@ -1,8 +1,8 @@ import { render, screen } from '@testing-library/svelte'; import { readable, writable } from 'svelte/store'; import { beforeEach, expect, test, describe, vi, type Mock } from 'vitest'; -import ListViewOrderbookFilters from '../lib/components/ListViewOrderbookFilters.svelte'; -import type { Address, RaindexVaultToken } from '@rainlanguage/orderbook'; +import ListViewRaindexFilters from '../lib/components/ListViewRaindexFilters.svelte'; +import type { Address, RaindexVaultToken } from '@rainlanguage/raindex'; import type { ComponentProps } from 'svelte'; import type { QueryObserverResult } from '@tanstack/svelte-query'; import { useRaindexClient } from '$lib/hooks/useRaindexClient'; @@ -30,12 +30,12 @@ vi.mock('$lib/hooks/useRaindexClient', () => ({ useRaindexClient: vi.fn() })); -type ListViewOrderbookFiltersProps = ComponentProps; +type ListViewRaindexFiltersProps = ComponentProps; -describe('ListViewOrderbookFilters', () => { - const mockGetAllOrderbooks = vi.fn(); +describe('ListViewRaindexFilters', () => { + const mockGetAllRaindexes = vi.fn(); - const defaultProps: ListViewOrderbookFiltersProps = { + const defaultProps: ListViewRaindexFiltersProps = { hideZeroBalanceVaults: writable(false), hideInactiveOrdersVaults: writable(false), selectedChainIds: writable([]), @@ -49,13 +49,13 @@ describe('ListViewOrderbookFilters', () => { data: [] as RaindexVaultToken[], error: null } as QueryObserverResult), - activeOrderbookAddresses: writable([]), - selectedOrderbookAddresses: [], + activeRaindexAddresses: writable([]), + selectedRaindexAddresses: [], ownerFilter: writable
('' as unknown as Address) - } as ListViewOrderbookFiltersProps; + } as ListViewRaindexFiltersProps; beforeEach(() => { - mockGetAllOrderbooks.mockReturnValue({ + mockGetAllRaindexes.mockReturnValue({ value: new Map(), error: undefined }); @@ -80,7 +80,7 @@ describe('ListViewOrderbookFilters', () => { ]), error: undefined })), - getAllOrderbooks: mockGetAllOrderbooks + getAllRaindexes: mockGetAllRaindexes }); mockAccount.set(null); @@ -93,7 +93,7 @@ describe('ListViewOrderbookFilters', () => { error: undefined })) }); - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); expect(screen.getByTestId('no-networks-alert')).toBeInTheDocument(); }); @@ -104,7 +104,7 @@ describe('ListViewOrderbookFilters', () => { pathname: '/vaults' } as URL }); - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); expect(screen.getByTestId('zero-balance-vault-checkbox')).toBeInTheDocument(); expect(screen.getByTestId('inactive-orders-vault-checkbox')).toBeInTheDocument(); @@ -118,7 +118,7 @@ describe('ListViewOrderbookFilters', () => { pathname: '/orders' } as URL }); - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); expect(screen.getByTestId('order-hash-input')).toBeInTheDocument(); expect(screen.getByTestId('order-status-checkbox')).toBeInTheDocument(); @@ -127,14 +127,14 @@ describe('ListViewOrderbookFilters', () => { }); test('shows common components when networks exist', () => { - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); expect(screen.getByTestId('subgraphs-dropdown')).toBeInTheDocument(); }); test('does not show page-specific components on default view', () => { mockPageStore.reset(); - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); expect(screen.queryByTestId('zero-balance-vault-checkbox')).not.toBeInTheDocument(); expect(screen.queryByTestId('inactive-orders-vault-checkbox')).not.toBeInTheDocument(); @@ -143,20 +143,20 @@ describe('ListViewOrderbookFilters', () => { }); test('shows owner filter input', () => { - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); expect(screen.getByTestId('owner-filter-input')).toBeInTheDocument(); }); - test('shows orderbooks dropdown when orderbooks exist', () => { - mockGetAllOrderbooks.mockReturnValue({ + test('shows raindexes dropdown when raindexes exist', () => { + mockGetAllRaindexes.mockReturnValue({ value: new Map([ [ - 'orderbook1', + 'raindex1', { - key: 'orderbook1', + key: 'raindex1', address: '0x1234567890123456789012345678901234567890', - label: 'Test Orderbook', + label: 'Test Raindex', network: { chainId: 1 } } ] @@ -184,22 +184,22 @@ describe('ListViewOrderbookFilters', () => { ]), error: undefined })), - getAllOrderbooks: mockGetAllOrderbooks + getAllRaindexes: mockGetAllRaindexes }); - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); - expect(screen.getByTestId('dropdown-orderbooks-filter-button')).toBeInTheDocument(); + expect(screen.getByTestId('dropdown-raindexes-filter-button')).toBeInTheDocument(); }); - test('shows orderbooks dropdown even when no orderbooks exist', () => { - mockGetAllOrderbooks.mockReturnValue({ + test('shows raindexes dropdown even when no raindexes exist', () => { + mockGetAllRaindexes.mockReturnValue({ value: new Map(), error: undefined }); - render(ListViewOrderbookFilters, defaultProps); + render(ListViewRaindexFilters, defaultProps); - expect(screen.getByTestId('dropdown-orderbooks-filter-button')).toBeInTheDocument(); + expect(screen.getByTestId('dropdown-raindexes-filter-button')).toBeInTheDocument(); }); }); diff --git a/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts index 0c4ab76213..e500d9beb9 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusCard.test.ts @@ -1,7 +1,7 @@ import { render, screen, cleanup, fireEvent } from '@testing-library/svelte'; import { describe, it, expect, afterEach, vi } from 'vitest'; import LocalDbStatusCard from '../lib/components/LocalDbStatusCard.svelte'; -import type { NetworkSyncStatus, OrderbookSyncStatus } from '@rainlanguage/orderbook'; +import type { NetworkSyncStatus, RaindexSyncStatus } from '@rainlanguage/raindex'; vi.mock('$lib/utils/getNetworkName', () => ({ getNetworkName: (chainId: number) => { @@ -83,24 +83,24 @@ describe('LocalDbStatusCard', () => { render(LocalDbStatusCard, { props: { networkStatuses: new Map(), - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); expect(screen.getByText('Active')).toBeInTheDocument(); }); - it('accepts orderbookStatuses prop', () => { + it('accepts raindexStatuses prop', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'active', schedulerState: 'leader' @@ -109,7 +109,7 @@ describe('LocalDbStatusCard', () => { ]); render(LocalDbStatusCard, { - props: { networkStatuses, orderbookStatuses } + props: { networkStatuses, raindexStatuses } }); expect(screen.getByText('Active')).toBeInTheDocument(); diff --git a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts index 6d83fdebf5..49681786a4 100644 --- a/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts +++ b/packages/ui-components/src/__tests__/LocalDbStatusModal.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, afterEach, vi } from 'vitest'; import { render, screen, cleanup } from '@testing-library/svelte'; import LocalDbStatusModal from '../lib/components/LocalDbStatusModal.svelte'; -import type { NetworkSyncStatus, OrderbookSyncStatus } from '@rainlanguage/orderbook'; +import type { NetworkSyncStatus, RaindexSyncStatus } from '@rainlanguage/raindex'; vi.mock('$lib/utils/getNetworkName', () => ({ getNetworkName: (chainId: number) => { @@ -24,7 +24,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses: new Map(), - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); @@ -36,7 +36,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses: new Map(), - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); @@ -53,7 +53,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); @@ -70,7 +70,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); @@ -86,7 +86,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); @@ -102,24 +102,24 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); expect(screen.queryByText('Observing')).not.toBeInTheDocument(); }); - it('displays orderbook addresses under their network', () => { + it('displays raindex addresses under their network', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'active', schedulerState: 'leader' @@ -131,24 +131,24 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); expect(screen.getByText('0x1234567890123456789012345678901234567890')).toBeInTheDocument(); }); - it('shows phase message when orderbook is syncing', () => { + it('shows phase message when raindex is syncing', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'syncing', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'syncing', schedulerState: 'leader', @@ -161,24 +161,24 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); expect(screen.getByText('Fetching latest block')).toBeInTheDocument(); }); - it('does not show phase message when orderbook status is not syncing', () => { + it('does not show phase message when raindex status is not syncing', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'active', schedulerState: 'leader', @@ -191,24 +191,24 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); expect(screen.queryByText('This should not appear')).not.toBeInTheDocument(); }); - it('shows error message when orderbook has failure', () => { + it('shows error message when raindex has failure', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'failure', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'failure', schedulerState: 'leader', @@ -221,7 +221,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); @@ -245,25 +245,25 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses: new Map() + raindexStatuses: new Map() } }); expect(screen.getByText('Network initialization failed')).toBeInTheDocument(); }); - it('groups orderbooks correctly by chain ID', () => { + it('groups raindexes correctly by chain ID', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }], [42161, { chainId: 42161, status: 'active', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1111111111111111111111111111111111111111', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1111111111111111111111111111111111111111' + raindexAddress: '0x1111111111111111111111111111111111111111' }, status: 'active', schedulerState: 'leader' @@ -272,9 +272,9 @@ describe('LocalDbStatusModal', () => { [ '42161:0x2222222222222222222222222222222222222222', { - obId: { + raindexId: { chainId: 42161, - orderbookAddress: '0x2222222222222222222222222222222222222222' + raindexAddress: '0x2222222222222222222222222222222222222222' }, status: 'syncing', schedulerState: 'leader' @@ -286,7 +286,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); @@ -299,17 +299,17 @@ describe('LocalDbStatusModal', () => { expect(screen.getByText('0x2222222222222222222222222222222222222222')).toBeInTheDocument(); }); - it('handles multiple orderbooks on the same network', () => { + it('handles multiple raindexes on the same network', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1111111111111111111111111111111111111111', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1111111111111111111111111111111111111111' + raindexAddress: '0x1111111111111111111111111111111111111111' }, status: 'active', schedulerState: 'leader' @@ -318,9 +318,9 @@ describe('LocalDbStatusModal', () => { [ '137:0x2222222222222222222222222222222222222222', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x2222222222222222222222222222222222222222' + raindexAddress: '0x2222222222222222222222222222222222222222' }, status: 'syncing', schedulerState: 'leader', @@ -333,7 +333,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); @@ -342,17 +342,17 @@ describe('LocalDbStatusModal', () => { expect(screen.getByText('Running bootstrap')).toBeInTheDocument(); }); - it('does not show orderbook error when status is not failure', () => { + it('does not show raindex error when status is not failure', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'active', schedulerState: 'leader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'active', schedulerState: 'leader', @@ -365,7 +365,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); @@ -376,13 +376,13 @@ describe('LocalDbStatusModal', () => { const networkStatuses = new Map([ [137, { chainId: 137, status: 'syncing', schedulerState: 'notLeader' }] ]); - const orderbookStatuses = new Map([ + const raindexStatuses = new Map([ [ '137:0x1234567890123456789012345678901234567890', { - obId: { + raindexId: { chainId: 137, - orderbookAddress: '0x1234567890123456789012345678901234567890' + raindexAddress: '0x1234567890123456789012345678901234567890' }, status: 'syncing', schedulerState: 'notLeader', @@ -395,7 +395,7 @@ describe('LocalDbStatusModal', () => { props: { open: true, networkStatuses, - orderbookStatuses + raindexStatuses } }); diff --git a/packages/ui-components/src/__tests__/OrderAPY.test.ts b/packages/ui-components/src/__tests__/OrderAPY.test.ts index 45cbcb7f64..0cce0e39c1 100644 --- a/packages/ui-components/src/__tests__/OrderAPY.test.ts +++ b/packages/ui-components/src/__tests__/OrderAPY.test.ts @@ -2,7 +2,7 @@ // import { test, vi } from 'vitest'; import { test } from 'vitest'; // import { expect } from '$lib/test/matchers'; -// import type { OrderPerformance, RaindexOrder } from '@rainlanguage/orderbook'; +// import type { OrderPerformance, RaindexOrder } from '@rainlanguage/raindex'; // import { QueryClient } from '@tanstack/svelte-query'; // import OrderApy from '../lib/components/tables/OrderAPY.svelte'; // import { bigintStringToPercentage } from '../lib/utils/number'; @@ -10,7 +10,7 @@ import { test } from 'vitest'; // const mockOrderApy: OrderPerformance = { // orderId: '1', // orderHash: '1', -// orderbook: '1', +// raindex: '1', // denominatedPerformance: { // apy: '1200000000000000000', // apyIsNeg: true, diff --git a/packages/ui-components/src/__tests__/OrderDetail.test.ts b/packages/ui-components/src/__tests__/OrderDetail.test.ts index 81c24a55f6..43ca0f7454 100644 --- a/packages/ui-components/src/__tests__/OrderDetail.test.ts +++ b/packages/ui-components/src/__tests__/OrderDetail.test.ts @@ -4,7 +4,7 @@ import { RaindexOrder, RaindexTransaction, RaindexVault -} from '@rainlanguage/orderbook'; +} from '@rainlanguage/raindex'; import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { QueryClient } from '@tanstack/svelte-query'; import OrderDetail from '../lib/components/detail/OrderDetail.svelte'; @@ -28,7 +28,7 @@ vi.mock('$lib/providers/wallet/useAccount', () => ({ })); // Mock the js_api functions -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ RaindexClient: vi.fn() })); @@ -55,12 +55,12 @@ vi.mock('$lib/components/CodeMirrorRainlang.svelte', async () => { vi.mock('$lib/services/getExplorerLink', () => ({ getExplorerLink: vi.fn() })); -const orderbookAddress = '0x123456789012345678901234567890123456abcd'; +const raindexAddress = '0x123456789012345678901234567890123456abcd'; const orderHash = '0x0234'; const defaultProps: ComponentProps = { chainId: 1, - orderbookAddress, + raindexAddress, orderHash, codeMirrorTheme: readable('dark'), lightweightChartsTheme: readable(darkChartTheme), @@ -77,7 +77,7 @@ const mockVaultsList = () => ({ const mockOrder: RaindexOrder = { chainId: 1, - orderbook: orderbookAddress, + raindex: raindexAddress, id: 'mockId', orderBytes: '0x0000000000000000000000000000000000000000...', orderHash: orderHash, @@ -108,7 +108,7 @@ const mockOrder: RaindexOrder = { owner: '0x1234567890123456789012345678901234567890', ordersAsOutput: [], ordersAsInput: [], - orderbook: orderbookAddress + raindex: raindexAddress } as unknown as RaindexVault, { chainId: 1, @@ -126,7 +126,7 @@ const mockOrder: RaindexOrder = { owner: '0x1234567890123456789012345678901234567890', ordersAsOutput: [], ordersAsInput: [], - orderbook: orderbookAddress + raindex: raindexAddress } as unknown as RaindexVault ] }, @@ -181,7 +181,7 @@ describe('OrderDetail', () => { context: new Map([['$$_queryClient', queryClient]]) }); - expect(mockRaindexClient.getOrderByHash).toHaveBeenCalledWith(1, orderbookAddress, orderHash); + expect(mockRaindexClient.getOrderByHash).toHaveBeenCalledWith(1, raindexAddress, orderHash); }); it('shows the correct empty message when the query returns no data', async () => { @@ -205,10 +205,10 @@ describe('OrderDetail', () => { await waitFor(() => { expect(screen.getByText('Order')).toBeInTheDocument(); - expect(screen.getByText('Orderbook')).toBeInTheDocument(); + expect(screen.getByText('Raindex')).toBeInTheDocument(); expect(screen.getByText('Owner')).toBeInTheDocument(); expect(screen.getByText('Created')).toBeInTheDocument(); - expect(screen.getByText(orderbookAddress)).toBeInTheDocument(); + expect(screen.getByText(raindexAddress)).toBeInTheDocument(); expect(screen.getByText('0x1234567890123456789012345678901234567890')).toBeInTheDocument(); }); }); @@ -313,7 +313,7 @@ describe('OrderDetail', () => { await waitFor(() => { expect(screen.getByText('Order')).toBeInTheDocument(); - expect(screen.getByText('Orderbook')).toBeInTheDocument(); + expect(screen.getByText('Raindex')).toBeInTheDocument(); expect(screen.getByText('Owner')).toBeInTheDocument(); @@ -341,7 +341,7 @@ describe('OrderDetail', () => { await waitFor(() => { expect(screen.getByText('Order')).toBeInTheDocument(); - expect(screen.getByText('Orderbook')).toBeInTheDocument(); + expect(screen.getByText('Raindex')).toBeInTheDocument(); expect(screen.getByText('Owner')).toBeInTheDocument(); expect(screen.getByText('Created')).toBeInTheDocument(); }); diff --git a/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts b/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts index babfcb56ef..94dddbefc7 100644 --- a/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts +++ b/packages/ui-components/src/__tests__/OrderOrVaultHash.test.ts @@ -1,7 +1,7 @@ import { render } from '@testing-library/svelte'; import { describe, it, expect, vi } from 'vitest'; import OrderOrVaultHash from '../lib/components/OrderOrVaultHash.svelte'; -import type { RaindexOrder, RaindexVault } from '@rainlanguage/orderbook'; +import type { RaindexOrder, RaindexVault } from '@rainlanguage/raindex'; vi.mock('$app/navigation', () => ({ goto: vi.fn() @@ -30,7 +30,7 @@ describe('OrderOrVaultHash', () => { type: 'orders', orderOrVault: mockOrder, chainId: 1, - orderbookAddress: '0x234567' + raindexAddress: '0x234567' } }); @@ -53,7 +53,7 @@ describe('OrderOrVaultHash', () => { type: 'orders', orderOrVault: mockInactiveOrder, chainId: 1, - orderbookAddress: '0x234567' + raindexAddress: '0x234567' } }); @@ -69,7 +69,7 @@ describe('OrderOrVaultHash', () => { type: 'vaults', orderOrVault: mockVault, chainId: 1, - orderbookAddress: '0x234567' + raindexAddress: '0x234567' } }); @@ -89,7 +89,7 @@ describe('OrderOrVaultHash', () => { type: 'orders', orderOrVault: mockOrder as unknown as RaindexOrder, chainId: 1, - orderbookAddress: '0x234567' + raindexAddress: '0x234567' } }); @@ -102,7 +102,7 @@ describe('OrderOrVaultHash', () => { type: 'orders', orderOrVault: mockInactiveOrder as unknown as RaindexOrder, chainId: 1, - orderbookAddress: '0x234567' + raindexAddress: '0x234567' } }); diff --git a/packages/ui-components/src/__tests__/OrderPage.test.ts b/packages/ui-components/src/__tests__/OrderPage.test.ts index f371cbe051..c20a79a5d7 100644 --- a/packages/ui-components/src/__tests__/OrderPage.test.ts +++ b/packages/ui-components/src/__tests__/OrderPage.test.ts @@ -1,6 +1,6 @@ import { render, screen, waitFor } from '@testing-library/svelte'; import OrderPage from '../lib/components/deployment/OrderPage.svelte'; -import type { NameAndDescriptionCfg } from '@rainlanguage/orderbook'; +import type { NameAndDescriptionCfg } from '@rainlanguage/raindex'; import { vi, describe, it, expect, beforeEach } from 'vitest'; // Mock fetch diff --git a/packages/ui-components/src/__tests__/OrderTradesListTable.test.ts b/packages/ui-components/src/__tests__/OrderTradesListTable.test.ts index 96c224e8dd..8d79c85987 100644 --- a/packages/ui-components/src/__tests__/OrderTradesListTable.test.ts +++ b/packages/ui-components/src/__tests__/OrderTradesListTable.test.ts @@ -1,7 +1,7 @@ import { render, screen, waitFor } from '@testing-library/svelte'; import { test, vi, type Mock } from 'vitest'; import { expect } from '../lib/test/matchers'; -import type { RaindexOrder, RaindexTrade } from '@rainlanguage/orderbook'; +import type { RaindexOrder, RaindexTrade } from '@rainlanguage/raindex'; import OrderTradesListTable from '../lib/components/tables/OrderTradesListTable.svelte'; import { QueryClient } from '@tanstack/svelte-query'; @@ -39,7 +39,7 @@ const mockTradeOrdersList: RaindexTrade[] = [ timestamp: BigInt(1632000000), blockNumber: BigInt(0) }, - orderbook: '0x1' + raindex: '0x1' }, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -66,9 +66,9 @@ const mockTradeOrdersList: RaindexTrade[] = [ timestamp: BigInt(1632000000), blockNumber: BigInt(0) }, - orderbook: '0x1' + raindex: '0x1' }, - orderbook: '0x00' + raindex: '0x00' }, { id: '2', @@ -103,7 +103,7 @@ const mockTradeOrdersList: RaindexTrade[] = [ timestamp: BigInt(1632000000), blockNumber: BigInt(0) }, - orderbook: '0x1' + raindex: '0x1' }, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -130,9 +130,9 @@ const mockTradeOrdersList: RaindexTrade[] = [ timestamp: BigInt(1632000000), blockNumber: BigInt(0) }, - orderbook: '0x1' + raindex: '0x1' }, - orderbook: '0x00' + raindex: '0x00' } ] as unknown as RaindexTrade[]; @@ -359,7 +359,7 @@ const createMockTrade = (id: string, inputAmount: string, outputAmount: string): timestamp: BigInt(1632000000), blockNumber: BigInt(0) }, - orderbook: '0x1' + raindex: '0x1' }, orderHash: 'orderHash', inputVaultBalanceChange: { @@ -386,9 +386,9 @@ const createMockTrade = (id: string, inputAmount: string, outputAmount: string): timestamp: BigInt(1632000000), blockNumber: BigInt(0) }, - orderbook: '0x1' + raindex: '0x1' }, - orderbook: '0x00' + raindex: '0x00' }) as unknown as RaindexTrade; test('displays dash when output amount is zero (prevents division by zero)', async () => { diff --git a/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts b/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts index 79458c5919..def3963f69 100644 --- a/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts +++ b/packages/ui-components/src/__tests__/OrderVaultsVolTable.test.ts @@ -1,7 +1,7 @@ import { render, screen, waitFor } from '@testing-library/svelte'; import { test, vi } from 'vitest'; import { expect } from '$lib/test/matchers'; -import type { RaindexOrder, RaindexVaultVolume } from '@rainlanguage/orderbook'; +import type { RaindexOrder, RaindexVaultVolume } from '@rainlanguage/raindex'; import OrderVaultsVolTable from '../lib/components/tables/OrderVaultsVolTable.svelte'; import { QueryClient } from '@tanstack/svelte-query'; diff --git a/packages/ui-components/src/__tests__/OrdersListTable.test.ts b/packages/ui-components/src/__tests__/OrdersListTable.test.ts index 0bc00b39f5..4c1df2023f 100644 --- a/packages/ui-components/src/__tests__/OrdersListTable.test.ts +++ b/packages/ui-components/src/__tests__/OrdersListTable.test.ts @@ -3,12 +3,12 @@ import { render, screen, waitFor } from '@testing-library/svelte'; import { describe, it, expect, vi, type Mock } from 'vitest'; import userEvent from '@testing-library/user-event'; import OrdersListTable from '../lib/components/tables/OrdersListTable.svelte'; -import { RaindexOrder } from '@rainlanguage/orderbook'; +import { RaindexOrder } from '@rainlanguage/raindex'; import type { ComponentProps } from 'svelte'; import { readable } from 'svelte/store'; import { useAccount } from '$lib/providers/wallet/useAccount'; -vi.mock('../lib/components/ListViewOrderbookFilters.svelte', async () => { +vi.mock('../lib/components/ListViewRaindexFilters.svelte', async () => { const MockComponent = (await import('../lib/__mocks__/MockComponent.svelte')).default; return { default: MockComponent @@ -80,7 +80,7 @@ const mockOrder = { }, inputsOutputsList: mockVaultsList(), vaultsList: mockVaultsList(), - orderbook: '0x2222222222222222222222222222222222222222', + raindex: '0x2222222222222222222222222222222222222222', active: true, timestampAdded: BigInt(1678901234), meta: '', @@ -98,7 +98,7 @@ const { mockShowInactiveOrdersStore, mockSelectedChainIdsStore, mockActiveTokensStore, - mockActiveOrderbookAddressesStore, + mockActiveRaindexAddressesStore, mockOwnerFilterStore } = await vi.hoisted(() => import('../lib/__mocks__/stores')); @@ -111,13 +111,13 @@ const defaultProps: OrdersListTableProps = { hideInactiveOrdersVaults: mockHideInactiveOrdersVaultsStore, selectedChainIds: mockSelectedChainIdsStore, activeTokens: mockActiveTokensStore, - activeOrderbookAddresses: mockActiveOrderbookAddressesStore, + activeRaindexAddresses: mockActiveRaindexAddressesStore, ownerFilter: mockOwnerFilterStore } as unknown as OrdersListTableProps; const mockGetOrders = vi.fn(); const mockGetTokens = vi.fn(); -const mockGetAllOrderbooks = vi.fn(); +const mockGetAllRaindexes = vi.fn(); describe('OrdersListTable', () => { beforeEach(() => { @@ -129,12 +129,12 @@ describe('OrdersListTable', () => { (useRaindexClient as Mock).mockReturnValue({ getOrders: mockGetOrders, getTokens: mockGetTokens, - getAllOrderbooks: mockGetAllOrderbooks.mockReturnValue({ + getAllRaindexes: mockGetAllRaindexes.mockReturnValue({ value: new Map([ [ - 'orderbook1', + 'raindex1', { - key: 'orderbook1', + key: 'raindex1', address: '0x1111111111111111111111111111111111111111', network: { chainId: 1 } } @@ -172,7 +172,7 @@ describe('OrdersListTable', () => { expect(addressesCell).toBeInTheDocument(); expect(addressesCell).toHaveTextContent('Order:'); expect(addressesCell).toHaveTextContent('Owner:'); - expect(addressesCell).toHaveTextContent('Orderbook:'); + expect(addressesCell).toHaveTextContent('Raindex:'); // Check that vault cards are rendered with correct content const vaultCards = screen.getAllByTestId('vault-card'); @@ -458,7 +458,7 @@ describe('OrdersListTable', () => { if (appTable) { appTable.dispatchEvent(event); expect(gotoMock.goto).toHaveBeenCalledWith( - `/orders/${mockOrder.chainId}-${mockOrder.orderbook}-${mockOrder.orderHash}` + `/orders/${mockOrder.chainId}-${mockOrder.raindex}-${mockOrder.orderHash}` ); } }); @@ -568,10 +568,10 @@ describe('OrdersListTable', () => { expect(handleTakeOrderModal).toHaveBeenCalledWith(mockOrder, mockRefetch, new Map()); }); - it('passes orderbookAddresses filter to getOrders when orderbooks are selected', async () => { - const orderbookAddress = '0x1111111111111111111111111111111111111111'; + it('passes raindexAddresses filter to getOrders when raindexes are selected', async () => { + const raindexAddress = '0x1111111111111111111111111111111111111111'; - mockActiveOrderbookAddressesStore.mockSetSubscribeValue([orderbookAddress]); + mockActiveRaindexAddressesStore.mockSetSubscribeValue([raindexAddress]); const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -598,15 +598,15 @@ describe('OrdersListTable', () => { expect(mockGetOrders).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ - orderbookAddresses: [orderbookAddress] + raindexAddresses: [raindexAddress] }), expect.anything() ); }); }); - it('does not pass orderbookAddresses filter when no orderbooks are selected', async () => { - mockActiveOrderbookAddressesStore.mockSetSubscribeValue([]); + it('does not pass raindexAddresses filter when no raindexes are selected', async () => { + mockActiveRaindexAddressesStore.mockSetSubscribeValue([]); const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -633,7 +633,7 @@ describe('OrdersListTable', () => { expect(mockGetOrders).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ - orderbookAddresses: undefined + raindexAddresses: undefined }), expect.anything() ); diff --git a/packages/ui-components/src/__tests__/SelectToken.test.ts b/packages/ui-components/src/__tests__/SelectToken.test.ts index b705f66c11..fd3d394720 100644 --- a/packages/ui-components/src/__tests__/SelectToken.test.ts +++ b/packages/ui-components/src/__tests__/SelectToken.test.ts @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event'; import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import SelectToken from '../lib/components/deployment/SelectToken.svelte'; import type { ComponentProps } from 'svelte'; -import { Float, type AccountBalance, type DotrainOrderGui } from '@rainlanguage/orderbook'; +import { Float, type AccountBalance, type DotrainOrderGui } from '@rainlanguage/raindex'; import { useGui } from '$lib/hooks/useGui'; import type { TokenBalance } from '$lib/types/tokenBalance'; @@ -41,7 +41,7 @@ const mockGui: DotrainOrderGui = { }) } as unknown as DotrainOrderGui; -vi.mock('@rainlanguage/orderbook', async (importOriginal) => { +vi.mock('@rainlanguage/raindex', async (importOriginal) => { return { ...(await importOriginal()) }; diff --git a/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts b/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts index ca4ed36265..897c2d214f 100644 --- a/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts +++ b/packages/ui-components/src/__tests__/TanstackOrderQuote.test.ts @@ -3,12 +3,12 @@ import { describe, it, vi, type Mock } from 'vitest'; import { QueryClient } from '@tanstack/svelte-query'; import TanstackOrderQuote from '../lib/components/detail/TanstackOrderQuote.svelte'; import { expect } from '../lib/test/matchers'; -import type { RaindexOrder } from '@rainlanguage/orderbook'; +import type { RaindexOrder } from '@rainlanguage/raindex'; import { useToasts } from '$lib/providers/toasts/useToasts'; import { writable } from 'svelte/store'; import { invalidateTanstackQueries } from '$lib/queries/queryClient'; -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ getOrderQuote: vi.fn() })); diff --git a/packages/ui-components/src/__tests__/TokenBalance.test.ts b/packages/ui-components/src/__tests__/TokenBalance.test.ts index f1dfdaa4f2..29e7c49d62 100644 --- a/packages/ui-components/src/__tests__/TokenBalance.test.ts +++ b/packages/ui-components/src/__tests__/TokenBalance.test.ts @@ -3,11 +3,11 @@ import { describe, it, expect } from 'vitest'; import TokenBalance from '../lib/components/deployment/TokenBalance.svelte'; import type { ComponentProps } from 'svelte'; import type { TokenBalance as TokenBalanceType } from '$lib/types/tokenBalance'; -import { Float, type AccountBalance } from '@rainlanguage/orderbook'; +import { Float, type AccountBalance } from '@rainlanguage/raindex'; type TokenBalanceComponentProps = ComponentProps; -vi.mock('@rainlanguage/orderbook', async (importOriginal) => { +vi.mock('@rainlanguage/raindex', async (importOriginal) => { return { ...(await importOriginal()) }; diff --git a/packages/ui-components/src/__tests__/TokenIOInput.test.ts b/packages/ui-components/src/__tests__/TokenIOInput.test.ts index dc5bf18167..f4e4d2b5b4 100644 --- a/packages/ui-components/src/__tests__/TokenIOInput.test.ts +++ b/packages/ui-components/src/__tests__/TokenIOInput.test.ts @@ -2,11 +2,11 @@ import { render, fireEvent, waitFor } from '@testing-library/svelte'; import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import TokenIOInput from '../lib/components/deployment/TokenIOInput.svelte'; import type { ComponentProps } from 'svelte'; -import { AccountBalance, DotrainOrderGui, Float } from '@rainlanguage/orderbook'; +import { AccountBalance, DotrainOrderGui, Float } from '@rainlanguage/raindex'; import { useGui } from '$lib/hooks/useGui'; import type { TokenBalance } from '$lib/types/tokenBalance'; -vi.mock('@rainlanguage/orderbook', async (importOriginal) => { +vi.mock('@rainlanguage/raindex', async (importOriginal) => { return { ...(await importOriginal()), DotrainOrderGui: vi.fn() diff --git a/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts b/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts index ee7b51ef42..2cd104cf9d 100644 --- a/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts +++ b/packages/ui-components/src/__tests__/TokenSelectionModal.test.ts @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event'; import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import TokenSelectionModal from '../lib/components/deployment/TokenSelectionModal.svelte'; import type { ComponentProps } from 'svelte'; -import type { ExtendedTokenInfo, DotrainOrderGui } from '@rainlanguage/orderbook'; +import type { ExtendedTokenInfo, DotrainOrderGui } from '@rainlanguage/raindex'; import { useGui } from '$lib/hooks/useGui'; type TokenSelectionModalProps = ComponentProps; diff --git a/packages/ui-components/src/__tests__/Transaction.test.ts b/packages/ui-components/src/__tests__/Transaction.test.ts index 4e252e6f0a..3773d0961d 100644 --- a/packages/ui-components/src/__tests__/Transaction.test.ts +++ b/packages/ui-components/src/__tests__/Transaction.test.ts @@ -12,7 +12,7 @@ import { waitForTransactionReceipt, type Config } from '@wagmi/core'; import { get } from 'svelte/store'; import type { Chain } from 'viem'; import type { ToastLink } from '../lib/types/toast'; -import type { SgVault } from '@rainlanguage/orderbook'; +import type { SgVault } from '@rainlanguage/raindex'; vi.mock('@wagmi/core', () => ({ waitForTransactionReceipt: vi.fn() @@ -72,7 +72,7 @@ describe('TransactionStore', () => { ordersAsOutput: [], balanceChanges: [], balance: '1000000000000000000', - orderbook: { + raindex: { id: '0x00' } }; @@ -296,7 +296,7 @@ describe('TransactionStore', () => { ctx.updateState({ status: TransactionStatusMessage.SUCCESS }); // Add a "View order" link const newLink = { - link: `/orders/1-0xorderbook-${newOrderHash}`, + link: `/orders/1-0xraindex-${newOrderHash}`, label: 'View order' }; ctx.updateState({ links: [newLink, ...ctx.links] }); @@ -325,7 +325,7 @@ describe('TransactionStore', () => { expect(state.status).toBe(TransactionStatusMessage.SUCCESS); expect(state.links).toHaveLength(2); expect(state.links[0]).toEqual({ - link: `/orders/1-0xorderbook-${newOrderHash}`, + link: `/orders/1-0xraindex-${newOrderHash}`, label: 'View order' }); expect(mockOnSuccess).toHaveBeenCalled(); diff --git a/packages/ui-components/src/__tests__/TransactionManager.test.ts b/packages/ui-components/src/__tests__/TransactionManager.test.ts index 3939c8eb77..39253521de 100644 --- a/packages/ui-components/src/__tests__/TransactionManager.test.ts +++ b/packages/ui-components/src/__tests__/TransactionManager.test.ts @@ -22,7 +22,7 @@ import { RaindexVault, type Address, type WasmEncodedResult -} from '@rainlanguage/orderbook'; +} from '@rainlanguage/raindex'; vi.mock('../lib/models/Transaction', () => ({ TransactionStore: vi.fn() @@ -32,7 +32,7 @@ vi.mock('../lib/services/getExplorerLink', () => ({ getExplorerLink: vi.fn() })); -vi.mock('@rainlanguage/orderbook', async (importOriginal) => ({ +vi.mock('@rainlanguage/raindex', async (importOriginal) => ({ ...(await importOriginal()), getTransactionRemoveOrders: vi.fn(), getTransaction: vi.fn(), @@ -53,7 +53,7 @@ describe('TransactionManager', () => { const mockSgOrderEntity = { id: 'mockOrderEntityId', - orderbook: 'mockOrderbook', + raindex: 'mockRaindex', getRemoveOrdersForTransaction: vi.fn() } as unknown as RaindexOrder; @@ -246,7 +246,7 @@ describe('TransactionManager', () => { // Verify the SDK method was called with correct arguments expect(mockRaindexClient.getRemoveOrdersForTransaction).toHaveBeenCalledWith( removeOrderMockArgs.chainId, - mockSgOrderEntity.orderbook, + mockSgOrderEntity.raindex, removeOrderMockArgs.txHash ); @@ -325,7 +325,7 @@ describe('TransactionManager', () => { queryKey: withdrawMockArgs.queryKey, toastLinks: [ { - link: `/vaults/${withdrawMockArgs.chainId}-${withdrawMockArgs.entity.orderbook}-${withdrawMockArgs.queryKey}`, + link: `/vaults/${withdrawMockArgs.chainId}-${withdrawMockArgs.entity.raindex}-${withdrawMockArgs.queryKey}`, label: 'View vault' }, { @@ -448,10 +448,10 @@ describe('TransactionManager', () => { await callArgs.awaitIndexingFn!(mockContext); - // Verify the SDK method was called with correct arguments (chainId, orderbook, txHash) + // Verify the SDK method was called with correct arguments (chainId, raindex, txHash) expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( withdrawMockArgs.chainId, - withdrawMockArgs.entity.orderbook, + withdrawMockArgs.entity.raindex, withdrawMockArgs.txHash ); @@ -571,7 +571,7 @@ describe('TransactionManager', () => { queryKey: mockArgs.queryKey, toastLinks: [ { - link: `/vaults/${mockArgs.chainId}-${mockEntity.orderbook}-${mockArgs.queryKey}`, + link: `/vaults/${mockArgs.chainId}-${mockEntity.raindex}-${mockArgs.queryKey}`, label: 'View vault' }, { @@ -716,7 +716,7 @@ describe('TransactionManager', () => { queryKey: mockArgs.queryKey, toastLinks: [ { - link: `/vaults/${mockArgs.chainId}-${mockEntity.orderbook}-${mockArgs.queryKey}`, + link: `/vaults/${mockArgs.chainId}-${mockEntity.raindex}-${mockArgs.queryKey}`, label: 'View vault' }, { @@ -831,10 +831,10 @@ describe('TransactionManager', () => { await callArgs.awaitIndexingFn!(mockContext); - // Verify the SDK method was called with correct arguments (chainId, orderbook, txHash) + // Verify the SDK method was called with correct arguments (chainId, raindex, txHash) expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( mockArgs.chainId, - mockArgs.entity.orderbook, + mockArgs.entity.raindex, mockArgs.txHash ); @@ -882,13 +882,13 @@ describe('TransactionManager', () => { describe('createAddOrderTransaction', () => { const addOrderMockArgs: InternalTransactionArgs & { raindexClient: RaindexClient; - orderbook: Address; + raindex: Address; } = { txHash: '0xaddordertxhash' as `0x${string}`, chainId: 1, queryKey: 'myNewStrategyDeployment', raindexClient: mockRaindexClient, - orderbook: '0xorderbook' as Address + raindex: '0xraindex' as Address }; beforeEach(() => { @@ -1095,7 +1095,7 @@ describe('TransactionManager', () => { expect(mockRaindexClient.getTransaction).toHaveBeenCalledWith( takeOrderMockArgs.chainId, - takeOrderMockArgs.entity.orderbook, + takeOrderMockArgs.entity.raindex, takeOrderMockArgs.txHash ); diff --git a/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts b/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts index f556e09d36..66cb719400 100644 --- a/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts +++ b/packages/ui-components/src/__tests__/VaultBalanceChangesTable.test.ts @@ -7,7 +7,7 @@ import type { RaindexVault, RaindexVaultBalanceChange, RaindexVaultBalanceChangeType -} from '@rainlanguage/orderbook'; +} from '@rainlanguage/raindex'; import { formatTimestampSecondsAsLocal } from '../lib/services/time'; import { VAULT_BALANCE_CHANGE_LABELS } from '../lib/utils/vaultBalanceChangeLabels'; @@ -48,7 +48,7 @@ const createMockVaultBalanceChange = ( timestamp: BigInt(1625247600), blockNumber: BigInt(1234567890) }, - orderbook: '0x00', + raindex: '0x00', ...overrides } as unknown as RaindexVaultBalanceChange; }; diff --git a/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts b/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts index d8040c54e0..56c44755dc 100644 --- a/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts +++ b/packages/ui-components/src/__tests__/VaultBalanceChart.test.ts @@ -4,7 +4,7 @@ import { test } from 'vitest'; // import { expect, test, vi } from 'vitest'; // import { QueryClient } from '@tanstack/svelte-query'; // import VaultBalanceChart from '../lib/components/charts/VaultBalanceChart.svelte'; -// import type { RaindexVault } from '@rainlanguage/orderbook'; +// import type { RaindexVault } from '@rainlanguage/raindex'; // import { writable } from 'svelte/store'; // import type { ComponentProps } from 'svelte'; diff --git a/packages/ui-components/src/__tests__/VaultCard.test.ts b/packages/ui-components/src/__tests__/VaultCard.test.ts index af8dfad26f..5db4fd65ad 100644 --- a/packages/ui-components/src/__tests__/VaultCard.test.ts +++ b/packages/ui-components/src/__tests__/VaultCard.test.ts @@ -1,7 +1,7 @@ import { render, screen } from '@testing-library/svelte'; import { describe, it, expect, vi } from 'vitest'; import VaultCard from '../lib/components/VaultCard.svelte'; -import type { RaindexVault } from '@rainlanguage/orderbook'; +import type { RaindexVault } from '@rainlanguage/raindex'; import userEvent from '@testing-library/user-event'; // Mock the navigation @@ -12,7 +12,7 @@ vi.mock('$app/navigation', () => ({ const mockVault: RaindexVault = { id: '0x1234567890abcdef1234567890abcdef12345678', chainId: 1, - orderbook: '0x2222222222222222222222222222222222222222', + raindex: '0x2222222222222222222222222222222222222222', token: { symbol: 'ETH', name: 'Ethereum', diff --git a/packages/ui-components/src/__tests__/VaultDetail.test.ts b/packages/ui-components/src/__tests__/VaultDetail.test.ts index 6d76742743..7c29847643 100644 --- a/packages/ui-components/src/__tests__/VaultDetail.test.ts +++ b/packages/ui-components/src/__tests__/VaultDetail.test.ts @@ -7,7 +7,7 @@ import { darkChartTheme } from '../lib/utils/lightweightChartsThemes'; import userEvent from '@testing-library/user-event'; import type { ComponentProps } from 'svelte'; import { useRaindexClient } from '$lib/hooks/useRaindexClient'; -import { RaindexClient, RaindexVault, type RaindexOrderAsIO } from '@rainlanguage/orderbook'; +import { RaindexClient, RaindexVault, type RaindexOrderAsIO } from '@rainlanguage/raindex'; import { useAccount } from '../lib/providers/wallet/useAccount'; import { QKEY_VAULT } from '$lib/queries/keys'; import { useToasts } from '../lib/providers/toasts/useToasts'; @@ -24,7 +24,7 @@ vi.mock('$lib/hooks/useRaindexClient', () => ({ useRaindexClient: vi.fn() })); -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ RaindexClient: vi.fn() })); @@ -53,7 +53,7 @@ const mockErrToast = vi.fn(); const defaultProps: VaultDetailProps = { chainId: 1, - orderbookAddress: '0x00', + raindexAddress: '0x00', id: '100', lightweightChartsTheme: readable(darkChartTheme), onDeposit: vi.fn(), @@ -108,7 +108,7 @@ describe('VaultDetail', () => { formattedBalance: '100000', ordersAsInput: [], ordersAsOutput: [], - orderbook: '0x00' + raindex: '0x00' } as unknown as RaindexVault; (mockRaindexClient.getVault as Mock).mockResolvedValue({ value: mockData }); }); diff --git a/packages/ui-components/src/__tests__/VaultIdInformation.test.ts b/packages/ui-components/src/__tests__/VaultIdInformation.test.ts index 2360c26aa6..36f8d4b55b 100644 --- a/packages/ui-components/src/__tests__/VaultIdInformation.test.ts +++ b/packages/ui-components/src/__tests__/VaultIdInformation.test.ts @@ -2,11 +2,11 @@ import { render, screen } from '@testing-library/svelte'; import { describe, it, expect } from 'vitest'; import type { ComponentProps } from 'svelte'; import VaultIdInformation from '$lib/components/deployment/VaultIdInformation.svelte'; -import { Float, type AccountBalance } from '@rainlanguage/orderbook'; +import { Float, type AccountBalance } from '@rainlanguage/raindex'; export type VaultIdInformationComponentProps = ComponentProps; -vi.mock('@rainlanguage/orderbook', async (importOriginal) => { +vi.mock('@rainlanguage/raindex', async (importOriginal) => { return { ...(await importOriginal()) }; diff --git a/packages/ui-components/src/__tests__/VaultsListTable.test.ts b/packages/ui-components/src/__tests__/VaultsListTable.test.ts index 5fcc538ef5..b68ee2386e 100644 --- a/packages/ui-components/src/__tests__/VaultsListTable.test.ts +++ b/packages/ui-components/src/__tests__/VaultsListTable.test.ts @@ -3,7 +3,7 @@ import { render, screen, waitFor } from '@testing-library/svelte'; import { describe, it, expect, vi, type Mock, beforeEach } from 'vitest'; import VaultsListTable from '../lib/components/tables/VaultsListTable.svelte'; import { readable } from 'svelte/store'; -import { Float, type RaindexVault, type RaindexVaultsList } from '@rainlanguage/orderbook'; +import { Float, type RaindexVault, type RaindexVaultsList } from '@rainlanguage/raindex'; import type { ComponentProps } from 'svelte'; import userEvent from '@testing-library/user-event'; import { useAccount } from '$lib/providers/wallet/useAccount'; @@ -42,7 +42,7 @@ const mockVault = { symbol: 'MTK', decimals: '18' }, - orderbook: '0x2222222222222222222222222222222222222222', + raindex: '0x2222222222222222222222222222222222222222', ordersAsInput: [], ordersAsOutput: [] } as unknown as RaindexVault; @@ -56,7 +56,7 @@ vi.mock('@tanstack/svelte-query'); // Hoisted mock stores const { mockActiveNetworkRefStore, - mockActiveOrderbookRefStore, + mockActiveRaindexRefStore, mockHideZeroBalanceVaultsStore, mockHideInactiveOrdersVaultsStore, mockOrderHashStore, @@ -64,7 +64,7 @@ const { mockActiveAccountsStore, mockSelectedChainIdsStore, mockActiveTokensStore, - mockActiveOrderbookAddressesStore, + mockActiveRaindexAddressesStore, mockOwnerFilterStore } = await vi.hoisted(() => import('../lib/__mocks__/stores')); @@ -74,11 +74,11 @@ const defaultProps = { hideZeroBalanceVaults: mockHideZeroBalanceVaultsStore, hideInactiveOrdersVaults: mockHideInactiveOrdersVaultsStore, activeNetworkRef: mockActiveNetworkRefStore, - activeOrderbookRef: mockActiveOrderbookRefStore, + activeRaindexRef: mockActiveRaindexRefStore, activeAccounts: mockActiveAccountsStore, selectedChainIds: mockSelectedChainIdsStore, activeTokens: mockActiveTokensStore, - activeOrderbookAddresses: mockActiveOrderbookAddressesStore, + activeRaindexAddresses: mockActiveRaindexAddressesStore, ownerFilter: mockOwnerFilterStore }; @@ -112,12 +112,12 @@ describe('VaultsListTable', () => { value: new Map(), error: undefined })), - getAllOrderbooks: vi.fn(() => ({ + getAllRaindexes: vi.fn(() => ({ value: new Map([ [ - 'orderbook1', + 'raindex1', { - key: 'orderbook1', + key: 'raindex1', address: '0x1111111111111111111111111111111111111111', network: { chainId: 1 } } @@ -149,7 +149,7 @@ describe('VaultsListTable', () => { const addressesCell = screen.getByTestId('vaultAddresses'); expect(addressesCell).toBeInTheDocument(); expect(addressesCell).toHaveTextContent('Vault:'); - expect(addressesCell).toHaveTextContent('Orderbook:'); + expect(addressesCell).toHaveTextContent('Raindex:'); expect(addressesCell).toHaveTextContent('Owner:'); // Token column now contains both token name and balance @@ -447,10 +447,10 @@ describe('VaultsListTable', () => { expect(withdrawButton).toBeDisabled(); }); - it('passes orderbookAddresses filter to getVaults when orderbooks are selected', async () => { - const orderbookAddress = '0x1111111111111111111111111111111111111111'; + it('passes raindexAddresses filter to getVaults when raindexes are selected', async () => { + const raindexAddress = '0x1111111111111111111111111111111111111111'; - mockActiveOrderbookAddressesStore.mockSetSubscribeValue([orderbookAddress]); + mockActiveRaindexAddressesStore.mockSetSubscribeValue([raindexAddress]); const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); mockQuery.createInfiniteQuery = vi.fn((options: any) => { @@ -476,15 +476,15 @@ describe('VaultsListTable', () => { expect(mockGetVaults).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ - orderbookAddresses: [orderbookAddress] + raindexAddresses: [raindexAddress] }), expect.anything() ); }); }); - it('does not pass orderbookAddresses filter when no orderbooks are selected', async () => { - mockActiveOrderbookAddressesStore.mockSetSubscribeValue([]); + it('does not pass raindexAddresses filter when no raindexes are selected', async () => { + mockActiveRaindexAddressesStore.mockSetSubscribeValue([]); const mockQuery = vi.mocked(await import('@tanstack/svelte-query')); mockQuery.createInfiniteQuery = vi.fn((options: any) => { @@ -510,7 +510,7 @@ describe('VaultsListTable', () => { expect(mockGetVaults).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ - orderbookAddresses: undefined + raindexAddresses: undefined }), expect.anything() ); diff --git a/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts b/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts index e07b467002..2c336b2b83 100644 --- a/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts +++ b/packages/ui-components/src/__tests__/awaitTransactionIndexing.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import type { RaindexOrder, RaindexTransaction } from '@rainlanguage/orderbook'; +import type { RaindexOrder, RaindexTransaction } from '@rainlanguage/raindex'; import { awaitSubgraphIndexing } from '$lib/services/awaitTransactionIndexing'; import { TransactionStoreErrorMessage } from '$lib/types/transaction'; @@ -22,7 +22,7 @@ describe('subgraphIndexing', () => { const resultPromise = awaitSubgraphIndexing({ chainId: 1, - orderbook: '0x123', + raindex: '0x123', txHash: '0x0234', successMessage: 'Transaction confirmed', fetchEntityFn: mockFetchData, @@ -54,7 +54,7 @@ describe('subgraphIndexing', () => { const resultPromise = awaitSubgraphIndexing({ chainId: 1, - orderbook: '0x123', + raindex: '0x123', txHash: '0x0234', successMessage: 'Order confirmed', fetchEntityFn: mockFetchData, @@ -74,7 +74,7 @@ describe('subgraphIndexing', () => { const resultPromise = awaitSubgraphIndexing({ chainId: 1, - orderbook: '0x123', + raindex: '0x123', txHash: '0x0234', successMessage: 'Transaction confirmed', maxAttempts: 5, @@ -100,7 +100,7 @@ describe('subgraphIndexing', () => { const resultPromise = awaitSubgraphIndexing({ chainId: 1, - orderbook: '0x123', + raindex: '0x123', txHash: '0x0234', successMessage: 'Transaction confirmed', maxAttempts: 3, @@ -127,7 +127,7 @@ describe('subgraphIndexing', () => { const resultPromise = awaitSubgraphIndexing({ chainId: 1, - orderbook: '0x123', + raindex: '0x123', txHash: '0x0234', successMessage: 'Transaction confirmed', maxAttempts: 5, diff --git a/packages/ui-components/src/__tests__/handleShareChoices.test.ts b/packages/ui-components/src/__tests__/handleShareChoices.test.ts index 0a21ed1080..e43f1254e0 100644 --- a/packages/ui-components/src/__tests__/handleShareChoices.test.ts +++ b/packages/ui-components/src/__tests__/handleShareChoices.test.ts @@ -1,8 +1,8 @@ import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; import { handleShareChoices } from '../lib/services/handleShareChoices'; -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ DotrainOrderGui: vi.fn() })); diff --git a/packages/ui-components/src/__tests__/loadRainlangUrl.test.ts b/packages/ui-components/src/__tests__/loadRainlangUrl.test.ts index deb798ac82..f3ac83afea 100644 --- a/packages/ui-components/src/__tests__/loadRainlangUrl.test.ts +++ b/packages/ui-components/src/__tests__/loadRainlangUrl.test.ts @@ -3,10 +3,10 @@ import type { Mock } from 'vitest'; import { loadRainlangUrl } from '../lib/services/loadRainlangUrl'; import { RainlangManager } from '../lib/providers/rainlang/RainlangManager'; import { initialRainlang } from '../__fixtures__/RainlangManager'; -import { DotrainRainlang } from '@rainlanguage/orderbook'; +import { DotrainRainlang } from '@rainlanguage/raindex'; // Mock dependencies -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ DotrainRainlang: { validate: vi.fn() } diff --git a/packages/ui-components/src/__tests__/pairTradesChartData.test.ts b/packages/ui-components/src/__tests__/pairTradesChartData.test.ts index abf8e9d473..9c1c8da243 100644 --- a/packages/ui-components/src/__tests__/pairTradesChartData.test.ts +++ b/packages/ui-components/src/__tests__/pairTradesChartData.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; -import type { RaindexTrade, RaindexVaultToken } from '@rainlanguage/orderbook'; +import type { RaindexTrade, RaindexVaultToken } from '@rainlanguage/raindex'; import { extractPairsFromTrades, getDefaultPair, @@ -66,7 +66,7 @@ function createMockTrade( blockNumber: BigInt(12345) }, orderHash: '0xorderhash', - orderbook: '0xorderbook' + raindex: '0xraindex' } as unknown as RaindexTrade; } diff --git a/packages/ui-components/src/__tests__/rainlang.test.ts b/packages/ui-components/src/__tests__/rainlang.test.ts index 041298a1ef..96219d559b 100644 --- a/packages/ui-components/src/__tests__/rainlang.test.ts +++ b/packages/ui-components/src/__tests__/rainlang.test.ts @@ -4,11 +4,11 @@ import { fetchRainlangDotrains, validateOrders } from '../lib/services/rainlang'; -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; import type { Mock } from 'vitest'; // Mock the DotrainOrderGui dependency -vi.mock('@rainlanguage/orderbook', () => ({ +vi.mock('@rainlanguage/raindex', () => ({ DotrainOrderGui: { getOrderDetails: vi.fn() } diff --git a/packages/ui-components/src/lib/__fixtures__/settings.yaml b/packages/ui-components/src/lib/__fixtures__/settings.yaml index 5f054e53d7..94faa60f40 100644 --- a/packages/ui-components/src/lib/__fixtures__/settings.yaml +++ b/packages/ui-components/src/lib/__fixtures__/settings.yaml @@ -1,4 +1,4 @@ -version: 2 +version: 6 networks: flare: rpc: https://rpc.ankr.com/flare @@ -56,7 +56,7 @@ metaboards: bsc: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-bsc/0.1/gn linea: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/mb-linea-0xed7d6156/1.0.0/gn ethereum: https://api.goldsky.com/api/public/project_clv14x04y9kzi01saerx7bxpg/subgraphs/metadata-mainnet/2024-10-25-2857/gn -orderbooks: +raindexes: flare: address: 0xCEe8Cd002F151A536394E564b84076c41bBBcD4d network: flare diff --git a/packages/ui-components/src/lib/__mocks__/stores.ts b/packages/ui-components/src/lib/__mocks__/stores.ts index be80da39b7..b910df51b4 100644 --- a/packages/ui-components/src/lib/__mocks__/stores.ts +++ b/packages/ui-components/src/lib/__mocks__/stores.ts @@ -1,5 +1,5 @@ import { writable } from 'svelte/store'; -import type { Address } from '@rainlanguage/orderbook'; +import type { Address } from '@rainlanguage/raindex'; import { type Config } from '@wagmi/core'; import { mockWeb3Config } from './mockWeb3Config'; @@ -18,7 +18,7 @@ type MockPageState = { }; if (import.meta.vitest) { - vi.mock(import('@rainlanguage/orderbook'), async (importOriginal) => { + vi.mock(import('@rainlanguage/raindex'), async (importOriginal) => { const actual = await importOriginal(); return { ...actual @@ -48,7 +48,7 @@ const mockOrderHashWritable = writable(''); const mockHideZeroBalanceVaultsWritable = writable(false); const mockHideInactiveOrdersVaultsWritable = writable(false); const mockActiveNetworkRefWritable = writable(''); -const mockActiveOrderbookRefWritable = writable(''); +const mockActiveRaindexRefWritable = writable(''); const mockActiveAccountsWritable = writable>({}); const mockSubgraphUrlWritable = writable(''); const mockChainIdWritable = writable(0); @@ -56,7 +56,7 @@ const mockConnectedWritable = writable(true); const mockWagmiConfigWritable = writable(mockWeb3Config); const mockSelectedChainIdsWritable = writable([]); const mockActiveTokensWritable = writable([]); -const mockActiveOrderbookAddressesWritable = writable([]); +const mockActiveRaindexAddressesWritable = writable([]); const mockOwnerFilterWritable = writable
('' as Address); export const mockShowInactiveOrdersStore = { @@ -89,10 +89,10 @@ export const mockActiveNetworkRefStore = { mockSetSubscribeValue: (value: string): void => mockActiveNetworkRefWritable.set(value) }; -export const mockActiveOrderbookRefStore = { - subscribe: mockActiveOrderbookRefWritable.subscribe, - set: mockActiveOrderbookRefWritable.set, - mockSetSubscribeValue: (value: string): void => mockActiveOrderbookRefWritable.set(value) +export const mockActiveRaindexRefStore = { + subscribe: mockActiveRaindexRefWritable.subscribe, + set: mockActiveRaindexRefWritable.set, + mockSetSubscribeValue: (value: string): void => mockActiveRaindexRefWritable.set(value) }; export const mockActiveAccountsStore = { @@ -152,10 +152,10 @@ export const mockActiveTokensStore = { mockSetSubscribeValue: (value: string[]): void => mockActiveTokensWritable.set(value) }; -export const mockActiveOrderbookAddressesStore = { - subscribe: mockActiveOrderbookAddressesWritable.subscribe, - set: mockActiveOrderbookAddressesWritable.set, - mockSetSubscribeValue: (value: string[]): void => mockActiveOrderbookAddressesWritable.set(value) +export const mockActiveRaindexAddressesStore = { + subscribe: mockActiveRaindexAddressesWritable.subscribe, + set: mockActiveRaindexAddressesWritable.set, + mockSetSubscribeValue: (value: string[]): void => mockActiveRaindexAddressesWritable.set(value) }; export const mockOwnerFilterStore = { diff --git a/packages/ui-components/src/lib/components/ButtonVaultLink.svelte b/packages/ui-components/src/lib/components/ButtonVaultLink.svelte index bf8aecb943..f9c10f591a 100644 --- a/packages/ui-components/src/lib/components/ButtonVaultLink.svelte +++ b/packages/ui-components/src/lib/components/ButtonVaultLink.svelte @@ -1,11 +1,11 @@
{toHex(tokenVault.vaultId)} {tokenVault.token.name} ({tokenVault.token.symbol}) diff --git a/packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte b/packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte index 5ad7a04c96..e6c846eb8a 100644 --- a/packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte +++ b/packages/ui-components/src/lib/components/CodeMirrorRainlang.svelte @@ -1,5 +1,5 @@ diff --git a/packages/ui-components/src/lib/components/VaultBalanceChangeTypeFilter.svelte b/packages/ui-components/src/lib/components/VaultBalanceChangeTypeFilter.svelte index cd8c9a8a23..27ae1083fb 100644 --- a/packages/ui-components/src/lib/components/VaultBalanceChangeTypeFilter.svelte +++ b/packages/ui-components/src/lib/components/VaultBalanceChangeTypeFilter.svelte @@ -1,5 +1,5 @@ diff --git a/packages/ui-components/src/lib/components/charts/OrderTradesChart.svelte b/packages/ui-components/src/lib/components/charts/OrderTradesChart.svelte index 983beace6a..635fd9d9fc 100644 --- a/packages/ui-components/src/lib/components/charts/OrderTradesChart.svelte +++ b/packages/ui-components/src/lib/components/charts/OrderTradesChart.svelte @@ -1,6 +1,6 @@ - -
- -
- - - - {#if orderbooksError} -
- Cannot load orderbooks list: {orderbooksError.readableMsg || 'Unknown error'} -
- {:else if isEmpty(availableOrderbooks)} -
{emptyMessage}
- {:else} -
- - - -
- - {#if isEmpty(filteredOrderbooks)} -
No orderbooks match your search
- {:else} - {#each sortedFilteredOrderbooks as orderbook, index (`${orderbook.address}-${orderbook.chainId}`)} - toggleOrderbook(orderbook)} - checked={!!( - orderbook.address && - selectedOrderbookAddresses.some( - (addr) => addr.toLowerCase() === orderbook.address.toLowerCase() - ) - )} - > -
-
{getDisplayName(orderbook)}
-
- {getNetworkName(orderbook.chainId)} -
-
-
- {/each} - {/if} - {/if} -
-
-
diff --git a/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte b/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte new file mode 100644 index 0000000000..a601f6568b --- /dev/null +++ b/packages/ui-components/src/lib/components/dropdown/DropdownRaindexesFilter.svelte @@ -0,0 +1,209 @@ + + +
+ +
+ + + + {#if raindexesError} +
+ Cannot load raindexes list: {raindexesError.readableMsg || 'Unknown error'} +
+ {:else if isEmpty(availableRaindexes)} +
{emptyMessage}
+ {:else} +
+ + + +
+ + {#if isEmpty(filteredRaindexes)} +
No raindexes match your search
+ {:else} + {#each sortedFilteredRaindexes as raindex, index (`${raindex.address}-${raindex.chainId}`)} + toggleRaindex(raindex)} + checked={!!( + raindex.address && + selectedRaindexAddresses.some( + (addr) => addr.toLowerCase() === raindex.address.toLowerCase() + ) + )} + > +
+
{getDisplayName(raindex)}
+
+ {getNetworkName(raindex.chainId)} +
+
+
+ {/each} + {/if} + {/if} +
+
+
diff --git a/packages/ui-components/src/lib/components/dropdown/DropdownTokensFilter.svelte b/packages/ui-components/src/lib/components/dropdown/DropdownTokensFilter.svelte index 4c95625618..4977e962bd 100644 --- a/packages/ui-components/src/lib/components/dropdown/DropdownTokensFilter.svelte +++ b/packages/ui-components/src/lib/components/dropdown/DropdownTokensFilter.svelte @@ -2,7 +2,7 @@ import { Button, Dropdown, Label, Checkbox, Input } from 'flowbite-svelte'; import { ChevronDownSolid, SearchSolid } from 'flowbite-svelte-icons'; import { isEmpty } from 'lodash'; - import type { Address, RaindexVaultToken } from '@rainlanguage/orderbook'; + import type { Address, RaindexVaultToken } from '@rainlanguage/raindex'; import type { AppStoresInterface } from '../../types/appStores'; import type { Readable } from 'svelte/store'; import type { QueryObserverResult } from '@tanstack/svelte-query'; diff --git a/packages/ui-components/src/lib/components/input/InputOrderHash.svelte b/packages/ui-components/src/lib/components/input/InputOrderHash.svelte index 8f033f9921..0df08fa5b6 100644 --- a/packages/ui-components/src/lib/components/input/InputOrderHash.svelte +++ b/packages/ui-components/src/lib/components/input/InputOrderHash.svelte @@ -1,7 +1,7 @@ - @@ -137,7 +137,7 @@ emptyMessage="No Orders Found" dataSelector={(page) => page.orders} on:clickRow={(e) => { - goto(`/orders/${e.detail.item.chainId}-${e.detail.item.orderbook}-${e.detail.item.orderHash}`); + goto(`/orders/${e.detail.item.chainId}-${e.detail.item.raindex}-${e.detail.item.orderHash}`); }} > @@ -213,8 +213,8 @@
- Orderbook: - + Raindex: +
diff --git a/packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte b/packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte index ac53b8c7a5..9b7a98877a 100644 --- a/packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte +++ b/packages/ui-components/src/lib/components/tables/VaultBalanceChangesTable.svelte @@ -5,7 +5,7 @@ RaindexVault, type RaindexVaultBalanceChange, type VaultBalanceChangeFilter - } from '@rainlanguage/orderbook'; + } from '@rainlanguage/raindex'; import { formatTimestampSecondsAsLocal } from '../../services/time'; import Hash, { HashType } from '../Hash.svelte'; import { QKEY_VAULT_CHANGES } from '../../queries/keys'; diff --git a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte index 4cf60b095b..78f55ea0c5 100644 --- a/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte +++ b/packages/ui-components/src/lib/components/tables/VaultsListTable.svelte @@ -13,7 +13,7 @@ import { ArrowUpFromBracketOutline, DotsVerticalOutline } from 'flowbite-svelte-icons'; import { createInfiniteQuery, createQuery } from '@tanstack/svelte-query'; import TanstackAppTable from '../TanstackAppTable.svelte'; - import ListViewOrderbookFilters from '../ListViewOrderbookFilters.svelte'; + import ListViewRaindexFilters from '../ListViewRaindexFilters.svelte'; import OrderOrVaultHash from '../OrderOrVaultHash.svelte'; import Hash, { HashType } from '../Hash.svelte'; import { DEFAULT_PAGE_SIZE, DEFAULT_REFRESH_INTERVAL } from '../../queries/constants'; @@ -23,8 +23,8 @@ RaindexVault, RaindexVaultsList, type Address, - type OrderbookCfg - } from '@rainlanguage/orderbook'; + type RaindexCfg + } from '@rainlanguage/raindex'; import { QKEY_TOKENS, QKEY_VAULTS } from '../../queries/keys'; import type { AppStoresInterface } from '$lib/types/appStores.ts'; import { useAccount } from '$lib/providers/wallet/useAccount'; @@ -42,7 +42,7 @@ export let hideInactiveOrdersVaults: AppStoresInterface['hideInactiveOrdersVaults']; export let activeTokens: AppStoresInterface['activeTokens']; export let selectedChainIds: AppStoresInterface['selectedChainIds']; - export let activeOrderbookAddresses: AppStoresInterface['activeOrderbookAddresses']; + export let activeRaindexAddresses: AppStoresInterface['activeRaindexAddresses']; export let ownerFilter: AppStoresInterface['ownerFilter']; export let handleDepositModal: | (( @@ -84,19 +84,19 @@ (address) => !$tokensQuery.data || $tokensQuery.data.some((t) => t.address === address) ) ?? []; - $: orderbooksMap = raindexClient.getAllOrderbooks()?.value ?? new Map(); - $: availableOrderbookAddresses = (() => { + $: raindexesMap = raindexClient.getAllRaindexes()?.value ?? new Map(); + $: availableRaindexAddresses = (() => { const addrs: string[] = []; - orderbooksMap.forEach((cfg: OrderbookCfg) => { + raindexesMap.forEach((cfg: RaindexCfg) => { if ($selectedChainIds.length === 0 || $selectedChainIds.includes(cfg.network.chainId)) { addrs.push(cfg.address.toLowerCase()); } }); return addrs; })(); - $: selectedOrderbookAddresses = - $activeOrderbookAddresses?.filter((address) => - availableOrderbookAddresses.includes(address.toLowerCase()) + $: selectedRaindexAddresses = + $activeRaindexAddresses?.filter((address) => + availableRaindexAddresses.includes(address.toLowerCase()) ) ?? []; $: query = createInfiniteQuery({ @@ -107,7 +107,7 @@ $selectedChainIds, ownerAddress, selectedTokens, - selectedOrderbookAddresses + selectedRaindexAddresses ], queryFn: async ({ pageParam }) => { const result = await raindexClient.getVaults( @@ -116,8 +116,8 @@ owners, hideZeroBalance: $hideZeroBalanceVaults, tokens: selectedTokens, - orderbookAddresses: - selectedOrderbookAddresses.length > 0 ? selectedOrderbookAddresses : undefined, + raindexAddresses: + selectedRaindexAddresses.length > 0 ? selectedRaindexAddresses : undefined, onlyActiveOrders: $hideInactiveOrdersVaults }, pageParam + 1 @@ -215,7 +215,7 @@ {#if $query} - { - goto(`/vaults/${e.detail.item.chainId}-${e.detail.item.orderbook}-${e.detail.item.id}`); + goto(`/vaults/${e.detail.item.chainId}-${e.detail.item.raindex}-${e.detail.item.id}`); }} > @@ -299,8 +299,8 @@
- Orderbook: - + Raindex: +
Owner: @@ -324,7 +324,7 @@ type="orders" orderOrVault={order} chainId={item.chainId} - orderbookAddress={item.orderbook} + raindexAddress={item.raindex} /> {/each} {#if item.ordersAsInput.length > 3}...{/if} @@ -339,7 +339,7 @@ type="orders" orderOrVault={order} chainId={item.chainId} - orderbookAddress={item.orderbook} + raindexAddress={item.raindex} /> {/each} {#if item.ordersAsOutput.length > 3}...{/if} diff --git a/packages/ui-components/src/lib/hooks/useGui.ts b/packages/ui-components/src/lib/hooks/useGui.ts index 5d8636dedb..d4127be1d7 100644 --- a/packages/ui-components/src/lib/hooks/useGui.ts +++ b/packages/ui-components/src/lib/hooks/useGui.ts @@ -1,5 +1,5 @@ import { getContext } from 'svelte'; -import { DotrainOrderGui } from '@rainlanguage/orderbook'; +import { DotrainOrderGui } from '@rainlanguage/raindex'; import { DeploymentStepsError, DeploymentStepsErrorCode } from '../errors/DeploymentStepsError'; export const GUI_CONTEXT_KEY = 'gui-context'; diff --git a/packages/ui-components/src/lib/hooks/useRaindexClient.ts b/packages/ui-components/src/lib/hooks/useRaindexClient.ts index cf004e1232..a84927e8de 100644 --- a/packages/ui-components/src/lib/hooks/useRaindexClient.ts +++ b/packages/ui-components/src/lib/hooks/useRaindexClient.ts @@ -1,5 +1,5 @@ import { getContext } from 'svelte'; -import { RaindexClient } from '@rainlanguage/orderbook'; +import { RaindexClient } from '@rainlanguage/raindex'; import { DeploymentStepsError, DeploymentStepsErrorCode } from '../errors/DeploymentStepsError'; export const RAINDEX_CLIENT_CONTEXT_KEY = 'raindex-client-context'; diff --git a/packages/ui-components/src/lib/index.ts b/packages/ui-components/src/lib/index.ts index 6c8c976865..28fb817eae 100644 --- a/packages/ui-components/src/lib/index.ts +++ b/packages/ui-components/src/lib/index.ts @@ -4,7 +4,7 @@ export { default as Hash, HashType } from './components/Hash.svelte'; export { default as TanstackAppTable } from './components/TanstackAppTable.svelte'; export { default as DropdownCheckbox } from './components/dropdown/DropdownCheckbox.svelte'; export { default as DropdownTokensFilter } from './components/dropdown/DropdownTokensFilter.svelte'; -export { default as DropdownOrderbooksFilter } from './components/dropdown/DropdownOrderbooksFilter.svelte'; +export { default as DropdownRaindexesFilter } from './components/dropdown/DropdownRaindexesFilter.svelte'; export { default as InputOwnerFilter } from './components/input/InputOwnerFilter.svelte'; export { default as DropdownRadio } from './components/dropdown/DropdownRadio.svelte'; export { default as Refresh } from './components/icon/Refresh.svelte'; @@ -12,7 +12,7 @@ export { default as CheckboxActiveOrders } from './components/checkbox/CheckboxA export { default as InputOrderHash } from './components/input/InputOrderHash.svelte'; export { default as CheckboxZeroBalanceVault } from './components/CheckboxZeroBalanceVault.svelte'; export { default as CheckboxInactiveOrdersVault } from './components/CheckboxInactiveOrdersVault.svelte'; -export { default as ListViewOrderbookFilters } from './components/ListViewOrderbookFilters.svelte'; +export { default as ListViewRaindexFilters } from './components/ListViewRaindexFilters.svelte'; export { default as OrdersListTable } from './components/tables/OrdersListTable.svelte'; export { default as VaultsListTable } from './components/tables/VaultsListTable.svelte'; export { default as PageHeader } from './components/PageHeader.svelte'; diff --git a/packages/ui-components/src/lib/providers/GuiProvider.svelte b/packages/ui-components/src/lib/providers/GuiProvider.svelte index 3ea838c727..5773cadde6 100644 --- a/packages/ui-components/src/lib/providers/GuiProvider.svelte +++ b/packages/ui-components/src/lib/providers/GuiProvider.svelte @@ -1,6 +1,6 @@