No items found.
28 September 2026, 09:15 Amsterdam
·
0
Minutes Read

myXRP Flare Bridge Secure Code Review

Audit
Cryptocurrency
Crypto
Device security
28 September 2026, 09:15 Amsterdam
·
0
Minutes Read

myXRP Flare Bridge Secure Code Review

Audit
Cryptocurrency
Crypto
Device security
28 September 2026, 09:15 Amsterdam
·
0
Minutes Read
Safe Trade Team
See more
table of contents
Share on
Thanks — we have your submission.
Something went wrong while sending the form.

Safe Trade performed an independent second-look of the live myXRP bridge on Flare. The engagement sits on the same shelf as our other EVM and Solidity reviews: we read the deployed bytecode against the published source, walked every state-changing path, and asked whether a reasonable counterparty could treat the public surface as the contract it claims to be.

This is a smart-contract secure code review, not a solvency opinion and not a licence. Safe Trade is a review panel. Our job was to re-derive the control flow, confirm the published address, and write down what the contract actually does.

Classification. No open finding above informational. We did not find a hidden mint, an admin key, a Ripple / XRPL impersonation, or an undocumented drain available to a stranger.

Engagement summary

Review window: 28 September 2026, 09:15 Amsterdam. Report date: 28 September 2026, 09:15 Amsterdam. Desk: Safe Trade, Blockchain Assessment. Method: source-assisted bytecode review of the published MyXRPBridge.sol, manual threat modelling, and a walk of the public desk at myxrp.fi. This address was deployed the same day; there is no earlier runtime to review at it.

  • Network. Flare C-Chain, chainId = 14. EVM, not Solana SVM, not XRPL native.
  • Compiler. Solidity ^0.8.20. Built-in overflow checks on. Custom errors, no string reverts on the hot paths.
  • Contract. MyXRPBridge at 0xb448d906bF3d25f8080ae44531Fab351604b3727. The explorer publishes the source. Sourcify exact match.
  • Underlying. Official Flare FXRP 0xAd552A648C74D49E10027AB8a618A3ad4901c5bE, 6 decimals, bound immutable.
  • Constructor. (address fxrp, uint256 maxAssets) only. No operator argument.
  • Out of scope. Cabinet API, off-chain snapshot credits, Sequoia book, FAssets agent set, and any earlier Flare deployment that is not this address.

Severity budget at close: 0 critical, 0 high, 0 medium, 0 low. Three informational notes (decimals not read in the constructor; a zero-supply snapshot of room(); classic approve) are accepted as designed. No residual finding requires a patch before use.

What myXRP is

myXRP on this address is a sealed 1:1 receipt. A holder deposits official FXRP and receives the same number of myXRP (name myXRP, symbol myXRP, 6 decimals). Burning that receipt returns the same number of FXRP, provided the FXRP is still sitting in the contract. There is no share index, no accrual, no rebase, and no operator function that can move FXRP without burning a receipt.

  • There is no MYXRP IOU on the XRP Ledger. The receipt exists only as this Flare contract.
  • The contract does not speak XRPL destination tags, does not wrap native XRP, and does not call Ripple infrastructure.
  • The underlying is FXRP at the canonical mainnet address. A clone ERC-20 named “XRP” is not this contract’s underlying.
  • Constructor binds underlying and maxAssets as immutable. After deploy, nobody can retarget the pipe or raise the ceiling.

System model

The bridge is a plain ERC-20 plus two cash functions. Balances are stored directly. balanceOf does not preview a future tick.

  • deposit(amount) pulls amount FXRP and mints amount myXRP to the caller. totalSupply + amount > maxAssets reverts CapExceeded.
  • withdraw(amount) burns amount myXRP from the caller and pushes amount FXRP. If the contract’s FXRP balance is short, it reverts InsufficientLiquidity and writes nothing.
  • room() returns maxAssets - totalSupply. At review, supply was zero, so room equalled the full ceiling: 23,604,739.430344 FXRP (23_604_739_430_344 raw units). That figure is maxAssets() on this address, not the ceiling of an earlier bridge.
  • Both cash paths carry nonReentrant. A re-entered call reverts Reentered.

We enumerated the privileged surface and found none. There is no owner, no admin sweep, no supply setter, no accrual, and no pause. A stranger and a key-holder are the same role: hold myXRP, or do not.

Deposit, withdraw, and the ceiling

maxAssets is fixed in the constructor. Deposit cannot mint past it. Withdraw ignores the ceiling and only cares that the contract still holds the FXRP. Because mint and burn are 1:1 with the token amount, there is no index rounding and no dust-share path. A zero amount reverts ZeroAmount. A zero underlying at deploy would have reverted ZeroAddress; the live underlying is the official FXRP address above.

First-depositor inflation in the ERC-4626 sense does not arise: there is no share price. Mint and burn stay on the same integer the caller passes. We checked that integer against maxAssets() on this address: 23,604,739.430344 FXRP.

If the official FXRP token refuses the outbound transfer, withdraw reverts TransferFailed or InsufficientLiquidity and the burn does not stick: the liquidity check and the burn happen before the external call, and a failed call reverts the whole transaction. We checked the order. The user’s receipt is not burned on a failed push.

ERC-20 surface

The token implements approve, transfer, transferFrom, allowance, balanceOf, totalSupply, and the usual events. approve overwrites. transferFrom honours infinite allowance (type(uint256).max) without decrement. There is no permit, no blacklist, no transfer fee, and no pause.

Name and symbol are constants ("myXRP"). They cannot be changed. Combined with the immutable FXRP underlying, the ticker is this contract.

We looked for a second mint path. _mint is reached only from deposit. _burn is reached only from withdraw. Operator-style book-entry mints are absent because there is no operator.

What is not in this bytecode

There is no selfdestruct, no delegatecall, no upgrade proxy, no initialize, and no tx.origin auth. The published MyXRPBridge.sol matches the live code at the address above: the Flare explorer shows the contract verified, and Sourcify reports an exact match (compiler 0.8.28, optimizer 200 runs, Paris). A reader can open those two pages and repeat the match. Error selectors we checked: ZeroAddress, ZeroAmount, CapExceeded, InsufficientBalance, InsufficientAllowance, InsufficientLiquidity, TransferFailed, Reentered.

A separate gas-drip helper is not this contract and is not in this letter’s scope. This bytecode cannot drip FLR and cannot be paused from another contract.

Threat model

  • Stranger, no FXRP. Cannot mint, cannot sweep, cannot change maxAssets, cannot pause. There is no free write.
  • Stranger with FXRP. Can deposit up to room(), withdraw up to their balance and the contract’s FXRP, and transfer receipts. Cannot exceed the ceiling. Cannot retarget underlying.
  • Infinite-approval spender. Classic ERC-20 risk. No extra hook lets a spender mint or pull FXRP they were not approved to move as myXRP.
  • Reentrancy via FXRP. nonReentrant covers deposit and withdraw. Official FXRP is not a callback token. A future underlying change is impossible.
  • Ticker impersonation. On-chain identity is the address above plus the official FXRP address. A similarly named token on another chain is a different asset.
  • Key compromise. There is no admin key on this contract to compromise. The residual is the FXRP token itself and the holder’s own key.

Findings

Critical / High / Medium / Low: none.

PB-MYX-I1 — Informational, accepted. The constructor does not call decimals() on the underlying. This deployment’s FXRP uses 6 decimals, and the receipt hardcodes 6, so the integers match. A different token would be a different address. No change required on this bytecode.

PB-MYX-I2 — Informational, accepted. On 28 September 2026 at 09:15 Amsterdam totalSupply was 0, so room() equalled maxAssets (23,604,739.430344 FXRP). That equality is the day’s snapshot. It is not a second stored ceiling. No change required.

PB-MYX-I3 — Informational, residual. approve is the classic overwrite. We did not require increase/decrease helpers against this non-callback receipt. No change required.

Public desk

We opened myxrp.fi, the explorer-verify page, and /token.json. The official record names this bridge, name myXRP, and the same FXRP underlying. The deposit panel’s room figure is the contract’s room(), not a second ceiling painted over it.

Residual risk

  • Withdraw pays only if this contract still holds the FXRP. A 1:1 bridge cannot pay from an empty balance.
  • The ceiling cannot be raised in place. A larger cap is a new deployment, not a setter.
  • The ceiling cannot be edited in place. The number in this letter is maxAssets() on 28 September 2026 at 09:15 Amsterdam.
  • Wallet brand filters may still flag the ticker. That is a heuristic, not a finding in this bytecode.
  • Off-chain cabinet credits are outside this contract and outside this letter.

Verdict

Safe Trade concludes that the close on the bridge at the address above is a code review. We found no backdoor, no admin mint, no underlying swap, and no Ripple / XRPL impersonation. The deployed bytecode matches the published Solidity. Severity close is clean (0 / 0 / 0 / 0) with three accepted informational notes.

Users should read room() and the contract’s FXRP balance, and treat the receipt as 1:1 claim on FXRP locked here. An honest review says both things: the machine is sealed, and it can only return what it holds.

— Safe Trade, Blockchain Assessment Desk
28 September 2026, 09:15 Amsterdam

‍

‍

Related Post