Usual is a decentralized stablecoin issuer launched 3 months ago, now ranked among the top 15 with over $350M in TVL and 20k holders. The V1 release, which is the focus of this audit, includes the introduction of $USUAL, the governance token for the protocol, along with its allocation, staking and distribution logic, and the related airdrop contracts.
Scope
On what chains are the smart contracts going to be deployed?
Ethereum
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?
As part of the V1 competition, we are integrating only our own new token contracts that are also part of this competition.
Are there any limitations on values set by admins (or other roles) in the codebase, including restrictions on array lengths?
DistributionModule.sol::queueOffChainUsualDistribution(bytes32 _merkleRoot)
DistributionModule.sol::distributeUsualToBuckets(uint256 ratet, uint256 p90Rate)
Are there any limitations on values set by admins (or other roles) in protocols you integrate with, including restrictions on array lengths?
No
For permissioned functions, please list all checks and requirements that will be made before calling the function.
N/A
Is the codebase expected to comply with any EIPs? Can there be/are there any deviations from the specification?
N/A
Are there any off-chain mechanisms for the protocol (keeper bots, arbitrage bots, etc.)? We assume they won't misbehave, delay, or go offline unless specified otherwise.
Yes, the DISTRIBUTION_OPERATOR_ROLE.
The operator will, on a recurring schedule(DISTRIBUTION_FREQUENCY_SCALAR minimum), trigger DistributionModule.sol::distributeUsualToBuckets(uint256 ratet, uint256 p90Rate), with the appropiate values.
The operator will also, on a recurring schedule(DISTRIBUTION_FREQUENCY_SCALAR) call DistributionModule.sol::queueOffChainUsualDistribution(bytes32 _merkleRoot) to post a merkle tree to distribute the offchain allocations assigned by distributeUsualToBuckets above.
If the codebase is to be deployed on an L2, what should be the behavior of the protocol in case of sequencer issues (if applicable)? Should Sherlock assume that the Sequencer won't misbehave, including going offline?
N/A
What properties/invariants do you want to hold even if breaking them has a low/unknown impact?
N/A
Please discuss any design choices you made.
We are choosing to not be able to withdraw fees on UsualX for the time being. At the moment, the fees wouldn't be withdrawable. `This is a deliberate choice to be implemented in a later contract upgrade, when the protocol governance decides on how the unstaking fees should be dealt with (i.e. burned, redistributed).
The distribution to all the buckets, even if a bucket at that time wouldn't have any recipients eligible, is intended. An applicable scenario would be if nobody is staking in UsualX or UsualSP, therefore any rewards accrued would be essentially unredeemable. This is intentional until the protocol decides on how to proceed with unclaimed rewards later on.
Rounding does not necessarily need to be in the favor of the protocol, unless it would lead to breaking behaviour ( i.e. underflows)
Bucket Distribution Changes being applicable retroactively to distributions is intended.
Please list any known issues and explicitly state the acceptable risks for each known issue.
Any risk regarding the DaoCollateral & USD0 contract, that are not related to the role management changes, is acceptable unless its High Severity.
Any risks from the acknowledged issues from the previous audit reports are known and acceptable:
We will report issues where the core protocol functionality is inaccessible for at least 7 days. Would you like to override this value?
We would like to override this value to 14 days. The reason for this is that as part of our challenge-mechanic on the offchain distribution merkle trees challengers can, via their privileged role, render an offchain distribution inaccessible for up to 14 days. This requires a malicious privileged actor challenging legitimate distributions at the maximum possible impact, which is 14 days.
Please provide links to previous audits (if any).
Please list any relevant protocol resources.
https://www.loom.com/share/bd30edd538594f6da36d083b0b8ccf47?sid=cf1d0cef-b810-4bdf-8f95-42fbe5f60230
Our tech gitbook, which is currently work in progress:
https://usual.gitbook.io/usual-technical-documentation/Aw3jUdIChYIRnEPcqUqK/
Overview Diagrams for this competition:
Miro board link: https://miro.com/app/board/uXjVLNEXyS0=/ Password: sherlock
Additional audit information.
The main focus on this audit is:
These consist of our UsualX Vault, UsualSP Staking & the distribution system based on an offchain merkle tree done inside the distribution module contract itself. This also includes the new Tokens $USUAL & $USUALS.
The diffs to our previous audited version can be found here ( diffs appear larger than they are because the contracts have been cleaned up formatting wise, i.e. sorting functions):
Total Rewards
Contest Pool
Lead Senior Watson
Judging Pool
Lead Judge
59,500 USDC
21,500 USDC
3,000 USDC
Status
Scope
Start Time
End Time
Judging Rules