Exploring the trustfulness of the Sablier V1 protocol

Exploring the trustfulness of the Sablier V1 protocol

Update Jan 29, 2021: We burned the admin keys. We don’t have any administrative rights anymore. This article should be consulted for historical purposes only.

Introduction

Sablier has two building blocks:

  1. End-user products: pay.sablier.finance and app.sablier.finance
  2. Money streaming engine powered by Ethereum smart contracts

In this article, we will focus on the second item. We will shed light on the administrator rights we have as protocol authors and maintainers, as well as on the security measures we’ve taken.

Architecture

Let’s start with a primer on the technical design.

Sablier v1 has three smart contracts, all non-upgradeable:

  1. Payroll.sol — Dapp Proxy
  2. Sablier.sol — Money Streaming Engine adhering to ERC-1620
  3. CTokenManager.solCompound token manager

User Flow

  1. User goes to pay.sablier.finance to stream some money
  2. They fill the form and submit the blockchain transaction
  3. The transaction is sent to the Dapp Proxy
  4. The Dapp Proxy pings the Money Streaming Engine to create a new stream
  5. (Optionally) If the stream is a compounding stream, the Money Streaming Engine pings the Compound Token Manager to ensure that the requested token had been previously whitelisted

Simplicity = Key

As you may have noticed, we designed the protocol with simplicity in mind. There’s no fluff or unnecessary complexity — just the bare minimum required to kick off real-time finance on Ethereum.

To see the source code, head to our GitHub repository:

GitHub - sablier-labs/v1-protocol: Core smart contracts of the Sablier V1 protocol
Core smart contracts of the Sablier V1 protocol. Contribute to sablier-labs/v1-protocol development by creating an account on GitHub.

And for a more in-depth account, we provide you with these resources:

Administrative Rights

We burned the admin keys and don’t have any admin permissions anymore.

All of our smart contracts inherits from a forked version of OpenZeppelin’s Ownable.sol, which means they each have an “owner” property, further referred to as the administrator.

The administrator is the same across all contracts:

Which is an account controlled by Sablier Labs Ltd, the developer of the protocol— a private limited company incorporated in the United Kingdom.

The rights the administrator has are different for each smart contract.

Dapp Proxy

View the source code of this contract here.

The administrator has the exclusive permission to call these two functions:

  • whitelistRelayer

Adds a new account as a relayer tied to a specific stream. The relayer can then withdraw money for end users.

  • discardRelayer

Removes a previously whitelisted relayer.

For more information about how our relayer system works, head to this section of the FAQ.

Money Streaming Engine

View the source code of this contract here.

The administrator has the exclusive permission to call these two functions:

  • updateFee

Updates the fee charged by using compounding streams. This is a percentage that can take integer values between 0 and 100. The fee is currently set to 0 and we have no plans to update it in the near future.

  • takeEarnings

Withdraws any earnings that accrued in the smart contract.

For a thorough explanation of how compounding streams work, and how our business fee can technically be mandated, head to this section of our protocol documentation.

Compound Token Manager

View the source code of this contract here.

The administrator has the exclusive permission to call these two functions:

  • whitelistCToken

Adds a new cToken to the whitelist, so that users can create compounding streams with it.

  • discardCToken

Discards a previously whitelisted cToken. Previously created compounding streams are not affected.

There aren’t many cTokens in circulations, so one might wonder why we added this limitation in the first place. The answer is that the math surrounding the Compound protocol is complex and we wanted to limit the risk.

Security

On top of the core business logic, we’ve taken a few security measures in the form of a “dead man’s switch”.

The “Sablier.sol” contract inherits from a forked version of OpenZeppelin’s Pausable.sol, which means it has a “pauser” property. Its value is:

Which is also an account controlled by Sablier Labs Ltd, the developer of the protocol.

What can the pauser do?

The security of the Sablier protocol is our outmost priority. Our team, accompanied by external auditors and consultants, has invested considerable effort to create a protocol that is safe and reliable, but we can’t rule out the possibility that there may be undiscovered vulnerabilities.

If a major bug is to be found, we will use the pauser account to set the “paused” property from “false” to “true”, which will break the following functions:

Now, it is of extraordinary importance to note that this does *not* make the Sablier protocol a custodial, and it neither means users have to trust us, because we *cannot* touch any of the funds sitting in the smart contract.

We purposely left the cancelStream outside of the pauser’s reach. As long as this function is free of bugs, any stream can be cancelled by either the sender or the recipient, a contract call that transfers all remaining funds back to both parties on a pro rata basis.

Wrap Up

We think we found an equilibrium with Sablier v1. We sought to make it robust to errors but also retain its trustless and decentralised dimensions. Nonetheless, we can do better.

As we evolve as a company and find product/market fit, we may migrate the administrator keys to a community-managed DAO. It is likely though that, by then, Sablier v2 will be out, which will bring significant changes to the smart contract architecture.


If you have any questions, ideas, or issues, ping us on Discord or Twitter — we’d love to hear from you.