diff --git a/AGENTS.md b/AGENTS.md index 6ab44e82..eb3f13b3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -156,6 +156,11 @@ When touching transaction and position flows, validation MUST include all releva 21. **Modal UX integrity**: transaction-modal help/fee tooltips must render above modal layers via shared tooltip z-index chokepoints, and per-flow input mode toggles (for example target LTV vs amount) must persist through shared settings across modal reopen. 22. **Chain-scoped identity integrity**: all market/token/route identity checks must be chain-scoped and use canonical identifiers (`chainId + market.uniqueKey` or `chainId + address`), including matching, dedupe keys, routing, and trust/allowlist gates. 23. **Bundler residual-asset integrity**: any flash-loan transaction path that routes assets through Bundler/adapter balances (Bundler V2, GeneralAdapter, ParaswapAdapter) must end with explicit trailing sweeps of both loan and collateral tokens to the intended recipient across leverage/deleverage and swap/ERC4626 paths, and must keep execute-time slippage bounds consistent with quote-time slippage settings. +24. **Swap execution-field integrity**: for Velora/Paraswap routes, hard preview and execution guards must validate execution-authoritative fields only (trusted target, exact sell amount, min-out / close floor, token identities). Do not block flows on echoed route metadata such as quoted source or quoted destination amounts when calldata checks already enforce the executable bounds. +25. **Deterministic flash-loan asset floors**: when a no-swap ERC4626 redeem/withdraw leg is the source of flash-loan repayment assets, its execute-time minimum asset bound must be at least the flash-loan settlement amount itself; do not apply swap-style slippage floors that allow the callback to under-return assets and fail only at final flash-loan settlement. +26. **Deterministic ERC4626 quote/execution matching**: when a no-swap ERC4626 leverage leg uses vault previews, the execute-time operation must match the preview semantics exactly: `previewDeposit` should map to exact-asset deposit with the quoted share floor, and `previewMint` should map to exact-share mint with the quoted asset cap. Do not reuse swap-style slippage floors on either path. +27. **Transaction-tracking preflight integrity**: do not call `tracking.start(...)` until all synchronous preflight validation for the flow has passed (account, route, quote, input, fee viability). Once tracking has started, execution helpers must either complete successfully or throw so the caller can finish the lifecycle with exactly one `tracking.complete()` or `tracking.fail()`. +28. **Close-route collateral handoff integrity**: when a deleverage projection derives an exact close-bound collateral amount for full-repay-by-shares, route-specific executors must receive and use that quote-derived close bound explicitly for withdraw/redeem steps instead of relying on the raw user input amount. Any remaining collateral must be returned through the dedicated post-close withdraw/sweep path. ### REQUIRED: Regression Rule Capture diff --git a/app/tools/page.tsx b/app/tools/page.tsx index 998b78c2..c4eff89c 100644 --- a/app/tools/page.tsx +++ b/app/tools/page.tsx @@ -12,7 +12,7 @@ import { useMorphoAuthorization } from '@/hooks/useMorphoAuthorization'; import { useStyledToast } from '@/hooks/useStyledToast'; import { toUserFacingTransactionErrorMessage } from '@/utils/transaction-errors'; import { getBundlerV2, MONARCH_TX_IDENTIFIER } from '@/utils/morpho'; -import { getNetworkName, SupportedNetworks } from '@/utils/networks'; +import { getNetworkName, type SupportedNetworks } from '@/utils/networks'; import NetworkFilter from '@/features/markets/components/filters/network-filter'; export default function ToolsPage() { @@ -159,14 +159,16 @@ export default function ToolsPage() { }) + MONARCH_TX_IDENTIFIER) as `0x${string}`, value: 0n, chainId: selectedChainId, - }).catch((error: unknown) => { - const userFacingMessage = toUserFacingTransactionErrorMessage(error, 'Failed to submit Bundler V2 asset sweep.'); - if (userFacingMessage !== 'User rejected transaction.') { - toast.error('Asset sweep failed', userFacingMessage); - } - }).finally(() => { - setIsSweepConfirmModalOpen(false); - }); + }) + .catch((error: unknown) => { + const userFacingMessage = toUserFacingTransactionErrorMessage(error, 'Failed to submit Bundler V2 asset sweep.'); + if (userFacingMessage !== 'User rejected transaction.') { + toast.error('Asset sweep failed', userFacingMessage); + } + }) + .finally(() => { + setIsSweepConfirmModalOpen(false); + }); }; const getInputClassName = () => { @@ -277,9 +279,7 @@ export default function ToolsPage() { Executes via Bundler V2 multicall on the selected network: erc20Transfer(asset, yourWallet, maxUint256).

-

- ⚠️ This transfers only what Bundler V2 already holds for the asset address. -

+

⚠️ This transfers only what Bundler V2 already holds for the asset address.

@@ -292,7 +292,10 @@ export default function ToolsPage() { />
-
@@ -360,7 +361,10 @@ export default function ToolsPage() { -