Skip to content

Add fresh account check#1177

Merged
ebma merged 5 commits into
stagingfrom
add-fresh-account-check
May 29, 2026
Merged

Add fresh account check#1177
ebma merged 5 commits into
stagingfrom
add-fresh-account-check

Conversation

@ebma
Copy link
Copy Markdown
Member

@ebma ebma commented May 29, 2026

Adds checks to the register-ramp endpoint to ensure that the ephemeral accounts are unused.

ebma added 3 commits May 29, 2026 16:06
Reject registerRamp if any required ephemeral has on-chain history on a
route-relevant chain (non-zero nonce/balance on Substrate/EVM, or a
pre-existing Stellar account). Without this, the backend builds presigned
transactions assuming nonce 0 and the ramp halts mid-execution after
subsidies have already been spent.

Route-to-network mapping mirrors the offramp/onramp transaction-builder
dispatcher so only chains an ephemeral actually signs on are checked.
Fails closed on RPC errors (SERVICE_UNAVAILABLE) since freshness cannot
be presumed without on-chain data.
Add EphemeralNotFreshError and EphemeralFreshnessCheckError so partner
clients can distinguish stale-ephemeral failures from other registerRamp
errors and recover by retrying (the SDK regenerates ephemerals on every
call). Document the retry pattern in the SDK README.
Add F-068 to FINDINGS.md (Medium, fixed), extend the ephemeral-accounts
spec with invariant 9 + threat row + audit checklist item, and add
invariant 10 + threat row + checklist item to transaction-validation.
@ebma ebma requested a review from Copilot May 29, 2026 14:17
@netlify
Copy link
Copy Markdown

netlify Bot commented May 29, 2026

Deploy Preview for vortexfi ready!

Name Link
🔨 Latest commit d98a1c6
🔍 Latest deploy log https://app.netlify.com/projects/vortexfi/deploys/6a19a5ad2e3f3e000732b0b1
😎 Deploy Preview https://deploy-preview-1177--vortexfi.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@ebma ebma requested a review from a team May 29, 2026 14:17
@netlify
Copy link
Copy Markdown

netlify Bot commented May 29, 2026

Deploy Preview for vortex-sandbox ready!

Name Link
🔨 Latest commit d98a1c6
🔍 Latest deploy log https://app.netlify.com/projects/vortex-sandbox/deploys/6a19a5ad2e3f3e000732b0b5
😎 Deploy Preview https://deploy-preview-1177--vortex-sandbox.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds route-aware freshness validation for client-submitted ephemeral accounts during ramp registration, with SDK error types/docs and security-spec updates for finding F-068.

Changes:

  • Introduces validateEphemeralAccountsFresh() and route-to-network mapping for ephemeral checks.
  • Wires freshness validation into registerRamp before transaction preparation.
  • Adds SDK error parsing/documentation and updates security specs/findings.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
apps/api/src/api/services/ramp/ephemeral-freshness.ts Adds freshness network mapping and on-chain account checks.
apps/api/src/api/services/ramp/ephemeral-freshness.test.ts Adds unit coverage for mapping and freshness failures.
apps/api/src/api/services/ramp/ramp.service.ts Calls freshness validation during ramp registration.
packages/sdk/src/errors.ts Adds SDK freshness error classes and parser branches.
packages/sdk/README.md Documents recoverable freshness errors.
docs/security-spec/FINDINGS.md Adds F-068 as fixed and updates counts.
docs/security-spec/03-ramp-engine/transaction-validation.md Adds freshness validation requirement and checklist entry.
docs/security-spec/02-signing-keys/ephemeral-accounts.md Adds ephemeral freshness principle and mitigation note.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +211 to +228
async function assertEvmAccountFresh(address: string, network: EvmNetworks): Promise<void> {
let nonce: number;
try {
const client = EvmClientManager.getInstance().getClient(network);
nonce = await client.getTransactionCount({ address: address as `0x${string}` });
} catch (error) {
throw new APIError({
message: `Could not verify freshness of EVM ephemeral ${address} on ${network}: ${(error as Error).message}`,
status: httpStatus.SERVICE_UNAVAILABLE
});
}

if (nonce !== 0) {
throw new APIError({
message: `EVM ephemeral ${address} is not fresh on ${network} (nonce=${nonce}). A new, unused ephemeral account must be provided.`,
status: httpStatus.BAD_REQUEST
});
}

if (quote.inputCurrency === FiatToken.EURC) {
if (toNetwork === Networks.AssetHub) {
pushEvmDedup(result, Networks.Polygon);
Comment on lines +372 to +374
const freshnessCheckMatch = errorMessage.match(/^Could not verify freshness of (Substrate|EVM|Stellar) ephemeral (\S+)/);
if (freshnessCheckMatch) {
return new EphemeralFreshnessCheckError(errorMessage, freshnessCheckMatch[1] as EphemeralChain, freshnessCheckMatch[2]);
1. EVM freshness now checks both nonce AND balance (not just nonce),
   rejecting addresses that received native funds but never sent a tx.
2. Use sandbox-aware Polygon network (PolygonAmoy when sandboxEnabled)
   in the freshness mapping, matching the transaction builders.
3. Error middleware now only masks 500 messages in production, preserving
   503 SERVICE_UNAVAILABLE messages so the SDK can parse freshness errors.
Copilot finished work on behalf of ebma May 29, 2026 14:30
@ebma ebma merged commit 7a6cd3e into staging May 29, 2026
7 checks passed
@ebma ebma deleted the add-fresh-account-check branch May 29, 2026 14:49
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.

4 participants