Skip to content

Phase 0: availableBalance refactor to pure helpers + tests#36

Closed
kgrgpg wants to merge 2 commits intorefactor/better-codefrom
refactor/phase0-available-balance-pure
Closed

Phase 0: availableBalance refactor to pure helpers + tests#36
kgrgpg wants to merge 2 commits intorefactor/better-codefrom
refactor/phase0-available-balance-pure

Conversation

@kgrgpg
Copy link
Contributor

@kgrgpg kgrgpg commented Aug 12, 2025

Phase 0: availableBalance refactor to pure helpers + tests

This PR is stacked on top of PR #35 (base: refactor/better-code). It completes the Phase 0 vertical slice for health/withdraw by wiring the public query path to pure helpers while preserving existing top-up behavior.

Summary

  • availableBalance:
    • Preserves deposit-assisted path when pullFromTopUpSource=true by delegating to fundsAvailableAboveTargetHealthAfterDepositing(...).
    • Otherwise uses the new pure pipeline: buildPositionView(pid) + maxWithdraw(...) with 18-decimal UInt256 math.
  • Pure math tests: Adds cadence/tests/phase0_pure_math_test.cdc covering healthFactor and maxWithdraw (both debt-increase and collateral-drawdown paths). Expectations computed in UInt256 to match on-chain truncation.
  • Docs: Regenerates REFACTORING_PLAN.md code sections to use current Cadence syntax and mirror the implemented Phase 0 shape (incl. top-up path note).
  • Housekeeping: Removes deprecated DeFiBlocks/ and REFACTOR_EVALUATION.md (superseded by DeFiActions and current plan).

Rationale

  • Introduces a clean functional-core / imperative-shell boundary without changing end-user semantics.
  • Greatly improves testability of the core math (healthFactor, maxWithdraw).
  • Keeps deposit-assisted behavior intact for platforms relying on topUpSource.

Implementation Notes

  • buildPositionView(pid) creates immutable snapshots per token (price, indices, risk) and copies of position balances; no storage mutation.
  • maxWithdraw(view, withdrawSnap, withdrawBal, targetHealth) solves the linear constraint to maintain target health; handles both credit and debit cases.
  • availableBalance now chooses:
    • Top-up path → original async/deposit-assisted logic.
    • Pure path → view + helper + uint256ToUFix64(...).
  • Rounding is explicit in 18-decimal UInt256 arithmetic to match chain truncation.

Tests

  • Added: cadence/tests/phase0_pure_math_test.cdc
    • test_healthFactor_zeroBalances_returnsZero
    • test_healthFactor_simpleCollateralAndDebt
    • test_maxWithdraw_increasesDebtWhenNoCredit
    • test_maxWithdraw_fromCollateralLimitedByHealth
  • All existing suites remain passing with run_tests.sh.

Backward Compatibility

  • No change to deposit-assisted semantics when pullFromTopUpSource=true.
  • Query-only behavior updated to use pure math; results validated against existing suites.

Documentation

  • REFACTORING_PLAN.md snippets updated to current Cadence (access(all), correct entitlements/types) and reflect the preserved top-up path in availableBalance.

Next Phases (follow-ups)

  • Phase 1: introduce applyWithdraw/applyDeposit/applyAccrual/applyLiquidation with pre/post invariants, using the same pure helpers for validation before mutation.
  • Phase 2+: rate/capacity pure math; async queue refactor; governance resource & snapshots.

How to verify locally

./run_tests.sh

All tests should pass, including the new Phase 0 tests.

kgrgpg added 2 commits August 12, 2025 12:03
…add phase0 pure math tests; remove DeFiBlocks dir and REFACTOR_EVALUATION.md
Copy link
Contributor

@sisyphusSmiling sisyphusSmiling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes look to be included in #35. If this branch has already been merged to refactor/better-code, I think we can close this one out and review in #35

Comment on lines +622 to +644
let view = self.buildPositionView(pid: pid)

// Build a TokenSnapshot for the requested withdraw type (may not exist in view.snaps)
let tokenState = self._borrowUpdatedTokenState(type: type)
let snap = TidalProtocol.TokenSnapshot(
price: TidalProtocolUtils.ufix64ToUInt256(self.priceOracle.price(ofToken: type)!, decimals: 18),
credit: tokenState.creditInterestIndex,
debit: tokenState.debitInterestIndex,
risk: TidalProtocol.RiskParams(
cf: TidalProtocolUtils.ufix64ToUInt256(self.collateralFactor[type]!, decimals: 18),
bf: TidalProtocolUtils.ufix64ToUInt256(self.borrowFactor[type]!, decimals: 18),
lb: TidalProtocolUtils.e18 + 50_000_000_000_000_000
)
)

let withdrawBal = view.balances[type]
let uintMax = TidalProtocol.maxWithdraw(
view: view,
withdrawSnap: snap,
withdrawBal: withdrawBal,
targetHealth: view.minHealth
)
return TidalProtocolUtils.uint256ToUFix64(uintMax, decimals: 18)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what's going on, but these changes appear to be included in #35

@kgrgpg
Copy link
Contributor Author

kgrgpg commented Aug 18, 2025

Thanks! This branch was stacked on #35 and those changes have been incorporated into refactor/better-code (now migrated to UInt128/e24 via DeFiActionsMathUtils). Closing this PR and continuing review in #35: #35

@kgrgpg
Copy link
Contributor Author

kgrgpg commented Aug 18, 2025

Closing in favor of #35; changes are already included and updated to UInt128/e24 on refactor/better-code.

@kgrgpg kgrgpg closed this Aug 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments