sablier-labs / v1-protocol

Core smart contracts of the Sablier V1 protocol
https://sablier.finance
GNU General Public License v3.0
263 stars 78 forks source link

Streamed atomic swaps #35

Closed TomAFrench closed 1 year ago

TomAFrench commented 4 years ago

This PR aims to implement streamed atomic swaps as defined in #29

Todo:

Currently it's possible for a party to cancel the stream of tokens they are receiving from the swap. This will refund the remaining balance back to StreamedSwap.sol where it would remain stuck. This is mitigated by the fact that it would require directly calling the contract as https://app.sablier.finance/ does not expose cancellations to the recipient.

It doesn't seem like it's possible to attack the other party using this (it would be impossible to then refund your own tokens by cancelling the swap after this) but it's not ideal.

Possible solutions:

  1. Rather than stream directly to participant, set up a thin proxy on the receiving end which the recipient can withdraw through but not cancel the stream in sablier.sol. Not great as stream would then not be visible from https://app.sablier.finance/
  2. Deploy a new contract each time similarly to SealedSablier.sol through a factory. Increased gas costs although seems like it would work in terms of preventing loss of funds. Still has the issue of the other stream still running so the token balances will become unbalanced.
  3. Wait until locking streams is supported in sablier.sol and then just lock stream on recipient's end.

Currently no verification of consent from the "recipient" of a swap is required. Any funds which StreamedSwap.sol is approved to transfer can be trivially stolen. I need to look into the best way to handle this while still allowing contracts to be one/both of the parties involved in a swap.

I've started writing a solui interface for StreamedSwap.sol to allow easy interaction with it in the case of issues with any frontend. solui currently doesn't support method calls which return multiple values so this is on hold.

It currently has my details in it which should be updated if merged.

TomAFrench commented 4 years ago

RE: Add security on creation of swaps

StreamedSwap is now formed by inheriting from SwapProposer and SwapExecutor contracts

Rather than immediately initiating a swap, a user ('sender') creates an AtomicSwapProposal through the methods inherited from SwapProposer, this defines the terms of the swap (the recipient's address, tokens, amounts, and duration). The sender is also required to pass their deposit to StreamedSwap at this point.

The other party to the swap ('recipient') may then choose to accept or reject this swap proposal using methods inherited from SwapExecutor. If accepted, StreamedSwap takes their deposit as well and creates the streams. Both parties have the option to cancel the proposal instead, refunding the sender's deposit.

Otherwise works as before.

It would be interesting to see if the requirement for the recipient of the swap to be pre-selected could be loosened to be optional although I want to keep it simple for now.

PaulRBerg commented 1 year ago

Closing due to inactivity.

Streamed atomic swaps remain an interesting idea, which we are tracking on our Canny feature request dashboard:

https://sablier.canny.io/feature-requests/p/streamed-atomic-swaps