fix: Keep non-transferable MPT loan fees off the broker owner - #8152
fix: Keep non-transferable MPT loan fees off the broker owner#8152tyalymov wants to merge 3 commits into
Conversation
LoanPay sent the management fee to the broker owner even after the issuer cleared lsfMPTCanTransfer. Payment rejects that hop with tecNO_AUTH. Under fixCleanup3_4_0 the fee goes to the cover pool instead. Vault repayment still succeeds, as CoverWithdraw does after fixCleanup3_2_0. Co-authored-by: Cursor <cursoragent@cursor.com>
Name the cover/freeze/auth gate and return isTesSuccess from canTransfer instead of a nested TER check. Drop the comment on the untouched send. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
There was a problem hiding this comment.
The change adds an MPT-transferability check to LoanPay's broker-fee routing, gated by fixCleanup3_4_0, so that a Dynamic MPT whose issuer clears lsfMPTCanTransfer falls back to the cover/pseudo-account path instead of crediting the broker owner directly. The boolean refactor (cannotSendFeeToOwner) is logically equivalent to the prior condition, the new canTransfer check correctly uses accountID_ (a non-issuer holder, mirroring the borrower-side Payment check) as the transfer-check source, and dst=brokerOwner naturally lets issuer-owner cases succeed. IOU/XRP routing is untouched since the check is gated on asset.holds(). New tests exercise both the pre- and post-amendment behavior, verifying vault repayment still succeeds while fee routing differs, and use a documented ledger-poking technique consistent with existing test patterns in this file. I did not find a correctness, security, or consistency issue in the diff that meets the bar for flagging.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
High Level Overview of Change
LoanPaycredited the broker owner even when the vault MPT hadlsfMPTCanTransfercleared.Paymentalready rejects that hop withtecNO_AUTH. UnderfixCleanup3_4_0the fee uses the existing cover fallback. Repayment to the vault is unchanged, matching the CoverWithdraw recovery path.Context of Change
accountSendMultidoes not enforce MPT transferability.LoanBrokerCoverDepositcallscanTransferbefore sending.LoanBrokerCoverWithdrawandVaultWithdrawonly skip it with an explicit, amendment-gated waiver afterfixCleanup3_2_0.LoanPayhad neither.sendBrokerFeeToOwneralready falls back to the broker pseudo-account when cover is low, the owner is deep-frozen, or StrongAuth fails. Transferability was missing from that list, so a Dynamic MPT whose issuer later clearedlsfMPTCanTransferstill paid the owner.Repayment (borrower to vault, or the cover fallback) is a recovery path: blocking it would let an issuer halt servicing of every outstanding loan by clearing one flag. The MPT invariant already treats
ttLOAN_PAYthat way afterfixCleanup3_2_0. This change only stops the owner fee.IOU routing is unchanged. The new check runs only for MPT assets.
API Impact
libxrplchange (any change that may affectlibxrplor dependents oflibxrpl)The consensus result of
LoanPaychanges underfixCleanup3_4_0when the vault asset is a non-transferable MPT and the broker owner is not the issuer: the fee is credited to cover instead of the owner.Test Plan
LoanPaycases for a vault MPT withlsfMPTCanTransfercleared after origination:fixCleanup3_4_0: ordinaryLoanPaysucceeds, the vault is repaid, the fee goes to cover, a holder-to-holderPaymentstill failstecNO_AUTH.