- Total Prize Pool: $90,500 USDC
- HM awards: $63,750 USDC
- QA report awards: $7,500 USDC
- Gas report awards: 3,750 USDC
- Judge + presort awards: $15,000 USDC
- Scout awards: $500 USDC
- Join C4 Discord to register
- Submit findings using the C4 form
- Read our guidelines for more details
- Starts January 25, 2023 20:00 UTC
- Ends February 3, 2023 20:00 UTC
The C4audit output for the contest can be found here within an hour of contest opening.
Note for C4 wardens: Anything included in the C4udit output is considered a publicly known issue and is ineligible for awards.
Radicle Drips is an EVM blockchain protocol for streaming and splitting ERC-20 tokens.
See docs for a high-level introduction and documentation.
Watch a quick video introduction into the codebase.
Contract | SLOC | Purpose | Libraries used |
---|---|---|---|
Drips.sol | 672 | The dripping logic for DripsHub, it exposes no public functions, and it acts as a library. | |
DripsHub.sol | 259 | The smart contract implementing Drips protocol, it exposes the entire protocol API. | openzeppelin/token/ERC20/IERC20.sol openzeppelin/token/ERC20/utils/SafeERC20.sol |
Splits.sol | 151 | The splitting logic for DripsHub, it exposes no public functions, and it acts as a library. | |
NFTDriver.sol | 149 | The DripsHub driver implementing NFT-based users identification for the protocol. | openzeppelin/metatx/ERC2771Context.sol openzeppelin/token/ERC20/utils/SafeERC20.sol openzeppelin/utils/StorageSlot.sol openzeppelin/token/ERC721/extensions/ERC721Burnable.sol |
Managed.sol | 86 | The mix-in adding upgrading, pausing and ownership management to smart contracts. | openzeppelin/proxy/utils/UUPSUpgradeable.sol openzeppelin/proxy/ERC1967/ERC1967Proxy.sol openzeppelin/utils/StorageSlot.sol openzeppelin/utils/structs/EnumerableSet.sol |
Caller.sol | 77 | The generic implementation of batching, approvals and signed permissions for smart contracts. | openzeppelin/utils/Address.sol openzeppelin/utils/cryptography/draft-EIP712.sol openzeppelin/metatx/ERC2771Context.sol openzeppelin/utils/structs/EnumerableSet.sol |
AddressDriver.sol | 74 | The DripsHub driver implementing address-based users identification for the protocol. | openzeppelin/metatx/ERC2771Context.sol openzeppelin/token/ERC20/utils/SafeERC20.sol |
ImmutableSplitsDriver.sol | 35 | The DripsHub driver implementing simplified user identification only capable of creating splits configurations that can never be updated. | openzeppelin/utils/StorageSlot.sol |
Drips protocol is 100% on-chain and self-contained, except ERC-20 tokens it works with and drivers. There are no off-chain actors, and no 3rd party services like oracles or DEX-es involved.
If malicious or unexpected behavior of an ERC-20 contract is a cause of loss or a tool of theft of these ERC-20 tokens, it's not considered an issue in scope. If such ERC-20 contract can cause loss or theft of other ERC-20 tokens without collusion, it's considered an issue in scope.
The protocol is extendable with drivers, and drivers should not be able to break the protocol. If a malicious driver causes harm to users with IDs in range managed by that driver, it's not considered an issue in scope. By harm we mean loss or theft of funds, but also harmful changes to configuration, e.g. the drips configuration, which may cause dripping to unwanted receivers, or the splits configuration, which may redirect received funds to unwanted receivers. If a malicious driver can harm users with IDs outside of range managed by that driver, it's considered an issue in scope.
The protocol at its core operates on abstract user IDs.
A contract can be registered in DripsHub as a drivers, then it gets assigned an exclusive, large range or user IDs.
The driver is the only entity that can perform important operations for user IDs it has assigned, e.g. updating configurations or transferring funds.
The driver can then expose a custom API and introduce custom rules about controlling its user IDs.
For example the AddressDriver
assigns 1-to-1 its user IDs to all existing addresses.
Via its API for each user ID it allows the assigned address to perform important operations in DripsHub.
Another driver is NFTDriver
, which assigns user IDs to token IDs.
Its API only allows the current NFT holder to perform important operations for the assigned user ID.
The protocol lets anybody register new drivers, it's supposed to invite integrations with 3rd party identity systems.
- If you have a public code repo, please share it here: https://github.com/radicle-dev/drips-contracts
- How many contracts are in scope?: 8
- Total SLoC for these contracts?: 1503
- How many external imports are there?: 0
- How many separate interfaces and struct definitions are there for the contracts within scope?: 9 structs + 4 structs only for storage for upgradable contracts. no internal interfaces only some external interfaces like OZ for ERC20s
- Does most of your code generally use composition or inheritance?: a mixture of both. We use in inheritance in the DripsHub but the Split and Drips logic are libraries used with composition.
- How many external calls?: 0
- What is the overall line coverage percentage provided by your tests?: 90
- Is there a need to understand a separate part of the codebase / get context in order to audit this part of the protocol?: false
- Please describe required context:
- Does it use an oracle?: false
- Does the token conform to the ERC20 standard?: we don't have a token
- Are there any novel or unique curve logic or mathematical models?: https://v2.docs.drips.network/docs/the-protocol/technical-overview
- Does it use a timelock function?: no
- Is it an NFT?: yes
- Does it have an AMM?: no
- Is it a fork of a popular project?: false
- Does it use rollups?: false
- Is it multi-chain?: false
- Does it use a side-chain?: false
Radicle Drips Hub uses Foundry for development. You can install it using foundryup.
The codebase is statically checked with Slither version 0.9.2. Here are the installation instructions.
First, you need to install the dependencies linked in /lib
:
# Install dependencies
forge install
Then you can run the tests:
# Running tests
forge test
All the tests are supposed to pass. Foundry by default prints the total gas usage for each test, but for a more detailed gas report table, you can use the following:
# Running tests and generate a gas report table
forge test --gas-report
slither .
There are supposed to be no issues found.