0068 XLS-68d: Sponsored Fees and Reserves #196
Replies: 4 comments 11 replies
-
|
Out of curiosity, wouldn't it be better if account x could submit a signed transaction on behalf account y so account y would bear the txn cost. |
Beta Was this translation helpful? Give feedback.
-
|
Does the sponsored account itself not require 10XRP for account reserves? If 10XRP is not required, then the new Account Reserve Calculation should subtract 1 acctReserve if the AccountRoot has |
Beta Was this translation helpful? Give feedback.
-
|
Currently a PriceOracle object requires an incremental reserve of 1 or 2. If an object with such a dynamic incremental reserve increases its reserve requirement from 1 to 2 (object update), is it necessary to specify a Sponsor field to the txn? |
Beta Was this translation helpful? Give feedback.
-
|
If a trust line is automatically created when an offer you created is executed, is it possible to have someone else sponsor it? How? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Sponsored Fees and Reserves
Abstract
As the blockchain industry grows, many projects want to be able to build on the blockchain, but abstract away the complexities of using the blockchain - users don't need to submit transactions or deal with transaction fees themselves, they can just pay the platform to handle all that complexity (though, of course, the users still control their own keys).
Some projects also want to onboard users more easily, allowing users to create accounts without needing to pay for their own account reserve or needing to gift accounts free XRP to cover the reserve (this could get rather expensive if it is exploited).
In order to handle these sorts of use-cases, this proposal adds a process for users to maintain control over their keys and account, but to have another account (e.g. a platform) submit the transaction and pay the transaction fee and/or reserves on their behalf. This proposal supports both account and object reserves.
Similar features on other chains are often called "sponsored transactions", "meta-transactions", or "relays".
1. Overview
Accounts can include signatures from sponsors in their transactions that will allow the sponsors to pay the transaction fee for the transaction, and/or the reserve for any accounts/objects created in the transaction.
We propose modifying one ledger object and creating one new transaction type:
AccountRootledger objectSponsorTransfertransaction typeThe common fields for all ledger objects and all transactions will also be modified.
In addition, there will be a modification to the
account_objectsRPC method, and a new RPC method calledaccount_sponsoring.This feature will require an amendment, tentatively titled
featureSponsor.1.1. Terminology
1.2. The Sponsorship Flow
In this scenario, the sponsor, Spencer, wants to pay the transaction fee and/or reserve for the sponsee Alice's transaction.
1.3. Recouping a Sponsored Object Reserve
In this scenario, the sponsor, Spencer, would like to re-obtain the reserve that is currently trapped due to his sponsorship of Alice's object.
Spencer can submit a
SponsorTransfertransaction, which allows him to pass the onus of the reserve back to Alice, or pass it onto another sponsor.1.4. Recouping a Sponsored Account Reserve
In this scenario, the sponsor, Spencer, would like to retrieve his reserve from sponsoring Alice's account.
There are two ways in which he could do this:
AccountDeletetransaction, which will send all remaining funds in the account back to Spencer.SponsorTransfertransaction to either remove sponsorship or transfer it to the new provider.2. On-Ledger Objects: Common Fields
2.1. Fields
As a reference, here are the fields that all ledger objects currently have:
LedgerIndexstringHash256LedgerEntryTypestringUInt16FlagsnumberUInt16We propose this additional field:
SponsorAccountstringAccountID2.1.1.
SponsorAccountThe
SponsorAccountis the sponsor that is paying the reserve for this ledger object.3. On-Ledger Object:
AccountRoot3.1. Fields
As a reference, here are the fields that the
AccountRootledger object currently has.AccountstringAccountIDAccountTxnIDstringHash256AMMIDstringHash256BalancestringAmountBurnedNFTokensnumberUInt32DomainstringBlobEmailHashstringHash128FirstNFTokenSequencenumberUInt32LedgerEntryTypestringUInt160x0061, mapped to the stringAccountRoot, indicates that this is anAccountRootobject.MessageKeystringBlobMintedNFTokensnumberUInt32NFTokenMinterstringAccountIDOwnerCountnumberUInt32PreviousTxnIDstringHash256PreviousTxnLgrSeqnumberUInt32RegularKeystringAccountIDSequencenumberUInt32TicketCountnumberUInt32TickSizenumberUInt8TransferRatenumberUInt32WalletLocatorstringHash256WalletSizenumberUInt32We propose these additional fields:
SponsorAccountstringAccountIDSponsoredOwnerCountnumberUInt32SponsoringOwnerCountnumberUInt32SponsoringAccountCountnumberUInt323.1.1.
SponsorAccountThe
SponsorAccountfield is already added in the ledger common fields (see section 2.1.1), but it has some additional rules associated with it on theAccountRootobject.This field is included if the account was created with a sponsor paying its account reserve. If this sponsored account is deleted, the destination of the
AccountDeletetransaction must equalSponsorAccount, so that the sponsor can recoup their fees.Note: The
Destinationfield ofAccountDeletewill still work as-is if the account is not sponsored, where it can be set to any account.3.1.2.
SponsoredOwnerCountThis is the number of objects the account owns that are being sponsored by a sponsor.
3.1.3.
SponsoringOwnerCountThis is the number of objects the account is sponsoring the reserve for.
3.1.4.
SponsoringAccountCountThis is the number of accounts that the account is sponsoring the reserve for.
3.2. Account Reserve Calculation
The existing reserve calculation is:
The total account reserve should now be calculated as:
4. Transactions: Common Fields
4.1. Fields
As a reference, here are the fields that all transactions currently have.
We propose these modifications:
SponsorobjectSTObject4.1.1.
SponsorThe
Sponsorinner object contains all of the information for the sponsorship happening in the transaction.The fields contained in this object are:
AccountstringAccountIDFlagsnumberUInt16SigningPubKeystringSTBlobSignaturestringSTBlobSignersarraySTArray4.1.1.1.
AccountThe
Sponsor.Accountfield represents the sponsor.This field will be a signing field (it will be included in transaction signatures).
4.1.1.2.
FlagsThe
Flagsfield allows the user to specify which sponsorship type(s) they wish to participate in. At least one flag must be specified if theSponsorfield is included in a transaction.There are two flag values that are supported:
0x00000001:tfSponsorFee, sponsoring (paying for) the fee of the transaction.0x00000002:tfSponsorReserve, sponsoring the reserve for any objects created in the transaction.This field will be a signing field (it will be included in transaction signatures).
4.1.1.3.
SigningPubKeyandSignatureThese fields are included if the sponsor is signing with a single signature (as opposed to multi-sign). This field contains a signature of the transaction from the sponsor, to indicate their approval of this transaction. All signing fields must be included in the signature, including
Sponsor.AccountandSponsor.Flags.Either
SignatureorSignersmust be included in the final transaction.There will be no additional transaction fee required for the use of the
Signaturefield.Signaturewill not be a signing field (it will not be included in transaction signatures, though it will still be included in the stored transaction).4.1.1.4.
SignersThis field contains an array of signatures of the transaction from the sponsor,'s signers to indicate their approval of this transaction. All signing fields must be included, including
Sponsor.AccountandSponsor.Flags.Either
SignatureorSignersmust be included in the final transaction.If the$(\#signatures+1)*base\textunderscore fee$ .
Signersfield is necessary, then the total fee of the transaction will be increased, due to the extra signatures that need to be processed. This is similar to the additional fees for multisigning. The minimum fee will beThe total fee calculation for signatures will now be$( 1+\# tx.Signers + \# tx.Sponsor.Signers) * base\textunderscore fee$ .
This field will not be a signing field (it will not be included in transaction signatures, though it will still be included in the stored transaction).
4.2. Failure Conditions
4.2.1. General Failures
Sponsor.Signatureis invalidSponsor.Signersis invalid (the signer list isn't on the account, quorum isn't reached, or signature(s) are invalid)4.2.2. Fee Sponsorship Failures
4.2.3. Reserve Sponsorship Failures
tecINSUFFICIENT_RESERVE)4.3. State Changes
4.3.1. Fee Sponsorship State Changes
The fee will be deducted from the sponsor instead of the sponsee. That's it.
4.3.2. Reserve Sponsorship State Changes
Any account/object that is created as a part of the transaction will have a
Sponsorfield.The sponsor's
SponsoringOwnerCountfield will be incremented by the number of objects that are sponsored as a part of the transaction, and theSponsoringAccountCountfield will be incremented by the number of new accounts that are sponsored as a part of the transaction.The sponsee's
SponsoredOwnerCountfield will be incremented by the number of objects that are sponsored as a part of the transaction.The
SponsoredOwnerCount,SponsoringOwnerCount, andSponsoringAccountCountfields will be decremented when those objects/accounts are deleted.4.4. Transactions that cannot be sponsored
All transactions (other than pseudo-transactions) may use the
tfSponsorFeeflag, since they all have a fee.However, some transactions will not support the
tfSponsorReserveflag.Batch(from XLS-56d)Batchto support that flag. The sub-transactions should usetfSponsorReserveinstead.EnableAmendment,SetFee, andUNLModify)Also, many transactions, such as
AccountSet, will have no change in output when using thetfSponsorReserveflag, if they do not create any new objects or accounts.5. Transaction:
SponsorTransferThis transaction transfers a sponsor relationship for a particular ledger object's object reserve. The sponsor relationship can either be passed on to a new sponsor, or dissolved entirely (with the sponsee taking on the reserve). Either the sponsor or sponsee may submit this transaction at any point in time.
5.1. Fields
TransactionTypestringUInt16AccountstringAccountIDLedgerIndexstringUInt256SponsorobjectSTObject5.1.1.
LedgerIndexThis field should be included if this transaction is dealing with sponsored object, rather than on a sponsored account. This field indicates which object the relationship is changing for.
If it is not included, then it refers to the account sending the transaction.
5.1.2.
SponsorThe
Sponsorfield is already added in the ledger common fields (see section 4.1.1), but it has some additional rules associated with it on theSponsorTransfertransaction.In this case, if
Sponsoris included with thetfSponsorReserveflag, then the reserve sponsorship for the provided object will be transferred to theSponsor.Accountinstead of passing back to the ledger object's owner.If there is no
Sponsorfield, or if thetfSponsorReserveflag is not included, then the burden of the reserve will be passed back to the ledger object's owner (the former sponsee).5.2. Ending the Sponsorship for a Sponsored Ledger Object
A sponsored ledger object will have the
Sponsorfield attached to it. Ending the sponsor relationship for a sponsored ledger object requires theLedgerIndexparameter, to specify which ledger object.Two accounts are allowed to submit a
SponsorTransferrelationship to end the sponsor relationship for a sponsored ledger object: either the sponsor for that object or the owner of that object (the sponsee).5.3. Migrating a Sponsorship to a New Account
A sponsorship can be migrated to a new account by including the
Sponsorfield with thetfSponsorReserveflag. This can be done for either a sponsored account or a sponsored ledger object.Two accounts are allowed to submit a
SponsorTransferrelationship to migrate the sponsor relationship: the sponsor or the sponsee.The sponsor will likely only rarely want to do this (such as if they are transferring accounts), but the sponsee may want to migrate if they change providers.
5.4. Failure Conditions
5.5. State Changes
Sponsorfield on the object is changed or deleted.SponsoringOwnerCount/SponsoringAccountCountdecremented by one.SponsoringOwnerCount/SponsoringAccountCountincremented by one.SponsoredOwnerCountwill be decremented by one.6. RPC:
account_objects6.1. Fields
The
account_objectsRPC method already exists on the XRPL. As a reference, here are the fields thataccount_objectscurrently accepts:accountstringdeletion_blockers_onlybooleanledger_hashstringledger_indexnumberorstringlimitnumbermarkeranytypestringWe propose this additional field:
sponsoredboolean6.2.
sponsoredIf this field is excluded, all objects, sponsored or not, will be included. If
sponsored == True, only sponsored objects will be included. Ifsponsored == False, only non-sponsored objects will be included.7. RPC:
account_sponsoringThe
account_sponsoringRPC method is used to fetch a list of objects that an account is sponsoring; namely, a list of objects where theSponsorAccountis the given account. It has a very similar API to theaccount_objectsmethod.accountstringdeletion_blockers_onlybooleantrue, the response only includes objects that would block this account from being deleted. The default isfalse.ledger_hashstringledger_indexnumberorstringlimitnumbermarkeranytypestringofferandescrow.8. Security
8.1. Security Axioms
Both the sponsee and the sponsor must agree to enter into a sponsor relationship. The sponsee must be okay with the sponsor handling the reserve, and the sponsor must be willing to take on that reserve. A signature from both parties ensures that this is the case.
A sponsor will never be stuck sponsoring an sponsee's account or object it doesn't want to support anymore, because it can submit a
SponsorTransfertransaction at any point.The sponsor's signature must always include the
AccountandSequencefields, to prevent signature replay attacks (where the sponsor's signature can be reused to sponsor an object or account that they did not want to sponsor).When sponsoring transaction fees, the sponsor must approve of the
Feevalue of the transaction, since that is the amount that they will be paying.When sponsoring reserves, the sponsor's signature must include any aspects of the transaction that involve a potential account/object reserve. This would include the
Destinationfield of aPaymenttransaction (and whether it is a new account) and theTicketSequencefield of aTicketCreatetransaction (since that dictates how manyTicketobjects are created, each of which results in one object reserve).A sponsee cannot take advantage of the generosity of their sponsor, since the sponsor must sign every transaction it wants to sponsor the ledger objects for. A sponsee also must not be able to change the sponsorship type that the sponsor is willing to engage in, as this could lock up to 500 of the sponsor's XRP (in the case of 250 tickets being created in one
TicketCreatetransaction).An axiom that is out of scope: the sponsee will not have any control over a sponsorship transfer. This is akin to a loanee having no control over a bank selling their mortgage to some other company, or a lender selling debt to a debt collection agency.
8.2. Signatures
Since a fee sponsorship must approve of the
Feefield, and a reserve sponsorship must approve of a broad set of transaction fields, the sponsor must always sign the whole transaction. This also avoids needing to have different sponsorship processes for different sponsorship types. This includes the non-signature parts of theSponsorobject (Sponsor.AccountandSponsor.Flags). The same is true for the sponsee's transaction signature; the sponsee must approve of the sponsor and sponsorship type.A sponsor's
Signaturecannot be replayed or attached to a different transaction, since the whole transaction (including theAccountandSequencevalues) must be signed.9. Invariants
An invariant is a statement, usually an equation, that must always be true for every valid ledger state on the XRPL. Invariant checks serve as a last line of defense against bugs; the
tecINVARIANT_FAILEDerror is thrown if an invariant is violated (which ideally should never happen).9.1. Tracking Owner Counts
A transaction that creates a ledger object either increments an account's
OwnerCountby 1 or increments two separate accounts'SponsoringOwnerCountandSponsoredOwnerCountby 1. The opposite happens when a ledger object is deleted.The equivalent also should happen with
SponsoringAccountCount.9.2. Balancing
SponsoredOwnerCountandSponsoringOwnerCountIn other words, the sum of all accounts'
SponsoredOwnerCounts must be equal to the sum of all accounts'SponsoringOwnerCounts. This ensures that every sponsored object is logged as being sponsored and also has a sponsor.10. Example Flows
Each example will show what the transaction will look like before and after both the sponsor and sponsee sign the transaction.
The unsigned transaction must be autofilled before it is passed to the sponsor to sign. Tooling can be updated to handle combining the sponsor and sponsee signatures, similar to helper functions that already exist for multisigning.
10.1. Fee Sponsorship
10.1.1. The Unsigned Transaction
Details
10.1.2. The Signed Transaction
Details
10.2. Account Sponsorship
The only way an account can be created is via a
Paymenttransaction. So the sponsor relationship must be initiated on thePaymenttransaction.10.2.1. The Unsigned Transaction
Details
10.2.2. The Signed Transaction
Details
10.3. Object Sponsorship
10.3.1. The Unsigned Transaction
Details
10.3.2. The Signed Transaction
Details
Appendix
Appendix A: FAQ
A.1: Does the sponsee receive any XRP for the reserve?
No, there is no XRP transfer in a sponsorship relationship - the XRP stays in the sponsor's account. The burden of the reserve for that object/account is just transferred to the sponsor.
A.2: What happens if you try to delete your account and you have sponsored objects?
If the account itself is sponsored, then it can be deleted, but the destination of the
AccountDeletetransaction (in other words, where the leftover XRP goes) must be the sponsor's account. This ensures that the sponsor gets their reserve back, and the sponsee cannot run away with those funds.If the sponsee still has sponsored objects, those objects will follow the same rules of deletion blockers. Whether or not they are sponsored is irrelevant.
If a sponsored object is deleted (either due to normal object deletion processes or, in the case of objects that aren't deletion blockers, because the owner account is deleted), the sponsor's reserve becomes available again.
A.3: What if a sponsor that is sponsoring a few objects wants to delete their account?
An account cannot be deleted if it is sponsoring any existing accounts or objects. They will need to either delete those objects (by asking the owner to do so) or use the
SponsorTransfertransaction to relinquish control of them.A.4: Does a sponsor have any powers over an object they pay the reserve for? I.e. can they delete the object?
No. If a sponsor no longer wants to support an object, they can always use the
SponsorTransfertransaction instead.A.5: What if a sponsee refuses to delete their account when a sponsor wants to stop supporting their account?
The sponsor will have the standard problem of trying to get ahold of a debtor to make them pay. They may be able to use
SponsorTransfertransaction to put the onus on the sponsee, though the sponsee would need to have enough XRP in their account to cover the reserve.A.6: What happens if the sponsor tries to
SponsorTransferbut the sponsee doesn't have enough funds to cover the reserve?If the sponsor really needs to get out of the sponsor relationship ASAP without recouping the value of the reserve, they can pay the sponsee the amount of XRP they need to cover the reserve. These steps can be executed atomically via a Batch transaction, to ensure that the sponsee can't do something else with the funds before the
SponsorTransfertransaction is validated.A.7: Would sponsored accounts carry a lower reserve?
No, they would still carry a reserve of 10 XRP at current levels.
A.8: Can an existing unsponsored ledger object/account be sponsored?
Yes, with the
SponsorTransfertransaction.A.9: Can a sponsored account be a sponsor for other accounts/objects?
No.
A.10: Can a sponsored account hold unsponsored objects, or objects sponsored by a different sponsor?
Yes, and yes.
A.11: What if I want different sponsors to sponsor the transaction fee vs. the reserve for the same transaction?
That will not be supported by this proposal. If you have a need for this, please provide example use-cases.
A.12: Won't it be difficult to add two signatures to a transaction?
This is something that good tooling can solve. It could work similarly to how multisigning is supported in various tools.
A.13. Why not instead do [insert some other design]?
See Appendix B for the alternate designs that were considered and why this one was preferred. If you have another one in mind, please describe it in the comments and we can discuss.
A.14: How is this account sponsorship model different from/better than XLS-23d, Lite Accounts?
A.15: How will this work for objects like trustlines, where multiple accounts might be holding reserves for it?
The answer to this question is still being explored. One possible solution is to add a second field,
Sponsor2, to handle the other reserve.A.16: How does this proposal work in conjunction with XLS-49d? What signer list(s) have the power to sponsor fees or reserves?
Currently, only the global signer list is supported. Another$2^{16}$ , since the $2^{32}$ , so there is room in the design for additional values that do not correlate to a specific transaction type.
SignerListIDvalue could be added to support sponsorship. Transaction values can only go up toTransactionTypefield is aUInt16, but theSignerListIDfield goes up toAppendix B: Alternate Designs
B.1: Add a
Sponsorto the accountThis design involved updating
AccountSetto allow users to add aSponsorto their account (with a signature from the sponsor as well). The sponsor would then sponsor every object from that account while the field was active, and either the sponsor or the account could remove the sponsorship at any time.This was a previous version of the spec, but it made more sense for the relationship to be specific to a transaction/transactions, to prevent abuse (the sponsor should decide what objects they want to support and what objects they don't want to support).
The current design also supports having different sponsors for different objects, which allows users to use a broad set of services and platforms, instead of being locked into one.
B.2: A Wrapper Transaction
There would be a wrapper transaction (tentatively named
Relay), similar toBatchin XLS-56d, that the sponsor would sign. It would contain a sub-transaction from the sponsee.It would look something like this:
TransactionTypestringUInt16AccountstringSTAccountFeestringSTAmountTransactionobjectSTTxThis was a part of a previous version of the spec (inspired by Stellar's sandwich transaction design for their implementation of sponsored reserves), but the existing design felt cleaner. From an implementation perspective, it's easier to have the fee payer as a part of the existing transaction rather than as a part of a wrapper transaction, since that info needs to somehow get passed down the stack. Also, while the wrapper transaction paradigm will be used in XLS-56d, they should be used sparingly in designs - only when necessary - as their flow is rather complicated in the
rippledcode.In addition, the signing process becomes complicated (as discovered in the process of developing XLS-56d). You have to somehow prevent the sponsor from submitting the as-is signed transaction to the network, without including it in the wrapper transaction.
B.3: A Create-Accept-Cancel Flow
The rough idea of this design was to have a new set of transactions (e.g.
SponsorCreate/SponsorAccept/SponsorCancel/SponsorFinish) where a sponsor could take on the reserve for an existing object.This design was never seriously considered, as it felt too complicated and introduced several new transactions. It also doesn't support adding a sponsor to the object at object creation time, which is a much smoother UX and never requires the owner/sponsee to hold enough XRP for the reserve.
Beta Was this translation helpful? Give feedback.
All reactions