Skip to content

Release: develop -> main#324

Open
github-actions[bot] wants to merge 3 commits into
mainfrom
develop
Open

Release: develop -> main#324
github-actions[bot] wants to merge 3 commits into
mainfrom
develop

Conversation

@github-actions

@github-actions github-actions Bot commented May 2, 2026

Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 1 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

* Add Telegram alerts bot link to footer and governance page

Introduces NEXT_PUBLIC_TELEGRAM_BOT_URL config so DEV deployments can
point to the dev bot while PRD points to the prod bot. Footer now
exposes both the community channel and the alerts bot as separate
icons. Adds title/aria-label to all footer social links.

* Move Telegram bot URLs into code config, drop env variable

The NEXT_PUBLIC_TELEGRAM_BOT_URL env variable is removed; both bot
URLs (prd/dev) live in SOCIAL.TelegramBot in utils/constant.ts. The
DEV/PRD selection reuses the existing NEXT_PUBLIC_APP_URL value via
optional chaining (no new fallback introduced).

* Use explicit DEPLOYMENT_ENV switch instead of URL string match

Replaces the fragile process.env.NEXT_PUBLIC_APP_URL?.startsWith("https://dev.")
detection with an explicit DEPLOYMENT_ENV constant in utils/constant.ts.
The constant reads NEXT_PUBLIC_DEPLOYMENT_ENV ("prd" | "dev") and throws
on missing/invalid value (no fallback). Bot URL is then a direct lookup
SOCIAL.TelegramBot[DEPLOYMENT_ENV].

DEV deployment must set NEXT_PUBLIC_DEPLOYMENT_ENV=dev, PRD must set =prd.

* Wire NEXT_PUBLIC_DEPLOYMENT_ENV through Docker build pipeline

Adds an ARG/ENV pair to the Dockerfile and passes the value via
build-args from each CI workflow:
- dapp-dev.yaml (build :beta on develop) -> NEXT_PUBLIC_DEPLOYMENT_ENV=dev
- api-prd.yaml  (build :latest on main)  -> NEXT_PUBLIC_DEPLOYMENT_ENV=prd

The value is fixed into the image at build time, so the constant.ts
validation runs against a real "prd" or "dev" string rather than the
placeholder used by the runtime sed-replace pattern.
* Fix "Available to lend" stuck at 0 on existing positions

The borrow-more headroom in BorrowedManageSection mixed gross and net
amounts: it computed amountToSendToWallet (net, after reserve cut) at
the current liquidation price and subtracted totalDebt (gross,
principal + interest). On a near-cap position the result clamped to
zero — even when Position._mint would still accept additional minting
on-chain.

Replace the formula with a port of the on-chain check in
MintingHubV3/Position.sol:

  collateral × price >= (principal + ΔX + ceilDivPPM(interest, reservePPM)) × 1e18

so ΔX_gross_max = collateralValue − principal − interestOverhead,
capped by Position.availableForMinting() (family-wide limit), then
discounted by (1 − reservePPM/1e6) to match the net UI input.

The formula is extracted as a pure utility (calculateNetBorrowHeadroom)
and covered by a unit test seeded with the live state of the WBTC
position 0x5AFb27c7…: gives 4 369.50 dEURO of headroom where the UI
previously displayed 0.

* Project interest forward when bounding borrow headroom

The previous version of calculateNetBorrowHeadroom consumed the bare
`getInterest()` snapshot from RPC. `Position._mint` runs
`_accrueInterest()` first and then `_checkCollateral`, so by the time
the TX is included the stored interest is higher than what the UI saw.
On a position that has not been touched for months (lastAccrual far in
the past), even a couple of seconds of inclusion delay push
`collateralRequirement × 1e18` past `collateral × price` and revert
with InsufficientCollateral.

Observed in mainnet tx 0x3dc68fbf34f02d6bdc7d2e036973fdd74c0f79d50697a5b773e1698ade3c8b54:
the mint requested by the "Lend more" max button reverted with
  needed     = 51_000.000000 dEURO  (collateral × price / 1e18)
  available  = 51_000.000451 dEURO  (collateralRequirement)
i.e. only ~2.66 seconds of additional interest accrual blew the budget.

Use the existing `calculateTimeBuffer` helper (already wired to the
DELAY_MINUTES=10 window used by repay quoting) to add the worst-case
extra interest before applying `_ceilDivPPM`, so the displayed max
remains mintable across realistic inclusion times.

On the 0x5AFb position the displayed "Available to lend" moves from
4 369.50 dEURO to 4 369.40 dEURO — negligible loss in usable headroom,
robust against the race condition.

* Align borrow-more max with the repay buffer pattern

The previous followup added the interest projection inside the
formula (projectedInterest = interest + calculateTimeBuffer(...)).
Flip it to the same shape the existing repay branch already uses on
line 196:

  const timeBufferWei = calculateTimeBuffer(principal, ratePPM);
  const safe = raw > timeBufferWei ? raw - timeBufferWei : 0n;

Same helper, same magic, same control-flow shape — reviewers see one
buffer pattern across both branches of the manage section. Math
result is within a few atto-dEURO of the additive variant; the live
0x5AFb position still displays ~4 369.40 dEURO of headroom.

* Align style with surrounding utils and tests

- Test file: switch to repo-wide double-quote string style (matches
  tests/coverage.spec.ts) and let prettier collapse the column-aligned
  trailing comments. `npx prettier --check` is now clean.
- calculateNetBorrowHeadroom: rename the destructured argument from
  `input` to `params`, matching the only other named-object helper in
  utils/ (`calculateOptimalRepayAmount` in dynamicRepayCalculations).

No logic changes; 6/6 unit tests still pass.

* Validate borrow-more against the raw on-chain cap, not the buffered max

Reproduced on localhost: clicking the max button filled the input with
`maxBeforeAddingMoreCollateral` (raw − calculateTimeBuffer). On the
very next block refetch — wagmi pulls `getInterest()` again every
block — the buffered max shrank by a few atto-dEURO. The validation
guard `BigInt(amount) > maxBeforeAddingMoreCollateral` then tripped
and the Lend more button greyed out within seconds, even though the
amount was still safely mintable on-chain.

Match the repay branch on line 150-160, which validates against
`walletBalance` and `debt` directly (the raw on-chain caps), not
against the buffered `maxFromWallet`. After this change the time
buffer protects exactly what it should — the on-chain
_checkCollateral after `_accrueInterest` — and the UI tolerates the
expected per-block drift without flickering the button.

New regression test covers a 5-minute idle window (half the
DELAY_MINUTES cushion): the max-button value remains ≤ rawNet even
after the cap drifts down.

* Tighten review comments and align param naming with codebase

Self-review pass on the open PR. Three small things:

- Rename the function param `reservePPM` to `reserveContribution`. The
  rest of utils/ and the PositionQuery type consistently call this
  field `reserveContribution` (the contract's storage name). The PPM
  unit is implied; no need to encode it in the param name and break
  the convention.
- Replace the line-number references in two BorrowedManageSection
  comments (\"on line 196\", \"line 150-160\") with branch names. The
  numbers go stale on every unrelated edit; the branch labels stay
  meaningful.
- Collapse the second `test.describe` block into the existing one.
  Both describe the same pure helper, splitting them only obscures
  that the race-regression test exercises the same code path.
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.

1 participant