stacks-network / stacks-core

The Stacks blockchain implementation
https://docs.stacks.co
GNU General Public License v3.0
3.01k stars 674 forks source link

Transaction bundles to enable new use-cases #4235

Open MarvinJanssen opened 10 months ago

MarvinJanssen commented 10 months ago

Is your feature request related to a problem? Please describe. Due to the nature of how the Stacks blockchain and the Clarity smart contract language works, some types of atomic actions are either impossible or very tedious to do. For example, let us say that I do not have any STX on my account but I own sBTC. If I want to make a Stacks transaction moving my sBTC then I only have two options:

  1. Buy STX and fund my address, which I might not want to do.
  2. Find a sponsor willing to sponsor my transaction.

A sponsor, naturally, would generally want something in return. In this hypothetical I could say: if someone is willing to sponsor my transaction, I will pay that sponsor in sBTC. It sounds good on paper, but today it is hard to achieve on Stacks in a decentralised and atomic way. How can the sponsor ensure that he gets paid for sponsoring my transaction? If I send two transaction, I can simply RBF the one where I pay him after he sponsors my transaction, it creates all sorts of bad situations.

For the sBTC Mini project I formulated a simple solution that effectively introduces a wrapper around common actions. All that the wrapper does, is pay a defined fee to the sponsor, and then continue with the action. For example, a sponsored sBTC/SIP010 transfer paid for in sBTC could look like this:

(define-public (transfer (amount uint) (sender principal) (recipient principal) (memo (optional (buff 34))) (sponsor-fee uint))
    (begin
        ;; Pay the fee.
        (try! (contract-call? .sbtc-token protocol-transfer fee sender (unwrap! tx-sponsor? err-no-sponsor)))
        ;; Perform the action (SIP010 transfer)
        (transfer amount sender recipient memo)
    )
)

This achieves atomicity of the two actions but it requires either:

  1. The contract in question to have implemented such a wrapper from the get-go.
  2. The deployment of a wrapper/proxy contract that introduces the features.

Neither solution is very attractive because the ecosystem is ever-evolving and continuously deploying proxy contracts for existing and new dapps / DeFi is untenable.

Describe the solution you'd like We talked about some kind of atomic action capability in the Clarity WG to maintain STX as the only gas fee whilst still allowing users to effectively only use sBTC in their day to day. It would involve signing a transaction bundle which are executed in sequence but all-or-nothing, if one reverts they all revert. If that exists, then one could do many things.

Convert sBTC to pay STX gas:

In that case, the bundle would fail if the STX obtained in tx1 is insufficient. STX remains the only gas token.

Pay sBTC to a sponsor which uses STX to sponsor the transaction:

The sponsor decides whether or not to sponsor the tx bundle. The difference between this and what we did in Mini is that no proxy contracts are needed to enable sBTC fees for all contract calls. STX remains the only gas token. Additionally, a new runtime constant tx-miner next to tx-sender and tx-sponsor? could be introduced to allow contract calls to directly interact with the transaction miner principal. In this case many new kinds of contracts / tx bundles could be created. In terms of fees, when assessing a tx bundle, the miner would sum all the fees together.

I used the example of enabling sBTC fees for transaction as a prime use-case for transaction bundles but obviously it is not limited to just fees. When thinking about bundles I can envision many other novel applications.

jcnelson commented 10 months ago

I think in your specific example, there's gonna be a SIP to make it possible to pay the transaction fee in sBTC. See here

MarvinJanssen commented 10 months ago

I've seen that thread but was unaware there is going to be a SIP. Looking forward to reading it. In any case, transaction bundles can prove quite useful in many cases so I hope this issue will spark some discussion.