Skip to content

fix(#991): add Ed25519 signature verification and replay protection to bridge_stub - #1074

Merged
Ceejaytech25 merged 1 commit into
ceejaylaboratory:mainfrom
giftben1763-ui:fix/991-bridge-ed25519-replay-protection
Sep 2, 2026
Merged

Ceejaytech25 merged 1 commit into
ceejaylaboratory:mainfrom
giftben1763-ui:fix/991-bridge-ed25519-replay-protection

Conversation

@giftben1763-ui

Copy link
Copy Markdown
Contributor

Summary

Fixes contracts/bridge_stub/src/lib.rs which accepted cross-chain mint messages without verifying cryptographic signatures, allowing anyone to mint tokens without relayer authorization.

Changes

contracts/bridge_stub/src/lib.rs

  • Storage: Added RelayerKey (Ed25519 public key) to DataKey enum
  • initialize(): Now accepts a relayer_key: BytesN<32> parameter and stores it
  • mint(): Now requires:
    • message_hash: BytesN<32> — the canonical hash of the message being processed
    • signature: BytesN<64> — relayer's Ed25519 signature over message_hash
    • Verifies signature via env.crypto().ed25519_verify() — reverts on invalid signature
    • Records message_hash in persistent storage to prevent replay attacks
  • Replay hash: Uses the caller-supplied message_hash (covering all message fields) rather than just a hash of the recipient address
  • Added unit tests:
    • test_mint_with_valid_signature
    • test_mint_with_invalid_signature_is_rejected
    • test_mint_with_signature_for_different_message_is_rejected
    • test_replay_attack_is_prevented
    • test_different_message_hashes_are_each_processed_once
    • test_unauthorized_relayer_is_rejected

Security Impact

Without this fix, any address could call mint() and receive tokens. The Ed25519 check ensures only the authorized relayer can authorize inbound transfers.

Closes #991

…lay protection to bridge_stub

- Add RelayerKey (BytesN<32>) storage key for the Ed25519 public key
- initialize() now accepts relayer_key: BytesN<32> parameter
- mint() verifies relayer Ed25519 signature over message_hash before processing
- mint() records message_hash in persistent storage after first execution
- Subsequent submissions of the same hash panic with 'message already processed'
- set_relayer() updated to also rotate the relayer key
- Add is_processed() view helper
- Add BridgeContractClient mint signature updated to include hash + sig args
- Add ed25519-dalek dev-dependency to Cargo.toml
- Add unit tests:
  - test_mint_with_valid_signature
  - test_mint_with_invalid_signature_is_rejected
  - test_mint_with_signature_for_different_message_is_rejected
  - test_replay_attack_is_prevented
  - test_different_message_hashes_are_each_processed_once
  - test_unauthorized_relayer_is_rejected

Closes ceejaylaboratory#991
@drips-wave

drips-wave Bot commented Aug 27, 2026

Copy link
Copy Markdown

@giftben1763-ui Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Ceejaytech25

Copy link
Copy Markdown
Contributor

Nice implementation, LGTM!

@Ceejaytech25
Ceejaytech25 merged commit 97f10ef into ceejaylaboratory:main Sep 2, 2026
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.

[Soroban] Implement cross-chain bridge stub signature verification in Bridge contract

2 participants