fix(escrow): guard against self-escrow and arbiter collisions#32
Merged
abayomicornelius merged 9 commits intoJul 16, 2026
Merged
Conversation
EscrowForm's zod schema validated address format but never compared beneficiaryPublicKey to the connected wallet's own public key, letting a depositor name themselves as beneficiary with no locking guarantee.
EscrowForm had no way to compare beneficiaryPublicKey/arbiterPublicKey against the depositor's own address since it never received it as a prop. EscrowPage already has publicKey from useWallet, so thread it through.
Guards against a regression of the beneficiary === depositor hole described in StellarSend#23.
Adds cases for arbiter === depositor, arbiter === beneficiary, and a happy-path check that three distinct addresses still allow submit.
Contributor
Author
|
please review all ci passed |
The repo shipped eslint + typescript-eslint + react-hooks/react-refresh as devDependencies and an `npm run lint` script, but no .eslintrc ever existed, so `eslint .` failed outright with "couldn't find a configuration file" — the Lint CI check was failing on every push regardless of code changes.
Now that lint actually runs, clean up unused testing-library imports flagged by @typescript-eslint/no-unused-vars in existing test files.
Fixes the remaining no-unused-vars warnings surfaced by the newly added ESLint config (unused destructured state, icon imports, and recharts imports).
useWalletContext is intentionally co-located with WalletProvider; this is the standard pattern for context files and doesn't affect Fast Refresh in practice.
Contributor
Author
|
Good Job |
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.
Summary
Fixes #23.
EscrowForm's zod schema validated thatbeneficiaryPublicKeyandarbiterPublicKeywere individually well-formed Stellar addresses, but never cross-checked them against each other or the connected wallet's own public key. SincegetEscrowPermissionslets the beneficiary or arbiter release funds at any time before the unlock time, this allowed:Self-escrow: depositor sets themselves as beneficiary and can release to themselves immediately, defeating the locking guarantee.
No-op arbiter: arbiter set to the depositor's own address, or to the same address as the beneficiary, which collapses the three-party trust model.
EscrowFormnow accepts adepositorPublicKeyprop (the connected wallet's address) and the zod schema adds cross-field refinements:beneficiaryPublicKey !== depositorPublicKeyarbiterPublicKey !== depositorPublicKeyarbiterPublicKey !== beneficiaryPublicKeyEscrowPagepassespublicKeyfromuseWallet()intoEscrowForm.Submit stays disabled with an inline field error until the conflict is resolved.
Test plan
npx vitest run— 59/59 tests pass, including 4 new cases inEscrowForm.test.tsx(self-escrow rejected, arbiter === depositor rejected, arbiter === beneficiary rejected, valid distinct addresses submit successfully)npx tsc --noEmit— no errorsnpm run build— succeeds