Release: develop -> main - #4458
Merged
Merged
Conversation
…hrough the value history (#4451) * fix(custody): carry the saving position and its interest through the value history The Safe's value history dropped any holding whose asset had no asset_price row for a given day, and left accrued interest out of both the history and the balance total. Ethereum/sZCHF was created long after the deposits it represents, so it has no price series before its creation date. The daily valuation iterated over the prices and looked up a balance for each, which meant a holding without a row that day contributed nothing and vanished from the series without a trace. In production a position booked in January only appeared in the chart six months later, on the day its first price was written, as a vertical jump. Valuation is now driven by the holdings instead, and an asset without a row of its own is priced from an asset sharing its price rule -- identical by definition, not an estimate. A holding that cannot be priced at all is reported once per request rather than silently skipped. Accrued interest is now part of both figures. It was previously excluded from totalValue to keep it equal to the history, which had no notion of interest; the history accrues it per day now, so both sides agree and the customer sees what the position is actually worth. * style: apply prettier formatting * fix(custody): stop reporting interest for a closed saving position Tranches accrue with their own sign, so a fully paid out position leaves a frozen remainder -- the interest it earned while it was held. That figure is never booked and never paid out. Carrying it into totalValue and the value history, as this branch newly does, left a Safe holding nothing showing a residue forever. Interest is now only reported while the position is actually open, in both the balance total and the history. Partial payouts are unaffected: the remaining principal keeps accruing, which the existing negative-tranche test pins down. Also replaces the exact zero-balance comparison in the daily valuation with a tolerance. Balances are plain floating point sums, so a closed position rarely lands on exact zero, and the dust left behind would be reported as an unpriced holding on any day without a price. * refactor(custody): hold the dust bound in one place The closed-position guards compared against exact zero while the daily valuation used a tolerance, so floating point residue could pass one and not the other -- and reviving the interest of a position that is in fact closed is exactly what the guard exists to prevent. All three now share one documented bound.
github-actions
Bot
requested review from
TaprootFreak and
davidleomay
as code owners
July 29, 2026 14:48
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automatic Release PR
This PR was automatically created after changes were pushed to develop.
Commits: 1 new commit(s)
Checklist