Replies: 1 comment
-
|
Care must be taken of the transaction size. Since there is a limit how big of a transaction can be verified on the smart chain side, we should preferably always try to stay below 10kB. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
The current lock-release design for BTC -> Solana swaps requires the LP to lock up a capital on the Solana side in a Solana transaction prior to a client sending in the BTC, in the protocol this cost is shifted on the user (where the user needs to cover the Solana transaction fee). In case of BTC -> Solana the user holds a free option open for 6 hours, therefore the user also needs to pay up a non-refundable deposit acting as an options premium for the LP - in case the user doesn't go through with the swap. All things considered, this means a user needs to have some small amount of SOL tokens before being able to initiate a BTC -> Solana swap. This was somewhat mitigated with a trusted "swap for gas" feature, however that only works with bitcoin lightning (due to the instant settlement) and would be cumbersome to use with on-chain (as user would have to wait for the on-chain tx to confirm first, and only then could he initate a proper trustless swap).
Here we outline a novel way to handle BTC -> Solana swaps which don't require initial locking transaction on the Solana side, allowing users to initiate swaps with 0 SOL balance. We iteratively go over different approaches until we end up with a secure approach of using deposit only vault with UTXO chaining.
Simple naive approach
A simple (but insecure) approach would be to eliminate the lock transaction - the funds of the LP are in the smart contract's vault anyway. Let's say an LP has 100 SOL in the LP vault - the user would just send certain amount of BTC to the pre-determined LP address on the bitcoin side, specifying his Solana address in an OP_RETURN of the transaction, watchtowers on Solana would then (upon confirmation of the TX), claim the corresponding amount of SOL (calculated from e.g. 3rd party oracle price) from the LP vault, with a transaction proof. In this approach it is important for the smart contract to save already claimed transaction IDs, so same transaction cannot be used to claim the SOL multiple times.
Problem in this system is that the LP can withdraw the 100 SOL from the LP vault at any time, and when user's bitcoin transaction confirms, there isn't any SOL left in the LP vault to pay out to the user on the Solana side.
Deposit only vault
To iterate on the previous approach we can let the LP vault be deposit only (e.g. the LP cannot withdraw funds from it, or can withdraw but with a long enough delay). This way the LP doesn't have a way anymore to simply "rug" the user.
However this approach is also not secure, imagine now another user (or bunch of users) also want to swap from BTC to SOL, so many that they would collectively depelete the 100 SOL available liqudity. This means only the users who can get their transactions confirmed first (pay the highest fee or bribe the miners) on the BTC side would be able to get the SOL, others would be "rugged" and left with no money. Astute reader can also see how an evil LP itself can act as "another user" and send enough BTC to the address (basically to self) with high enough fee to get into right the next block, depelete all its available liqudity and get free BTC by "rugging" the users.
Deposit only vault with utxo chaining
The issue with the previous approach is that we cannot be sure on the ordering of the transactions as they are sent on the bitcoin side (i.e. anyone can pay a higher btc tx fee and send any amount of BTC to the address before the client does).
We can make the ordering deterministic by introducing a dust UTXO chaining & adding UTXO chaining input/output to every swap transaction.
An LP, upon depositing 100 SOL to the vault, would specify a vault UTXO (a dust UTXO - 330 sats on the bitcoin blockchain) controlled by him. The UTXO identifier (txId:vout) would be saved in the vault's state, and would be required to be used by a swap transaction on the bitcoin's side. The swap transaction would also have one additional dust UTXO controlled by the LP, which would replace the prior vault's UTXO, such that the next swap transaction needs to use that UTXO, this creates a "UTXO chain", making swap transactions deterministically ordered.
Moreover, since now both LP's (because of the UTXO chaning input) and user's signatures are required to construct a transaction, we can include the swap's SOL output amount in the OP_RETURN data part of the transaction, making the output amount pre-determined!
This allows any potential swapper to go back the UTXO chain all the way to the UTXO specified in the vault's state on Solana, sum up the output amounts, deduct them from the current vault's balance and see if there is enough SOL left for the user to claim, without getting "rugged".
Example UTXO chained transactions:
Here the vault UTXO is always controlled by LP & User A swapped before User B. We can also see that if TX1 were to change (e.g. the amount sent changes), the Vault UTXO 1 txId reference would change as well, invalidating the TX2 and User B's swap.
Step-by-step process
vault's balance - sum(previous swap SOL outputs) > current swap SOL outputVault withdrawals
Vault withdrawals are also possible under this system, with the only pre-condition being that the vault processed all the submitted swap transactions. We can prove this by burning the Vault UTXO with OP_RETURN, then processing all the swaps until the vault UTXO was burned.
Simple vault burn transaction:
Putting it into our example chained transactions:
TX1 & TX2 would therefore have to be processed before the LP can withdraw funds from the vault
Drawbacks
Larger bitcoin transactions
As all swap transactions also need to include the UTXO chain input & output + OP_RETURN data, the minimum size of the transaction (using p2tr) is 305.5vB, this is 2x bigger than regular 1-in 2-out spends (again using p2tr), which are just 154vB.
LPs can cancel unconfirmed transactions
LPs can double-spend the vault utxo on the input of the swap transaction, invalidating the bitcoin transaction, in this case no money is lost (not even on TX fee) but this would result in a not so great UX for the user. A user would be presented with "Waiting for confirmations" screen, and then some minutes in a "Failed" screen would appear and he would have to go through a swap UI again.
This can be mitigated by LPs posting a slashable bond on the Solana side, such that when 2 signed txns using the same vault UTXO are presented (double-spend by LP) the bond can be slashed.
Prior users can cancel subsequent unconfirmed transactions
If a user A swaps through an LP (TX1) and its transaction is still unconfirmed & now user B also swaps through the same LP (TX2 - using the vault UTXO of the user A's swap for chaining), user A can double-spend it's inputs to the transaction, invalidating the transaction (and also the newly created vault UTXO)
... after User A double-spends UTXO 0
Therefore to be perfectly safe the vault UTXO should first be confirmed (at least 1 confirmation) and only then used by the other user. This however limits the number of swaps that a single LP can process (there are onlt 144 blocks in a day), so one can imagine a single LP managing multiple vaults, allowing swaps to happen in parallel, but this also decreases capital efficiency.
Beta Was this translation helpful? Give feedback.
All reactions