Conversation
Saves a bit of gas
Saves a bit of gas
For front end use
Allows user to change details of an open order. Functionally equivalent to canceling an existing order and opening a new one, with orderID retained and only one transaction required. Difference between existing and new order details is transferred from or to user.
CDAuctioneer Limit Orders
fix(cd-limit-orders): inherit `IERC721Receiver`, correct `getRemaining`, optimize
…rs-tweak Convertible Deposits: Parameters Tweak
Convertible Deposits: Limit Orders
📝 WalkthroughWalkthroughThis PR introduces a comprehensive limit order system for the Convertible Deposit Auctioneer, including a new core contract ( Changes
Sequence Diagram(s)sequenceDiagram
participant User as User
participant LimitOrders as LimitOrders Contract
participant CDAuctioneer as CDAuctioneer
participant DepositManager as DepositManager
participant USDS as USDS (ERC20)
participant sUSDS as sUSDS (ERC4626)
participant NFT as Position NFT
User->>LimitOrders: createOrder(period, depositBudget, incentiveBudget, maxPrice)
LimitOrders->>USDS: transferFrom(user, limitOrders, depositBudget + incentiveBudget)
LimitOrders->>sUSDS: deposit(depositBudget into sUSDS)
LimitOrders->>LimitOrders: Store order in mapping
LimitOrders-->>User: Return orderId
User->>LimitOrders: fillOrder(orderId, fillAmount)
LimitOrders->>LimitOrders: Validate order is active
LimitOrders->>CDAuctioneer: bid(period, fillAmount)
CDAuctioneer->>DepositManager: deposit(USDS, fillAmount)
CDAuctioneer-->>LimitOrders: Return (ohmOut, positionId, receiptTokenId, actualAmount)
LimitOrders->>NFT: transferFrom(limitOrders, filler, positionId)
LimitOrders->>USDS: transfer(filler, incentivePaid)
LimitOrders->>LimitOrders: Update order spent amounts
LimitOrders-->>User: Return (ohmOut, incentivePaid, actualAmount)
sequenceDiagram
participant Owner as Owner/Caller
participant LimitOrders as LimitOrders Contract
participant sUSDS as sUSDS (ERC4626)
participant YieldRecipient as Yield Recipient
Owner->>LimitOrders: getAccruedYield()
LimitOrders->>sUSDS: balanceOf(limitOrders)
sUSDS-->>LimitOrders: Return sUSDS balance
LimitOrders-->>Owner: Return total yield in sUSDS
Owner->>LimitOrders: sweepYield()
LimitOrders->>LimitOrders: Calculate accrued shares
LimitOrders->>sUSDS: transfer(yieldRecipient, accruedShares)
sUSDS-->>YieldRecipient: Receive sUSDS
LimitOrders->>LimitOrders: Reset yield tracking
LimitOrders-->>Owner: Return shares transferred
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Fix all issues with AI agents
In @src/scripts/ops/batches/ConvertibleDepositInstall.sol:
- Around line 802-879: The batch can re-enable disabled periods because
_configureDepositPeriods zeros reclaim rates for disabled entries but
_configureReclaimRates runs after and will set reclaim rates even for periods
not in enabledPeriods; before calling _configureReclaimRates in
configureDepositParameters, filter reclaimRatePeriods/reclaimRates to include
only periods present in enabledPeriods (or alternatively revert if any
reclaimRatePeriods are not subset of enabledPeriods) so that reclaim-rate
updates are skipped for disabled periods; implement the filtering/validation
immediately prior to the _configureReclaimRates call using the local variables
enabledPeriods, reclaimRatePeriods, and reclaimRates.
In @src/scripts/ops/lib/BatchScriptV2.sol:
- Around line 394-446: The validation currently pranks and calls heart.beat()
which both is unnecessary (beat has no access control) and mutates contract
state; to fix, in _validateHeartBeat wrap the entire heart-beat validation in a
VM snapshot/revert pair (use vm.snapshot() before calling _executeHeartBeats and
vm.revertTo(snapshotId) after) so you can call heartContract.beat() (via
_executeHeartBeats) without persisting lastBeat/reward changes, and remove any
vm.prank around the heart.beat calls (keep vm.prank only where needed for
priceModule.changeUpdateThresholds using priceConfig); reference
_validateHeartBeat, _executeHeartBeats, heartContract.beat(), vm.snapshot(), and
vm.revertTo().
In @src/test/mocks/MockConvertibleDepositAuctioneer.sol:
- Around line 62-112: In bid(), prevent underflow by requiring depositAmount_ >=
actualAmountDifference before computing actualAmount and align behavior with
production by checking that ohmOut != 0 and reverting on zero output before
doing the slippage check; specifically: compute ohmOut as now, if (ohmOut == 0)
revert("Zero output"), then require(ohmOut >= minOhmOut_, "Slippage"), then
require(depositAmount_ >= actualAmountDifference) and set actualAmount =
depositAmount_ - actualAmountDifference, and continue with the existing
deposit/mint flow (references: function bid, variables ohmOut, minOhmOut_,
actualAmountDifference, actualAmount).
In @src/test/mocks/MockDepositManager.sol:
- Around line 20-22: The functions configureDependencies and requestPermissions
currently rely on implicit default returns; explicitly construct and return
zero-length memory arrays of the correct types (Keycode[] for
configureDependencies and Permissions[] for requestPermissions) and return them
to make the ABI and calling code behavior explicit and safe.
🧹 Nitpick comments (9)
src/modules/RANGE/RANGE.v2.sol (1)
2-2: Pragma widened to allow future Solidity versions.The change from exact
0.8.15to>=0.8.15aligns with the broader PR pattern. For production modules, you may optionally consider a bounded pragma (e.g.,>=0.8.15 <0.9.0) to guard against potential breaking changes in future major versions, though this is not critical given Solidity 0.8.x stability.src/modules/CHREG/OlympusClearinghouseRegistry.sol (1)
2-2: Pragma widened for compiler flexibility.Consistent with the PR-wide pattern. Same optional consideration applies: a bounded upper limit (e.g.,
<0.9.0) could provide additional safety for production modules against future major version changes, though not strictly necessary.src/interfaces/IVersioned.sol (1)
1-14: Interface is fine; consider whether you want patch-level versioning and a tighter pragma.
- Returning
(major, minor)is straightforward; if you expect hotfix tracking, consider(major, minor, patch)(orbytes32semver string) up-front to avoid future interface churn.- If the repo is standardizing on
>=0.8.20elsewhere, aligning this pragma helps reduce toolchain variance.src/scripts/ops/lib/BatchScriptV2.sol (1)
416-433: Temp PRICE thresholds should be derived fromfrequency * numBeats(not fixed at2 days).If Heart frequency is ever > 16 hours (or changes),
2 daysmight not cover a 3-beat warp window and you can still hit stale feed checks.Also applies to: 447-475
src/test/mocks/MockDepositManager.sol (1)
26-38: Consider using SafeERC20 (or checking return values) even in mocks to match production ERC20 quirks.If
IERC20.transfer/transferFromreturnsbool, ignoring it can make tests pass incorrectly with “false-returning” tokens.src/scripts/ops/batches/ConvertibleDepositInstall.sol (1)
971-1020: Base-emissions “set” is actually scheduled; ensure that’s intended for this ops flow.
changeBaseRate(changeNeeded, uint48(1), shouldAdd)won’t necessarily makebaseEmissionRate == desiredimmediately; it schedules a change over beats. If this script is meant to converge the parameter immediately, you may want a direct setter (if available) or an explicit note in logs/args schema that this is “next beat”.src/test/mocks/MockConvertibleDepositAuctioneer.sol (3)
62-112: EnforceminimumBidinbid()(not onlypreviewBid()) to keep mock internally consistent.Right now
previewBid()returns0belowminimumBid, butbid()will proceed (and may mint/deposit), which can create confusing test behavior.Also applies to: 114-121
189-206: ImplementenableDepositPeriod/disableDepositPeriodto updatedepositPeriodsEnabled+enabledPeriods(instead of no-ops).Since other code paths may call the interface functions (not the test helper), leaving these empty can cause silent divergence in tests.
Also applies to: 228-255
93-110: Receipt/NFT minting via low-level calls is permissive; add basic contract-address checks (or use dedicated mocks).Calling
receiptTokenAddr.call(...)can succeed against EOAs (no mint) and still returntrue, producing false-positive tests. Similarly,positionIdis assumed to match minted token id.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (30)
deployments/.mainnet-1767809879.jsondeployments/.sepolia-1766489520.jsondeployments/.sepolia-1766582124.jsonshell/safeBatchV2.shsrc/interfaces/IVersioned.solsrc/modules/CHREG/OlympusClearinghouseRegistry.solsrc/modules/RANGE/OlympusRange.solsrc/modules/RANGE/RANGE.v2.solsrc/policies/deposits/LimitOrders.solsrc/policies/interfaces/deposits/ILimitOrders.solsrc/scripts/deploy/DeployV3.s.solsrc/scripts/deploy/savedDeployments/convertible_deposit_limit_orders.jsonsrc/scripts/deploy/savedDeployments/convertible_deposit_limit_orders_sepolia.jsonsrc/scripts/env.jsonsrc/scripts/ops/batches/ConvertibleDepositInstall.solsrc/scripts/ops/batches/PeripheryEnable.solsrc/scripts/ops/batches/args/ConfigureDepositParameters_202512.jsonsrc/scripts/ops/batches/args/ConvertibleDepositLimitOrders.jsonsrc/scripts/ops/lib/BatchScriptV2.solsrc/test/lib/bonds/BondAggregator.solsrc/test/lib/bonds/BondFixedTermSDA.solsrc/test/lib/bonds/BondFixedTermTeller.solsrc/test/lib/bonds/bases/BondBaseSDA.solsrc/test/lib/bonds/bases/BondBaseTeller.solsrc/test/mocks/MockConvertibleDepositAuctioneer.solsrc/test/mocks/MockDepositManager.solsrc/test/mocks/MockPrice.solsrc/test/policies/ConvertibleDepositAuctioneer/LimitOrders.t.solsrc/test/policies/ConvertibleDepositAuctioneer/LimitOrdersFork.t.solsrc/test/policies/EmissionManager.t.sol
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 29
File: src/policies/deposits/BaseDepositFacility.sol:631-639
Timestamp: 2025-11-07T11:09:53.808Z
Learning: OlympusDAO/olympus-v3: BaseDepositFacility.setAssetPeriodReclaimRate now uses a dedicated reclaim-rate error (not InvalidAddress) when reclaimRate_ > ONE_HUNDRED_PERCENT, fixed in a follow-up PR (#180). Avoid re-flagging this in earlier PRs.
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 29
File: src/modules/TRSRY/TRSRY.v1.sol:2-2
Timestamp: 2025-07-18T00:21:49.138Z
Learning: 0xJem prefers to avoid changing historical/already-deployed contracts to minimize risk and maintain stability, even when it would improve consistency across the codebase.
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 29
File: remappings.txt:35-40
Timestamp: 2025-07-18T00:22:32.511Z
Learning: 0xJem prefers to keep OpenZeppelin 4.8.0 as the standard/default dependency in remappings.txt for stability, with newer versions like 5.3.0 available only through explicit versioned dependency paths (e.g., openzeppelin-5.3.0/) to ensure intentional opt-in to newer versions.
📚 Learning: 2025-08-08T07:33:13.575Z
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 86
File: src/policies/deposits/DepositManager.sol:271-320
Timestamp: 2025-08-08T07:33:13.575Z
Learning: DepositManager (src/policies/deposits/DepositManager.sol) is deployed as non-upgradeable; when releasing a new version, existing receipt tokens and underlying deposits remain with the previous DepositManager instance. No migration path is expected or required when introducing facility scoping.
Applied to files:
src/scripts/deploy/savedDeployments/convertible_deposit_limit_orders.jsonsrc/test/mocks/MockDepositManager.solsrc/scripts/deploy/DeployV3.s.soldeployments/.mainnet-1767809879.jsonsrc/scripts/deploy/savedDeployments/convertible_deposit_limit_orders_sepolia.jsonsrc/test/policies/EmissionManager.t.soldeployments/.sepolia-1766582124.jsonsrc/policies/deposits/LimitOrders.solsrc/scripts/ops/batches/ConvertibleDepositInstall.solsrc/test/policies/ConvertibleDepositAuctioneer/LimitOrdersFork.t.solsrc/test/mocks/MockConvertibleDepositAuctioneer.solsrc/policies/interfaces/deposits/ILimitOrders.sol
📚 Learning: 2025-08-08T11:14:54.317Z
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 88
File: src/test/policies/ConvertibleDepositAuctioneer/ConvertibleDepositAuctioneerTest.sol:413-416
Timestamp: 2025-08-08T11:14:54.317Z
Learning: In ConvertibleDepositAuctioneer (src/policies/deposits/ConvertibleDepositAuctioneer.sol), bid() reverts with ConvertibleDepositAuctioneer_ConvertedAmountZero when ohmOut == 0, before evaluating the minOhmOut slippage check. Therefore, setting minOhmOut=0 does not guarantee acceptance in zero-output scenarios; the zero-output revert triggers first.
Applied to files:
src/scripts/deploy/DeployV3.s.soldeployments/.mainnet-1767809879.jsonsrc/test/policies/EmissionManager.t.solsrc/scripts/ops/batches/ConvertibleDepositInstall.solsrc/test/mocks/MockConvertibleDepositAuctioneer.solsrc/policies/interfaces/deposits/ILimitOrders.sol
📚 Learning: 2025-11-07T11:09:53.808Z
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 29
File: src/policies/deposits/BaseDepositFacility.sol:631-639
Timestamp: 2025-11-07T11:09:53.808Z
Learning: OlympusDAO/olympus-v3: BaseDepositFacility.setAssetPeriodReclaimRate now uses a dedicated reclaim-rate error (not InvalidAddress) when reclaimRate_ > ONE_HUNDRED_PERCENT, fixed in a follow-up PR (#180). Avoid re-flagging this in earlier PRs.
Applied to files:
deployments/.mainnet-1767809879.jsonsrc/scripts/ops/batches/ConvertibleDepositInstall.solsrc/test/mocks/MockConvertibleDepositAuctioneer.sol
📚 Learning: 2025-08-04T11:03:24.007Z
Learnt from: 0xJem
Repo: OlympusDAO/olympus-v3 PR: 84
File: src/test/policies/YieldDepositFacility/execute.t.sol:41-43
Timestamp: 2025-08-04T11:03:24.007Z
Learning: In YieldDepositFacility, 0xJem intentionally allows snapshots to be overwritten/updated within the same block to ensure they reflect the latest vault conversion rates. This is not a gaming vulnerability but desired behavior - the gaming fix was removing timestamp hints, not preventing snapshot updates within blocks.
Applied to files:
src/scripts/ops/batches/ConvertibleDepositInstall.sol
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: Cursor Bugbot
- GitHub Check: run-ci
- GitHub Check: run-ci
- GitHub Check: run-ci
- GitHub Check: run-ci
- GitHub Check: run-ci
- GitHub Check: run-ci
- GitHub Check: run-ci
🔇 Additional comments (35)
src/test/mocks/MockPrice.sol (1)
2-2: LGTM!Pragma widening for test mocks is appropriate and consistent with the PR-wide compiler compatibility updates.
src/test/lib/bonds/bases/BondBaseSDA.sol (1)
2-2: LGTM!Pragma widening for the test bond library is consistent with the PR-wide updates.
src/test/lib/bonds/BondFixedTermTeller.sol (1)
2-2: LGTM!Pragma widening for the test bond teller library aligns with the PR-wide compiler compatibility updates.
src/modules/RANGE/OlympusRange.sol (1)
2-2: Pragma relaxation acknowledged.The pragma change from exact
0.8.15to>=0.8.15allows broader compiler compatibility. Since no logic changes accompany this update, the risk is minimal. Based on learnings, this appears intentional despite the preference to avoid changes to deployed contracts.src/test/lib/bonds/bases/BondBaseTeller.sol (1)
2-2: LGTM!Pragma relaxation for a test library file is appropriate and allows broader compiler compatibility for testing purposes.
src/test/lib/bonds/BondFixedTermSDA.sol (1)
2-2: LGTM!Consistent pragma relaxation for test library files.
src/test/lib/bonds/BondAggregator.sol (1)
2-2: LGTM!Consistent pragma relaxation for test library files.
src/scripts/ops/batches/args/ConfigureDepositParameters_202512.json (1)
1-16: Configuration parameters look reasonable.The parameter values appear well-formed:
enabledPeriodsandreclaimRatePeriodsarrays are correctly aligned (both contain period3)reclaimRatesvalue of9750(97.5% in basis points) is within valid bounds (< 100%)minPriceScalarof1.1e18represents a 10% floor above base priceConsider adding a companion documentation file or inline comments in the consuming script to explain the rationale for these specific parameter choices for future maintainers.
src/scripts/ops/lib/BatchScriptV2.sol (1)
384-393: VerifystdJson.readUintArrayis available in your forge-std version.If
readUintArrayisn’t supported (or behaves differently), this will fail at runtime when parsing args files.src/test/policies/EmissionManager.t.sol (1)
3-3: Ctor callsite updates look consistent; just ensure no tests invokebid()withdepositManager = address(0).If any test path starts exercising bid/limit-order flows against this mock instance, the zero depositManager will revert on deposit.
Also applies to: 317-321, 845-846, 3263-3267
deployments/.mainnet-1767809879.json (1)
1-3: Verify this address matches the deployed bytecode for the intended mainnet release artifact.At minimum, confirm it matches your deploy script output and any saved deployment JSON used by ops tooling.
deployments/.sepolia-1766582124.json (1)
1-3: LGTM!The deployment mapping follows the established naming convention and contains a valid checksummed Ethereum address.
deployments/.sepolia-1766489520.json (1)
1-3: LGTM!Valid deployment mapping with proper address format. This appears to be an earlier Sepolia deployment compared to the 1766582124 timestamp file.
src/scripts/deploy/savedDeployments/convertible_deposit_limit_orders_sepolia.json (1)
1-13: LGTM!The Sepolia deployment configuration correctly uses a different receipt token address from the mainnet config while maintaining the same deposit period structure.
src/scripts/ops/batches/args/ConvertibleDepositLimitOrders.json (1)
1-10: LGTM!The batch configuration correctly references the
PeripheryEnablefunction with the matching contract identifier used in the deployment mappings.src/scripts/deploy/savedDeployments/convertible_deposit_limit_orders.json (1)
1-13: Configuration structure is correct; external verification needed for token validity.The JSON structure is valid with matching array lengths. The CDAuctioneerLimitOrders contract validates that the receipt token address is non-zero (line 173 in src/policies/deposits/LimitOrders.sol) and that the deposit period is enabled in the auctioneer (line 181). However, the contract does not validate that the provided address is the actual CDR (Convertible Deposit Receipt) token for deposit period 3. Confirm that
0x03d95a2f9A29228ea6D0690f2d1Bcd15973d926Fis the registered receipt token for period 3 on mainnet through blockchain inspection or deployment records.shell/safeBatchV2.sh (1)
17-17: LGTM!The verbose flag implementation follows the established patterns for boolean flags in this script. The verbosity levels (
-vvvdefault,-vvvvverbose) are appropriate for Forge script debugging.Also applies to: 40-40, 54-54, 66-66, 111-119
src/scripts/deploy/DeployV3.s.sol (3)
293-309: LGTM!The helper correctly uses
SafeCast.encodeUInt8which will revert if any value exceeds 255, ensuring safe downcasting fromuint256touint8.
311-319: LGTM!Follows the established pattern for deployment argument readers.
799-854: LGTM!The deployment function follows established patterns. Array length validation is appropriately delegated to the
CDAuctioneerLimitOrdersconstructor which will revert withArrayLengthMismatchif lengths don't match.src/scripts/env.json (1)
445-445: LGTM!The new
ConvertibleDepositAuctioneerLimitOrdersaddresses are correctly placed underolympus.peripheryfor mainnet and sepolia, consistent with the deployment script's return prefix.Also applies to: 642-642
src/scripts/ops/batches/PeripheryEnable.sol (1)
13-34: LGTM!The batch script correctly reads the contract key, resolves the address, and encodes the
enablecall. The empty payloadabi.encode("")is appropriate sinceCDAuctioneerLimitOrders._enableis a no-op.src/test/policies/ConvertibleDepositAuctioneer/LimitOrdersFork.t.sol (2)
48-100: LGTM!The fork test setup is well-structured. It correctly fetches deposit periods from the on-chain auctioneer, resolves receipt tokens via the deposit manager, and initializes the
LimitOrderscontract with realistic mainnet state.
102-180: LGTM!The test provides comprehensive coverage of the order lifecycle. The use of
assertGeat line 174 is appropriate since the filler could potentially have pre-existing USDS balance or receive additional tokens from other sources during the fill.src/policies/deposits/LimitOrders.sol (9)
87-121: LGTM!The constructor properly validates all inputs, sets immutables, and initializes the deposit period mapping. The max approval to sUSDS is a standard pattern for vault contracts.
221-254: LGTM!The
_depositfunction correctly handles sUSDS rounding by adjusting budgets based on the actual withdrawable amount. The check for zero shares prevents deposits that would round to nothing.
271-331: LGTM!The
createOrderfunction has comprehensive validation including ERC721 receiver check for early failure, minimum bid validation against the auctioneer, and proper accounting oftotalUsdsOwed.
375-446: LGTM!The
fillOrderfunction is well-implemented with proper validation, accounting, and transfers. The approval toDEPOSIT_MANAGER(line 417) is correct—the auctioneer'sbidfunction pulls tokens through the deposit manager. The re-deposit of remaining USDS (lines 436-437) handles dust appropriately by only depositing if it would result in at least 1 share.
457-479: LGTM!The
cancelOrderfunction intentionally omits theonlyEnabledmodifier to allow users to withdraw funds even when the contract is disabled. The use ofsaturatingSubis a defensive measure against potential accounting edge cases.
486-515: LGTM!The yield functions correctly use
previewWithdraw(which rounds up) to calculate the maximum shares needed to cover obligations, ensuring the protocol never sweeps funds that belong to users. ThesaturatingSubprovides additional safety.
340-357: LGTM!The incentive calculation correctly handles the final fill by allocating all remaining incentive, avoiding rounding dust. The multiplication in line 355 is safe for realistic deposit amounts.
581-619: LGTM!The
canFillOrderview function correctly mirrors all the validation checks infillOrder, providing consistent off-chain fillability preview.
681-774: LGTM!The
_getFillableOrdersfunction uses a standard pattern for building dynamic arrays in view functions. ThesupportsInterfacecorrectly declares support for all implemented interfaces.src/policies/interfaces/deposits/ILimitOrders.sol (2)
9-105: LGTM!The error and event definitions are comprehensive and well-documented, matching all usages in the implementation.
107-343: LGTM!The
LimitOrderstruct and all function signatures are well-defined with comprehensive NatSpec documentation. The interface correctly captures the full public API surface ofCDAuctioneerLimitOrders.
Note
Introduces limit orders for Convertible Deposits and wires up deployment and ops support.
CDAuctioneerLimitOrderscontract withcreateOrder/fillOrder/cancelOrder, incentive handling, sUSDS yield sweep, ERC721 position/receipt token transfers, andIVersioned+ILimitOrdersinterfacesdeployConvertibleDepositAuctioneerLimitOrders()inDeployV3.s.sol, saved deployment configs for mainnet/sepolia, and env/deployments files updated with addressesPeripheryEnablebatch to callIEnabler.enable, newConvertibleDepositInstall.configureDepositParametersflow,safeBatchV2.shadds--verbose, andBatchScriptV2gains arg array readers and heartbeat validationWritten by Cursor Bugbot for commit 5715d2b. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Release Notes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.