Moving STX assets w/ BTC transactions

I am trying to understand this: sips/ at main · stacksgov/sips · GitHub

  1. How do STX miners know which BTC address to listen to? eg that the BTC address has ownership over the STX? And how is that BTC address created?
  2. Is it the equivalent BTC address to the STX address that holds the assets? eg derived from the same seed phrase?
  3. Why is it only possible to move STX in this way?

If we were to allow NFTs and fungible tokens to work the same way, is it as simple as added a trait to current token contracts as a new standard?

1 Like

They inspect the state of the .pox contract as it was when the PoX anchor block was mined. The stacker is required to supply a BTC address when they stack directly, and a delegated stacker may either supply a BTC address (in which case, it must be used by the delegate when they lock up the STX), or defer to the delegate to do so on their behalf (e.g. so the delegate can take care of PoX reward disbursal out-of-band).


SIP-007 also describes a way to move STX via BTC transactions, and a way to stack STX via BTC transactions. The reason it’s limited to these two options is because (1) these transactions contribute to the block’s total compute budget, and (2) the sender of these transactions does not pay a STX transaction fee. Instead, all Stacks nodes must process these on-BTC transactions, and must do so before considering any Stacks block transactions (meaning, the total compute budget available to the block is reduced by the budget consumed by the on-BTC transactions’ use). As such, arbitrary smart contract deployments and contract-calls from BTC transactions are not supported, and likely never will be, because it turns out that it’s unnecessary.

To run arbitrary Clarity code from a Bitcoin transaction, you’d structure the smart contract to only run the intended code if the caller can prove that there exists a Bitcoin transaction that contains whatever well-formed data that the smart contract needs. Then, once the Bitcoin transaction gets mined, the smart contract would allow anyone to send a corresponding Stacks contract-call transaction that contained a Merkle proof that the transaction was mined as one of its arguments. The smart contract function would authenticate the transaction with the Merkle proof, parse the transaction, and extract any useful data (e.g. an OP_RETURN, the sender’s public key, the payment amount, the recipient(s), etc.) that is needed for the contract-call to complete. This can be achieved today, even in the presence of flash blocks, via MagicStx’s clarity-bitcoin.clar code (which seems based on my clarity-bitcoin.clar code).

In nearly all cases, the Bitcoin transaction will need to include a value that represents the sender as a STX address (since tx-sender will not be the Bitcoin transaction sender). The biggest challenge to doing this today is that principal-of is broken (but fixed in 2.1). principal-of would be useful here because you could use it to convert one of Bitcoin transaction’s input’s public keys into a STX address, thereby ensuring that the smart contract can automatically deduce the STX address of a Bitcoin transaction (note that the resulting address would be a re-encoding of the Bitcoin address, and thus all the concerns here apply regarding derivation paths). You could also use principal-of to verify a signed payload in the Bitcoin transaction’s OP_RETURN, for example, and use that to deduce the STX address if it’s not evident from the Bitcoin address (which in turn permits you to use the status quo’s derivation paths). But principal-of being broken isn’t insurmountable if you want to deploy something today; you’d just need to add some kind of “pre-registration” process for new users, which binds their STX address to a public key in the smart contract before they send the Bitcoin transaction. This pre-registration step could be handled by the smart contract author on the user’s behalf.

Once the user sends the Bitcoin transaction, anyone can relay it as well as the proof to the smart contract (e.g. the smart contract author could do this), and the Clarity code associated with that transaction would execute “as if” the Bitcoin sender had called it. Again, the biggest challenge with this design pattern is making sure that the Bitcoin sender is properly authenticated (and converted to) a STX address, and this is solvable today and easily done in Stacks 2.1.


So submitting your BTC address in POX means that BTC address can move any of the STX from that STX wallet in the future?

But with delegated stacking this doesn’t apply?

What is this other way?

Could this be supported in a different way to enable other assets? e.g. the the TX fee could be pre-paid, and remove the need for these to be processed before any Stacks block transaction.

So you can put clarity code in a bitcoin transaction and then Stacks can execute it once it is submitted by anyone? This wouldn’t trigger automatically though?

So this seems like a solve then to move any asset from a BTC address that is linked to the STX address holding the assets?

Got it, so today we will need pre-registration but with 2.1 we won’t.

My thinking now is that any wallets that support other apps, e.g. ledger supports a Stacks app, it should be easy to make it possible to send an asset to an existing BTC address and then go through this logic.

Could a UI be created where there’s a website that once an asset has been sent to an existing BTC address, the address owner could go to that website to generate a TX they could sign with the existing address’s private key and broadcast it to move the asset. This would be a great solve.

1 Like

No. The BTC address has no relationship with your STX.

See this section of SIP-007.

No, because the Bitcoin transaction fee is chosen independent of the share of the Stacks block budget the transaction might have consumed. For example, a Bitcoin miner could simply choose a fee of 0 satoshis for their BTC-hosted STX-bound transactions. This means that there’s no reliable way for the Bitcoin transaction to “pre-pay” a STX transaction fee.

Not quite. You can put data in the Bitcoin transaction, relay that transaction (and Merkle proof) to the Clarity contract, and have that Clarity contract take actions based on that data. Now, while someone has to relay the transaction, that relaying entity need not be the original submitter. For example, the smart contract developer could do this on behalf of users. As another example, the Clarity contract could compensate people for relaying Bitcoin transactions with a contract-defined asset.

I don’t know how to parse this question?

Yes, you could do this easily in Stacks 2.1. Alice sends Bob an NFT on Stacks by transferring it to Bob’s (legacy) Bitcoin address, encoded as a Stacks address. Then, Bob claims his NFT on Stacks via his Bitcoin wallet by sending a transaction that:

  • Spends a UTXO with his Bitcoin address (thereby exposing its public key, and proving that Bob controls the private key)
  • Includes an OP_RETURN payload that identifies the NFT to the Clarity contract, as well as the STX address to which the NFT should be sent. This can be identified with either (a) the 20-byte hash160, or (b) the bare public key.

Then, once Alice sees this transaction on the Bitcoin chain, she can relay it (and the proof) to the contract, which would:

  1. Verify that the public key in the scriptSig matches Bob’s STX-encoded Bitcoin address (requires principal-of)
  2. Verify that the OP_RETURN data is well-formed and identifies Bob’s NFT
  3. Transfer the NFT from the contract to the address in the OP_RETURN. If the OP_RETURN includes the bare public key, then a working principal-of would let the contract convert it into Bob’s intended STX address. If it instead includes a hash160 (which is safer), then the contract could use principal-construct (another 2.1 goodie) to convert it to his address.

You can do all of this today in Stacks 2.05, but there needs to be a pre-registration step that binds Bob’s public key to his STX address in the contract (thereby emulating principal-of). If you can do this, and if you don’t mind including the public key in the OP_RETURN in step 3, then you can do this today.

1 Like

The problem with this is that it somewhat defeats the purpose of sending the NFT to a Bitcoin address. Because you would need to create a Stacks wallet, in order to have a legacy Bitcoin address (encoded as a Stacks address), so that Alice can transfer it.

Is there anyway that Stacks addresses could be unified with Bitcoin addresses in the future? You mentioned previously that it will not be possible with P2SH segwit addresses since they encode different information. What about native segwit? Is there something we can do to Stacks addresses in a future fork that will enable this use case?

1 Like

This is true. If you want to avoid the pre-registration step altogether, then you’ll need to wait for the fixes that 2.1 brings (e.g. principal-of, principal-construct). Or, you could just use the same private key to sign both Bitcoin and Stacks transactions. But that’s not something that most people want (for good reason).

What does “unified” mean here? Do you have a list of concrete requirements you can provide us?

Native segwit isn’t supported in Stacks. A native segwit address isn’t even the right size – it’s 32 bytes instead of 20 bytes. I’ve been thinking about ways to do this in a backwards-compatible way in 2.1, but I’ll need to get them reviewed before implementing them.

1 Like

Does Alice need to do this or can anyone with a STX address do this?

Anyone can do this, provided the contract verifies that the transaction originated from Bob.