
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
Contest Results
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 daysFluidLocker::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::provideLiquidityFluidLocker::withdrawLiquidityFluidLocker::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