Platform: Code4rena
Start Date: 31/01/2023
End Date: 07/02/2023
Period: 7 days
Status: Completed
Pot Size: $90,500 USDC
Participants: 169
Reporter: itsmetechjay
Judge: LSDan
Id: 211
League: ETH
rvierdiiev | 1/169 | $8,268.35 | 15 | 4 | 0 | 10 | 1 | - | 0 | 0 |
gjaldon | 2/169 | $6,380.37 | 8 | 5 | 1 | 3 | 0 | 0 | 0 | 0 |
bin2chen | 3/169 | $4,342.78 | 12 | 3 | 0 | 9 | 0 | 0 | 0 | 0 |
hansfriese | 4/169 | $3,503.37 | 12 | 3 | 0 | 8 | 1 | Grade B | 0 | 0 |
Ruhum | 5/169 | $2,263.69 | 8 | 2 | 0 | 5 | 1 | Grade B | 0 | 0 |
0xNazgul | 6/169 | $2,246.26 | 6 | 2 | 0 | 3 | 1 | - | 0 | 0 |
peakbolt | 7/169 | $1,935.79 | 4 | 1 | 0 | 2 | 0 | - | 0 | 0 |
ulqiorra | 8/169 | $1,689.18 | 5 | 3 | 0 | 1 | 0 | Grade B | 0 | 0 |
0xBeirao | 9/169 | $1,646.35 | 4 | 1 | 0 | 2 | 1 | Grade B | 0 | 0 |
rbserver | 10/169 | $1,624.76 | 10 | 1 | 0 | 8 | 0 | Grade A | 0 | 0 |
Auditor per page
Automated findings output for the contest can be found here within an hour of contest opening.
Note for C4 wardens: Anything included in the automated findings output is considered a publicly known issue and is ineligible for awards.
This protocols goal is to make vault creation easy, safe and all without compromising on flexibility. It allows anyone to spin up their own Yearn in minutes.
Vaults can be created permissionlessly based on any underlying protocol and execute arbitrary strategies. The factory uses only endorsed Adapters and Strategies with minimal user input to reduce complexity for a creator and ensure safety of the created clones. It gives vault creators a quick and easy way to spin up any Vault they need and end users the guarantee that the created Vault will be safe. For some more context checkout the whitepaper
The protocol consists of 2 parts. The Vault Factory and the actual Vaults and Adapters.
The Vault Factory part consists of a mix of Registry and Execution contracts. All contracts are immutable but execution contracts can be swapped out if requirements change or additional functionality should be added.
Note: This system ensures that minimal user input is needed and executions are handled with valid inputs and in the correct order. The goal is to minimize human error and the attack surface. A lot of configurations for Adapters and Strategies is very protocol specific. These are therefore mainly handled in the implementations itself. Adapters should receive all there critical data from an on-chain registry of the underlying protocol. As its nearly impossible to tell otherwise if the passed in configuration is malicious. There is still a need for some kind of governance to ensure that only correct and safe Templates are added and dangerous assets get rejected.
Additionally we included 2 utility contracts that are used alongside the vault system.
File | SLOC | Description and Coverage | Libraries |
---|---|---|---|
Contracts (16) | |||
src/utils/EIP165.sol | 4 | Exposes the contract interface., - | |
src/vault/adapter/abstracts/OnlyStrategy.sol | 8 | Abstract modifier for delegatecall., - | |
src/vault/AdminProxy.sol | 12 | Proxy contract that owns a majority of contracts. Allows VaultController to call management functions., 100.00% | |
src/vault/adapter/abstracts/WithRewards.sol | 12 | Abstract for adapters with additional rewardTokens., 0.00% | |
src/vault/CloneFactory.sol | 17 | Creates arbitrary clones based on Templates., 100.00% | openzeppelin-contracts/* |
src/vault/PermissionRegistry.sol | 24 | Endorsement/Rejection registry for arbitrary addresses., 100.00% | |
src/vault/CloneRegistry.sol | 29 | Registers each newly created clone., 66.67% | |
src/vault/VaultRegistry.sol | 34 | Registers all created Vaults and provides aditional metadata., 60.00% | |
src/vault/DeploymentController.sol | 55 | Bundles auxiliary contracts for easy interaction., 100.00% | |
src/vault/TemplateRegistry.sol | 57 | Registry for clone Templates with additional metadata. Templates are used by the CloneFactory, 100.00% | |
src/vault/adapter/yearn/YearnAdapter.sol | 110 | Wraps any Yearn Vault in a 4626-compliant interface. Uses AdapterBase., 96.43% | |
src/utils/MultiRewardEscrow.sol 🧮 | 118 | Allows vesting of arbitrary token over any time frame., 100.00% | openzeppelin-contracts-upgradeable/* openzeppelin-contracts/* solmate/* |
src/vault/adapter/beefy/BeefyAdapter.sol | 163 | Wraps any BeefyV6 Vault in a 4626-compliant interface. Uses AdapterBase., 80.85% | |
src/utils/MultiRewardStaking.sol 📤 🧮 🔖 Σ | 311 | Staking contract with one stakingToken and multiple rewardsToken. Rewards can be paid out instantly or over time., 100.00% | openzeppelin-contracts-upgradeable/* solmate/* |
src/vault/Vault.sol 🧮 🔖 Σ | 426 | 4626-compliant Vault implementation. Uses Adapter for actual deposits and withdrawals. Allows creator to set fees., 90.00% | openzeppelin-contracts-upgradeable/* openzeppelin-contracts/* |
src/vault/VaultController.sol 🧮 | 520 | ManagementContract to create new clones, register and endorse Templates or call management functions., 98.87% | openzeppelin-contracts-upgradeable/* |
Abstracts (1) | |||
src/vault/adapter/abstracts/AdapterBase.sol 👥 🧮 🔖 Σ | 405 | 4626-compliant abstract for all adapter implementations. Holds a majority of the business logic of each adapter., 95.65% | openzeppelin-contracts-upgradeable/* |
Interfaces (18) | |||
src/interfaces/IEIP165.sol | 4 | - | |
src/interfaces/vault/IAdminProxy.sol | 5 | - | |
src/interfaces/vault/IWithRewards.sol | 5 | - | |
src/interfaces/vault/ICloneFactory.sol | 6 | - | |
src/interfaces/vault/IStrategy.sol | 7 | - | |
src/interfaces/vault/ICloneRegistry.sol | 10 | - | |
src/interfaces/vault/IPermissionRegistry.sol | 11 | - | |
src/interfaces/vault/IVaultRegistry.sol | 16 | - | |
src/vault/adapter/yearn/IYearn.sol | 18 | Yearn Interfaces, - | openzeppelin-contracts-upgradeable/* |
src/interfaces/vault/IAdapter.sol | 23 | - | |
src/interfaces/vault/IDeploymentController.sol | 24 | - | |
src/interfaces/vault/ITemplateRegistry.sol | 25 | - | |
src/interfaces/IMultiRewardEscrow.sol | 26 | - | openzeppelin-contracts-upgradeable/* |
src/interfaces/vault/IERC4626.sol | 28 | - | openzeppelin-contracts-upgradeable/* |
src/vault/adapter/beefy/IBeefy.sol | 31 | Beefy Interfaces, - | |
src/interfaces/IMultiRewardStaking.sol | 38 | - | |
src/interfaces/vault/IVault.sol | 48 | - | |
src/interfaces/vault/IVaultController.sol | 64 | - | |
Total (over 35 files): | 2694 | 94.84% |
File | SLOC | Description and Coverage | Libraries |
---|---|---|---|
Contracts (5) | |||
src/vault/strategy/StrategyBase.sol | 16 | 0.00% | |
src/vault/strategy/RewardsClaimer.sol | 22 | 0.00% | openzeppelin-contracts-upgradeable/* |
src/utils/Owned.sol | 29 | 100.00% | |
src/utils/OwnedUpgradeable.sol | 30 | 40.00% | openzeppelin-contracts-upgradeable/* |
src/vault/strategy/Pool2SingleAssetCompounder.sol | 47 | 0.00% | openzeppelin-contracts-upgradeable/* |
Interfaces (5) | |||
src/interfaces/external/IWETH.sol 💰 | 5 | - | |
src/interfaces/IPausable.sol | 6 | - | |
src/interfaces/IOwned.sol | 7 | - | |
src/interfaces/IPermit.sol | 14 | - | |
src/interfaces/external/uni/IUniswapRouterV2.sol 💰 | 158 | - | |
Total (over 10 files): | 334 | 18.97% |
Some of these contracts depend on older utility contracts which is why this repo contains more than just these contracts. These dependencies have been audited previously. Additionally there are some wip sample strategies which might help to illustrate how strategies can be used in conjuction with adapters.
Note: The AdapterBase.sol
still has a TODO to use a deterministic address for feeRecipient
. As we didnt deploy this proxy yet on our target chains it remains a placeholder value for the moment. Once the proxy exists we will simply switch out the palceholder address.
There are multiple possible targets for attacks.
deploymentController
Template
endorsedasset
endorsedYearnAdapter.t.sol
)fees
of a vault to the max amount and change the feeRecipient
to the attackerowner
of the adminProxy
to change configurations or endorse malicious templates
harvestCooldown
too low and waste tokens and gas on harvestsReject
legit vaults / assetsPause
vaults / adapters of other creators
Most of these attacks are only possible when the VaultController
is misconfigured on deployment or its owner
is compromised. The owner
of VaultController
should be a MultiSig which should make this process harder but nonetheless not impossible.
EIP-4626 is vulnerable to the so-called inflation attacks. This attack results from the possibility to manipulate the exchange rate and front run a victim’s deposit when the vault has low liquidity volume. A similiar issue that affects yearn is already known. See Finding 3, "Division rounding may affect issuance of shares" in Yearn's ToB audit for the details. In order to combat this AdapterBase.sol
ignores gifted assets when calculating totalAssets
. (To ensure correct functionality of rebasing tokens is the responsibility of the concrete adapter
-implementations).
Additionally creators
can send an initial deposit on vault/adapter creation to create some inital volume.
- If you have a public code repo, please share it here: - How many contracts are in scope?: 36 - Total SLoC for these contracts?: 2728 - How many external imports are there?: 8 - How many separate interfaces and struct definitions are there for the contracts within scope?: 18 interfaces, 10 structs - Does most of your code generally use composition or inheritance?: inheritance - How many external calls?: 21 - What is the overall line coverage percentage provided by your tests?: 94.52% - Is there a need to understand a separate part of the codebase / get context in order to audit this part of the protocol?: no - Please describe required context: - - Does it use an oracle?: no - Does the token conform to the ERC20 standard?: yes - Are there any novel or unique curve logic or mathematical models?: no - Does it use a timelock function?: yes - Is it an NFT?: no - Does it have an AMM?: no - Is it a fork of a popular project?: no - Does it use rollups?: no - Is it multi-chain?: no - Does it use a side-chain?: no
export ETH_RPC_URL="<your-eth-rpc-url>" && export POLYGON_RPC_URL="<your-polygon-rpc-url>" && rm -Rf 2023-01-popcorn || true && git clone https://github.com/code-423n4/2023-01-popcorn.git -j8 --recurse-submodules && cd 2023-01-popcorn && echo -e "ETH_RPC_URL=$ETH_RPC_URL\nPOLYGON_RPC_URL=$POLYGON_RPC_URL" > .env && foundryup && forge install && yarn install && forge test --no-match-contract 'Abstract' --gas-report
foundryup forge install yarn install
Add RPC urls to .env forge build forge test --no-match-contract 'Abstract'