Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Design]: Stacks Txn Sponsorship in sBTC-v1 #42

Closed
3 tasks done
AshtonStephens opened this issue Apr 8, 2024 · 7 comments
Closed
3 tasks done

[Design]: Stacks Txn Sponsorship in sBTC-v1 #42

AshtonStephens opened this issue Apr 8, 2024 · 7 comments
Assignees
Labels
clarity The clarity smart contracts. design making a design decision. sponsor api API that signs Stacks transactions for sponsorship.

Comments

@AshtonStephens
Copy link
Collaborator

AshtonStephens commented Apr 8, 2024

Completing the issue description and arriving at a conclusion is the deliverable of this issue.

Design - Stacks Txn Sponsorship in sBTC-v1

This ticket holds the practical details around implementing the Sponsoring of txn fees with proposal from stacks-network/stacks-core#4235 in sBTC-v1. This includes the sponsorship options as well as any implementation details required for it to be included smoothly.

In the research discussion #38 we concluded that a lean approach without a dynamic market would be the best path forward for sBTC-v1, with the potential for a third party to create a dynamic market at some point in the future.

How should sponsorship look in sBTC-v1?

1. Summary

To support making some sBTC transactions without the need to own or use STX, a "sponsoring server" will be built to provide on-demand sponsorship of certain Stacks-based sBTC transactions.

The funds for these sponsorships will be provided by entities within the Stacks ecosystem.

2. Context & Purpose

Stacks provides a mechanism for "sponsoring" transactions. In a sponsored transaction, the payload is still signed by the end user, but the funds for the STX fee is provided by a different address. This provides a mechanism where the security and authorization of the transaction remains decentralized, while providing a better user experience for users who wish to only own sBTC.

We have deemed that it's important for sBTC users to be able to make certain transactions, such as sBTC withdrawal requests, without owning STX. This provides a more "Bitcoin native" experience and simplifies the adoption of sBTC.

To make a sponsored transaction, the workflow (not specific to this design) is:

  1. An application requests that a user signs a transaction while providing a sponsored flag. This slightly alters the authorization payload of the transaction and prevents any fee from being added.
  2. After signing the transaction, the signed (but not yet sponsored) transaction payload is sent to the "sponsor".
  3. The sponsor modifies the transaction to add the fee and the sponsor's nonce. The sponsor signs the transaction and attaches their signature to the sponsor authorization payload.
  4. The transaction is broadcasted to the network.

To prevent allowing any transaction to be sponsored, which would quickly drain the sponsor's wallet, it is important for the sponsoring server to validate the transaction. For our use cases, we will mainly be validating the contract call details of the transaction.

Relevant Research Discussions

External Resources

Stacks.js function to sponsor a transaction

3. Design

3.1 Proposed Component Design

We will build a "sponsoring server", which is a backend server that provides HTTP endpoints for sponsoring transactions. Because of the highly available libraries for sponsoring and validating transactions, this server will likely be built with Node.JS or some other JS-based runtime, but that decision may be outside the scope of this document.

The sponsoring server will have a configured list of allowable contract calls, which is in the form of a (contractAddr, functionName) tuple. If the transaction matches one of those allowed contract calls, the transaction is sponsored.

The sponsoring server can be configured to use multiple sponsoring addresses. Using multiple addresses prevents errors that can stem from reaching the chaining limit.

API Endpoints

There are two main endpoints that need to be provided to end-users:

  • POST /sponsor-tx: sponsor a transaction, which is provided in the payload of the HTTP call
  • GET /status: An endpoint that provides information about whether the sponsoring server is available to sponsor transactions.
POST /sponsor-tx

Attached in the JSON payload of this endpoint is the signed, but not sponsored, transaction. This transaction is provided in hex format.

The transaction payload is first validated. For the most part, validation is based on the contract call payload of the transaction, but the sponsoring server can be flexible enough to easily add other rules like blocklisted addresses. If the transaction is not validated, a 400 status code is returned.

Next, the sponsoring server selects which internal wallet will be used for sponsoring transactions. The wallet selects the wallet that has:

  • Enough STX to cover the fee
  • The lowest number of pending transactions

If there are no available wallets, a 500 status code is returned.

Then, the server determines the fee to be used for the transaction. This uses the fee estimation RPC endpoint provided by Stacks nodes.

Finally, the server sponsors the transaction and returns a 200 response with the sponsored transaction (in hex).

GET /status

The status endpoint is primarily provided to inform sBTC applications whether they should request sponsored transactions or not. This is important because the transaction payload is different for non-sponsored transactions, and so applications need to make different transactions.

The primary result provided by this endpoint is a "true/false" about whether the server is available to sponsor transactions. This result is based on whether:

  • Any available addresses have enough funds to cover the fee
  • Any available addresses (that have funds) haven't reached the chaining limit

sBTC applications will use this endpoint when preparing to sign a transaction:

  • If "Ok", the application makes a transaction request with sponsored: true
  • If not "Ok", the application makes a transaction request with fees paid by the user

3.1.1 Design Diagram

Image

3.1.2 Considerations & Alternatives

Using a dynamic fee market, where users pay in sBTC in return for having transactions sponsored, was deemed too complex for v1. It's also possible to implement a fee market after the launch of v1.

3.2 Areas of Ambiguity

  • What are the transaction payloads that we'll support sponsoring?
  • Is fee estimation the right approach, compared to something like a fixed fee?
  • What do we do if the fees we set are too low, and then transactions are "stuck"? Should we build the sponsoring server with smart replace-by-fee logic?

Closing Checklist

  • The design proposed in this issue is clearly documented in the description of this ticket.
  • Everyone necessary has reviewed the resolution and agrees with the proposal.
  • This ticket has or links all the information necessary to familiarize a contributor with the design decision, why it was made, and how it'll be included.
@AshtonStephens AshtonStephens added the design making a design decision. label Apr 8, 2024
@AshtonStephens AshtonStephens added this to the Low Level Design milestone Apr 8, 2024
@setzeus
Copy link
Collaborator

setzeus commented Apr 10, 2024

Re: Areas of Ambiguity

  1. I believe Withdrawal requests are the most important transaction type to include sponsored transactions
  2. Yes, I believe it is. Especially since one of the key reasons we're considering this feature is UX/convenience. Optimizing for getting txs through makes sense to me.
  3. Hmm. That's a good Q. My gut feeling points to that solution introducing a ton of complexity & I'm not sure the payoff is worth. Need to consider. Possibly a want & not a need but would love to hear input from others.

@hstove
Copy link
Contributor

hstove commented Apr 10, 2024

  1. Hmm. That's a good Q. My gut feeling points to that solution introducing a ton of complexity & I'm not sure the payoff is worth. Need to consider. Possibly a want & not a need but would love to hear input from others.

Yeah, it's also something we can implement at a later date without requiring significant breaking changes to apps that use the sponsoring server.

@AshtonStephens
Copy link
Collaborator Author

AshtonStephens commented Apr 10, 2024

Conversation is changing a bit. There are now two different things that needs STX sponsorship:

  1. The deposit contract call made from the signers <-- needs new conversation
  2. The STX gas amount that an sBTC user would have

@AshtonStephens
Copy link
Collaborator Author

In the ticket linked below we discuss how the sBTC operation related contract calls will be paid for; now this discussion is here to decide how gas fees should be paid given the user only has sBTC and no STX.

After an impromptu discussion the best path forward seems to be providing clarity developers with two clarity contract "patterns":

  1. A pattern that allows the app to sponsor the execution fee in return for a defined amount of sBTC
  2. A pattern that allows the app to sponsor the execution fee for no sBTC in return

This won't meet everyone's needs, but will make sBTC-v1 functional for apps that build upon it. It will be their responsibility to maintain the funds necessary to make the contract calls for their app to run.

@hstove
Copy link
Contributor

hstove commented Apr 11, 2024

Building off your last comment @AshtonStephens , I think we also want to note that this can be demarcated into a few different problems to solve:

  • There are some transactions that the signers much make (like deposit-accept and withdrawal-reject), which costs STX fees. It's likely that the best approach is to sponsor these transactions with no sBTC paid in return.
  • When it comes to users using sBTC to pay for fees when interacting with the Stacks chain, we should provide guidance and tools to applications so that they can utilize transaction bundles and sponsored transactions. This will not be a "core" or "universal" feature in sBTC v1.
  • There might be some specific sBTC operations, like withdrawal-request, where it's important to not need STX to cover fees. We may want to also sponsor these transactions with nothing in return.

@hstove
Copy link
Contributor

hstove commented Apr 11, 2024

I'm hoping to help us get more understanding about what our plans are regarding allowing users to pay with sBTC in return for having their transaction sponsored. I know that apps can answer these questions however they want, but if we're planning on building this to support sBTC-paid withdrawals at launch, I think it would be good to get more clarity.

  • Is the plan to have the user transfer sBTC to the sponsor, or for the user to swap sBTC for STX, and then transfer STX?
    • User transfers sBTC to sponsor:
      • How is the exchange rate determined?
      • Does the user have any say in the exchange rate?
      • Is the entity doing the sponsoring comfortable with the price risk associated with balancing two assets?
    • User swaps sBTC for STX:
      • What DEX/AMM are they using to swap sBTC for STX? This is mainly a challenge if we want to support this at the launch of sBTC
  • The sponsoring server runs the risk of sponsoring a transaction that can fail, which would result in STX fees paid and no funds earned in receipt. Is that OK?
    • For example, the sponsor server could check the sBTC balance of the user to ensure they'll have funds, but there's no guarantee that the user will have that sBTC balance when the tx is executed.
    • If the user is swapping sBTC to STX, and sending that to the sponsor, you could also run a risk of a failed transaction if the exchange rate on the DEX changes before the transaction is executed.
    • This seems like a small issue IMO, but worth noting the DOS risk
  • Because the user is determining the transaction fee (based on the amount of sBTC they pay), how do you handle chained transactions with varying fees?
    • Example:
      • Alice makes a transaction with sponsor nonce 0 with 0.001 STX fee
      • Bob makes a transaction with sponsor nonce 1 with 10 STX fee
      • Bob's transaction will have to wait a long time, even though he spent a lot on fees
    • This is less of an issue on the "benevolent sponsor" implementation because the sponsor picks the fee
    • This isn't an unsolvable problem, but it's added complexity

@hstove
Copy link
Contributor

hstove commented Apr 12, 2024

Given the additional scope and complexity of this feature, we've decided to remove this feature as required for the launch of sBTC v1. We can find ways to provide guidance to developers, including the example contract linked in the description.

Fortunately, because this doesn't effect the core sBTC protocol, this can be implemented after the launch of v1.

@hstove hstove closed this as completed Apr 12, 2024
@AshtonStephens AshtonStephens added sponsor api API that signs Stacks transactions for sponsorship. clarity The clarity smart contracts. labels Apr 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clarity The clarity smart contracts. design making a design decision. sponsor api API that signs Stacks transactions for sponsorship.
Projects
Archived in project
Development

No branches or pull requests

3 participants