myXRP
GPT

Contract audit · 컨트랙트 감사

GPT

gpt-5.6-sol-medium

3 October 2026 · MyXRPBridge on Flare

Executive Summary

MyXRPBridge is a compact, non-custodial Solidity bridge on Flare mainnet. It accepts FXRP and mints an equal quantity of myXRP. A user can burn myXRP to recover the same nominal quantity of FXRP.

The public site also describes a custodial desk and a custodial cabinet. Those are a different object from this contract. This letter reviews only MyXRPBridge. On the contract, a user locks FXRP and a burn returns the same FXRP in that transaction. There is no operator key on the contract. The cabinet credit is a desk ledger entry. It is not a function of this bytecode. The heading “Why myXRP is custodial — on purpose” on the security page names the desk. It does not rename this bridge.

The reviewed source contains:

At reference block 71,254,525, the contract held 25.000000 FXRP against a total supply of 25.000000 myXRP, giving exact nominal 1:1 collateralization at that block.

No critical or high-severity issue was identified. The principal residual risk is dependence on the separately upgradeable FXRP token.

Scope

ItemValue
ContractMyXRPBridge
SourceMyXRPBridge.sol
NetworkFlare mainnet
Chain ID14
Address0x14b9DD90edaAff6527c1b168550B3FAA15b9F6AF
UnderlyingFXRP
FXRP address0xAd552A648C74D49E10027AB8a618A3ad4901c5bE
Solidity version^0.8.20

The review covered the supplied Solidity source and read-only calls to the deployed addresses. A reproducible source-to-runtime-bytecode build comparison was not performed.

Live Chain Facts

Read-only calls returned the following values:

PropertyResult
name()myXRP
symbol()myXRP
decimals()6
underlying()0xAd552A648C74D49E10027AB8a618A3ad4901c5bE
maxAssets()10,000,000.000000 FXRP
totalSupply()25.000000 myXRP
room()9,999,975.000000 FXRP
OPENS_AT()1790780400
Opening time30 September 2026, 15:00:00 UTC
FXRP held by bridge25.000000 FXRP

The opening timestamp had elapsed by the audit date. Deposits were therefore enabled, subject to the fixed ceiling and successful FXRP transfer.

The bridge address contains deployed runtime code. Its ERC-1967 implementation slot was zero at reference block 71,254,562, consistent with a direct, non-proxy deployment.

Architecture and Invariants

The intended accounting invariant is:

FXRP held by bridge >= totalSupply of myXRP

Each unit uses six decimals. Depositing one FXRP unit mints one myXRP unit; withdrawing one myXRP unit returns one FXRP unit.

The contract has no method that:

The ceiling applies to current totalSupply, not lifetime deposits. A withdrawal reduces supply and consequently restores deposit room.

Function-by-Function Review

constructor(address fxrp, uint256 maxAssets_)

Sets the immutable FXRP token and deposit ceiling.

It rejects:

Both values become immutable after deployment.

name(), symbol(), and decimals()

Constant metadata getters returning:

OPENS_AT()

Returns the fixed opening timestamp. There is no method to modify it.

underlying()

Returns the immutable FXRP contract address.

maxAssets()

Returns the immutable maximum outstanding myXRP supply.

totalSupply()

Returns the current myXRP supply. Supply increases only after a successful deposit and decreases during withdrawal.

balanceOf(address account)

Returns an account’s myXRP balance.

allowance(address owner, address spender)

Returns the quantity a spender may transfer from an owner.

room()

Returns zero when supply has reached the ceiling. Otherwise, it returns:

maxAssets - totalSupply

The subtraction is guarded by the preceding comparison.

deposit(uint256 amount)

The function:

1. Enters the reentrancy guard. 2. Requires the opening timestamp to have elapsed. 3. Rejects zero. 4. Rejects deposits that would exceed maxAssets. 5. Calls FXRP transferFrom to move the requested quantity into the bridge. 6. Increases totalSupply. 7. Credits the caller with an equal quantity of myXRP. 8. Emits Transfer from the zero address and Deposit.

State accounting occurs only after transferFrom returns successfully. A revert rolls back the complete transaction.

The caller must approve the bridge at the FXRP contract before depositing.

withdraw(uint256 amount)

The function:

1. Enters the reentrancy guard. 2. Rejects zero. 3. Verifies the caller’s myXRP balance. 4. Verifies that the bridge reports enough FXRP liquidity. 5. Debits the caller. 6. Reduces totalSupply. 7. Emits a burn-style Transfer. 8. Transfers the same quantity of FXRP to the caller. 9. Emits Withdraw.

If the FXRP transfer fails or reverts, all preceding state changes and events are reverted atomically.

Only the account owning the myXRP being burned can invoke this withdrawal path.

approve(address spender, uint256 amount)

Sets the caller’s allowance for a spender and emits Approval.

This implements conventional ERC-20 allowance replacement semantics.

transfer(address to, uint256 amount)

Moves myXRP from the caller to another nonzero address.

It rejects:

Zero-value transfers are permitted.

transferFrom(address from, address to, uint256 amount)

Allows an approved spender to transfer myXRP.

Finite allowances are reduced by the transferred amount. An allowance equal to uint256.max is treated as unlimited and is not reduced.

The function does not itself withdraw FXRP. A spender can transfer approved myXRP into an address it controls and subsequently redeem it from that address.

_transfer(address from, address to, uint256 amount)

Internal balance-transfer logic. It checks the recipient and source balance, performs arithmetic after establishing the source balance bound, and emits Transfer.

Self-transfers preserve the account’s final balance.

nonReentrant

Protects deposit and withdraw from nested execution. This is relevant because both functions call the external FXRP contract.

Who Can Move Funds

FXRP held by MyXRPBridge

The reviewed bridge source provides only one outbound FXRP path: withdraw.

A caller must hold and burn an equal amount of myXRP. There is no owner, operator, rescue address, administrator, or arbitrary FXRP transfer function in MyXRPBridge.

myXRP balances

A myXRP owner can:

An approved spender can move myXRP through transferFrom. Once the spender controls those tokens, it can redeem them normally.

External FXRP authority

MyXRPBridge cannot prevent actions implemented by the FXRP token itself. The live FXRP address resolves through a nonzero ERC-1967 implementation slot, meaning its behavior can be changed through FXRP’s own governance and authorization system.

Residual Risk in FXRP

The bridge’s solvency and availability depend on FXRP continuing to behave as expected.

Relevant risks include:

MyXRPBridge checks the Boolean return value of transfer and transferFrom, but deposit does not measure the bridge’s FXRP balance before and after the transfer. If FXRP were changed to deduct a transfer fee while still returning true, the bridge could mint more myXRP than the FXRP actually received.

At the reference block, this condition was not present: the bridge’s 25.000000 FXRP balance exactly matched its 25.000000 myXRP supply.

Findings Summary

SeverityCount
Critical0
High0
Medium1
Low2
Informational2

Detailed Findings

IDSeverityFindingStatus
M-01MediumSolvency and redemption depend on the upgradeable FXRP tokenOpen external dependency
L-01LowDirect FXRP transfers do not mint myXRP and cannot be recovered through a rescue functionBy design
L-02LowmyXRP transferred directly to the bridge address becomes inaccessibleBy design
I-01InformationalAllowance replacement has the conventional ERC-20 transaction-ordering riskAcknowledged standard behavior
I-02InformationalExact source-to-runtime-bytecode equivalence was not reproduced a second timeVerification limitation

M-01 — Upgradeable FXRP Is a Solvency and Availability Dependency

MyXRPBridge’s underlying address is immutable, but the FXRP address itself resolves through an ERC-1967 implementation slot.

Consequently, MyXRPBridge cannot guarantee that future FXRP behavior will retain the transfer properties assumed by its accounting. Pausing, restrictions, balance-changing privileged operations, or fee-charging transfers could impair deposits, withdrawals, or collateralization.

The most direct accounting concern is that deposit mints the requested amount after a successful Boolean return without confirming the amount actually received.

Recommendation: Continuously monitor the FXRP implementation address, upgrade events, bridge FXRP balance, and the relationship between FXRP balance and myXRP supply. Any future bridge version should compare pre-transfer and post-transfer balances and require the received amount to equal the requested amount.

L-01 — Direct FXRP Transfers Are Not Deposits

Sending FXRP directly to the bridge address does not call deposit, does not mint myXRP, and does not credit the sender.

Because there is no rescue function, directly transferred surplus FXRP cannot be specifically recovered by its sender.

Recommendation: Users and integrations should call deposit after approving FXRP rather than transferring FXRP directly.

L-02 — myXRP Sent to the Bridge Address Is Inaccessible

The bridge can hold myXRP like any address, but it has no function that invokes its own withdraw method or transfers its myXRP balance elsewhere.

myXRP sent directly to the bridge address therefore becomes inaccessible, while the corresponding FXRP remains locked.

Recommendation: Interfaces and integrations should reject or warn against selecting the bridge itself as a myXRP transfer recipient.

I-01 — Allowance Replacement Ordering

approve replaces an existing allowance directly. As with conventional ERC-20 approval, a spender may use an existing allowance before a pending replacement transaction is confirmed and then use the replacement allowance afterward.

Recommendation: When changing a nonzero allowance, first set it to zero and wait for confirmation before setting the new amount, or use uint256.max only for deliberately trusted integrations.

I-02 — Bytecode Equivalence Limitation

The live getter results, deployment shape, immutable values, and runtime behavior examined through read-only calls were consistent with the supplied source. However, an exact compiler-settings reconstruction and byte-for-byte comparison was outside this review.

Recommendation: Publish compiler version, optimizer configuration, constructor arguments, and verified source metadata sufficient for reproducible compilation.

Conclusion

MyXRPBridge has a narrow design and a small attack surface. The supplied source provides fixed 1:1 minting and redemption, a hard supply ceiling, reentrancy protection, and no bridge-level privileged fund-moving authority.

At the reference block, the contract was nominally fully collateralized, with 25.000000 FXRP held against 25.000000 myXRP outstanding. No critical or high-severity issue was identified.

The security conclusion remains conditional on the FXRP token preserving compatible transfer behavior and the bridge’s FXRP balance remaining at least equal to myXRP supply.

This is a technical opinion on one contract, not a guarantee and not a statement about any company.