Superfluid is the money streaming protocol, powering a real-time onchain economy. Start earning every second with streaming airdrops, rewards and yield. This contest focuses on a locker system built on top of Superfluid, which is a system showcasing programmable reward distribution.
Scope
On what chains are the smart contracts going to be deployed?
If you are integrating tokens, are you allowing only whitelisted tokens to work with the codebase or any complying with the standard? Are they assumed to have certain properties, e.g. be non-reentrant? Are there any types of weird tokens you want to integrate?
The project integrates the SUP Token, a Superfluid SuperToken that can be found at this address on Base : https://basescan.org/address/0xa69f80524381275A7fFdb3AE01c54150644c8792
(Note that in most of the codebase, SUP Token is named FLUID Token.)
In the context of liquidity provision feature, the project interacts with native ETH (gas token) and WETH.
For more info regarding SuperTokens, see https://docs.superfluid.finance/docs/category/super-tokens
Are there any limitations on values set by admins (or other roles) in the codebase, including restrictions on array lengths?
Always assume that owner / admin protected function parameters are valid and cross-checked before transaction submission.
FluidEPProgramManager.sol :
FluidEPProgramManager::startFunding
:FluidLocker.sol :
Fontaine.sol
Fonainte::initialize
:SupVestingFactory.sol
admin
& treasury
are trustedAre there any limitations on values set by admins (or other roles) in protocols you integrate with, including restrictions on array lengths?
No.
Is the codebase expected to comply with any specific EIPs?
N/A
Are there any off-chain mechanisms involved in the protocol (e.g., keeper bots, arbitrage bots, etc.)? We assume these mechanisms will not misbehave, delay, or go offline unless otherwise specified.
In order to grant units in Superfluid GDA pools, we rely on a third party tool : Stack (see stack.so).
Stack essentially allocates "points" to users based on onchain activity.
On user requests (i.e. when users need to claim these points that are representing pool units), Stack generate a signature that contains user related details and the amount of units to be claimed. The contract verifies that the signature is originated from a Stack whitelisted signer and allocate the units once the signature is verified.
Additionally, Superfluid will run some offchain monitoring system to ensure that programs do not overrun their duration (see FluidProgramDetails::duration
in FluidEPProgramManager). Upon detecting an approaching end of a program a transaction call to stopFunding
will be performed, ensuring that the different streams inherent to a program are closed on time. It is assumed that these calls will be performed on time.
In regards with the token vesting mechanism (SupVesting
), the protocol integrate with Superfluid VestingScheduler
contracts that rely on offchain automation. These automations are managed and monitored by the Superfluid Foundation. They guarantee that the vesting are being started & terminated on-time.
What properties/invariants do you want to hold even if breaking them has a low/unknown impact?
While the boolean UNLOCK_AVAILABLE
is set to false
(initial phase), the sum of all tokens distributed through FluidEPProgramManager
should be equal to the sum of all tokens inside the FluidLocker
instances plus the undistributed amount (still held in the FluidEPProgramManager
contract)
While the boolean UNLOCK_AVAILABLE
is set to true
, token distributed to lockers can only be unlocked through :
FluidLocker::unlock
functionFluidLocker::withdrawLiquidity
function (under specific circumstances, see below)FluidLocker::unlock
function with a unlocking duration of 365 days
FluidLocker::withdrawLiquidity
after having provided liquidity for over 6 months.Token distributed through the FluidEPProgramManager
should always land in a FluidLocker
instance (until withdrawn).
The sum of all the token distributed to FluidLocker
instance and distributed to the tax distribution pool (if subsidyFundingRate
is not null) should be equal to the sum of all token distributed through the FluidEPProgramManager
.
Please discuss any design choices you made.
FluidEPProgramManager::stopFunding
function permissionless.
FluidEPProgramManager
contract and stream will not necessarily be liquidated if there are still funds to provision them.FluidEPProgramManager::stopFunding
can create dust.
FluidLocker::stake
- Stakers units in the Stakers' tax distribution pools :
FluidLocker::provideLiquidity
- providing liquidity will perform a market buy operation
FluidLocker::_pump
) do not use slippage protection. Dev team assumed that the slippage protection occurring in FluidLocker::_createPosition
is sufficient to protect the _pump
call.FluidLocker::withdrawLiquidity
- tax bypassing mechanism
FluidLocker::collectFees
- accrued fees can be collected in Locker owner's EOA directly.
EPProgramManager.sol
: this contract will NOT be deployed. Only FluidEPProgramManager.sol
is deployed and used in the production system.
SupVesting.sol
: This contract is meant to be used to distribute the SUP Token to investor and team members as part of a token vesting.
SupVestingFactory::totalSupply
function could malfunction in case there are a large number of recipients. This shall not be considered a valid issue.Please provide links to previous audits (if any).
Previous Audit link can be found here :
https://audits.sherlock.xyz/contests/648
Please list any relevant protocol resources.
Superfluid Docs : https://docs.superfluid.finance/
Superfluid SuperToken Docs : https://docs.superfluid.finance/docs/protocol/super-tokens/overview
Superfluid GDA Docs : https://docs.superfluid.finance/docs/protocol/distributions/overview
Uniswap V3 Docs : https://docs.uniswap.org/contracts/v3/overview
Stack Docs : https://docs.stack.so/overview
Additional audit information.
It is suggested to look at the Uniswap related functions :
FluidLocker::provideLiquidity
FluidLocker::withdrawLiquidity
FluidLocker::collectFees
We also encourage Watson to ensure that locker owners will not be able to bypass the tax mechanism (aside from the feature allowing it described above).
We highly encourage Watson to look at the SupVesting
& SupVestingFactory
contracts.
Please note that the audited scope is meant to be used to upgrade currently live production system.
Live contracts can be found at below addresses on BASE Mainnet :
Contract | Address |
---|---|
SUPToken (SuperToken) | 0xa69f80524381275A7fFdb3AE01c54150644c8792 |
FluidEPProgramManager (Logic) | 0xee117cD6F04FB85c5bb1bBeB59Bf1F9E16E05764 |
FluidEPProgramManager (Proxy) | 0x1e32cf099992E9D3b17eDdDFFfeb2D07AED95C6a |
StakingRewardController (Logic) | 0x4f69302E435f6D6c9eD40719098B13265027D8C2 |
StakingRewardController (Proxy) | 0xb19Ae25A98d352B36CED60F93db926247535048b |
FluidLocker (Logic) | 0x939659D22aC378426EdF5e71Fc9bD5B89065F8A4 |
FluidLocker (Beacon) | 0x664161f0974F5B17FB1fD3FDcE5D1679E829176c |
Fontaine (Logic) | 0xbFe2ceE2Cc266f26Aaf434Ef69e390FC2a0033fA |
Fontaine (Beacon) | 0xA26FbA47Da24F7DF11b3E4CF60Dcf7D1691Ae47d |
FluidLockerFactory (Logic) | 0xf6EED68979870941AEF88914534F67d06Ae15B80 |
FluidLockerFactory (Proxy) | 0xA6694cAB43713287F7735dADc940b555db9d39D9 |
Total Rewards
Contest Pool
Lead Senior Watson
Judging Pool
Lead Judge
14,200 USDC
7,000 USDC
1,100 USDC
1,900 USDC
Status
Scope
Start Time
End Time
Judging Rules