Platform: Code4rena
Start Date: 07/07/2022
End Date: 14/07/2022
Period: 7 days
Status: Completed
Pot Size: $75,000 USDC
Participants: 141
Reporter: itsmetechjay
Judge: HardlyDifficult
Id: 144
League: ETH
kenzo | 1/141 | $6,232.65 | 12 | 9 | 1 | 2 | 0 | - | 0 | 0 |
0x29A | 2/141 | $5,286.12 | 9 | 4 | 0 | 3 | 1 | - | - | 0 |
cccz | 3/141 | $4,819.19 | 7 | 3 | 1 | 3 | 0 | - | 0 | 0 |
0x52 | 4/141 | $4,661.54 | 11 | 8 | 0 | 2 | 0 | - | 0 | 0 |
hansfriese | 5/141 | $4,474.07 | 9 | 7 | 0 | 1 | 0 | - | 0 | 0 |
zzzitron | 6/141 | $3,913.01 | 10 | 7 | 0 | 2 | 0 | - | 0 | 0 |
Treasure-Seeker | 7/141 | $3,225.92 | 11 | 7 | 0 | 3 | 0 | - | 0 | 0 |
TrungOre | 8/141 | $2,538.81 | 8 | 5 | 0 | 1 | 0 | - | - | 0 |
PwnedNoMore | 9/141 | $2,435.83 | 7 | 4 | 0 | 2 | 0 | 0 | - | 0 |
scaraven | 10/141 | $2,299.42 | 6 | 2 | 0 | 3 | 0 | - | 0 | 0 |
Auditor per page
This contest is open for one week to give wardens time to understand the protocol properly. Representatives from Fractional will be available in the Code Arena Discord to answer any questions during the contest period. The focus of the contest is to try and find any logic errors, mint/burn fractions unexpectedly, or ways to remove NFTs from the Fractional Vaults in ways that would be beneficial for an attacker at the expense of vault creators or fraction holders. Wardens should assume that governance variables are set sensibly (unless they can find a way to change the value of a governance variable, and not counting social engineering approaches for this).
The Fractional v2 Protocol is designed around the concept of Hyperstructures
Hyperstructures: Crypto protocols that can run for free and forever, without maintenance, interruption, or intermediaries
Fractional is a decentralized protocol that allows for shared ownership and governance of NFTs. When an NFT is fractionalized, the newly minted tokens function as normal ERC-1155 tokens which govern the non-custodial Vault containing the NFT(s).
The home of all items on Fractional
Vaults are a slightly modified implementation of PRBProxy which is a basic and non-upgradeable proxy contract. Think of a Vault as a smart wallet that enables the execution of arbitrary smart contract calls in a single transaction. Generally, the calls a Vault can make are disabled and must be explicitly allowed through permissions. The vault is intentionally left unopinionated and extremely flexible for experimentation in the future.
Authorize transactions performed on a vault
A permission is a combination of a Module contract, Target contract, and specific function Selector in a target contract that can be executed by the vault. A group of permissions creates the set of functions that are callable on the Vault in order to carry out its specific use case. Each permission is then hashed and used as a leaf node to generate a merkle tree, where the merkle root of the tree is stored on the vault itself. Whenever a transaction is executed on a vault, a merkle proof is used to verify legitimacy of the leaf node (Permission) and the Merkle root.
For example, a vault involved in an active buyout will need permission to burn fractional tokens. Therefore, a permission will be set on the deployment of the vault that consists of the Buyout
contract address (Module), Supply
contract address (Target), and a burn function (Selector) which is declared in the Supply
contract. This same process will then be repeated for all pre-defined actions that a vault may want, such as minting fractional tokens or transferring assets out of the vault.
Make vaults do cool stuff
Modules are the bread and butter of what makes Fractional unique. At Vault creation, modules are added to permissions for the vault. Each module should have specific goals it plans to accomplish. Some general examples are Buyouts, Inflation, Migration, and Renting. If a vault wants to update the set of modules enabled, then it must have the migration module enabled and go through the migration process.
In general, it is highly recommended for vaults to have a module that enables items to be removed from vaults. Without this, all items inside of a vault will be stuck forever.
Protoforms are templates for common vault use-cases
Protoforms aggregate static sets of module permissions to deploy vaults with similar base functionality. Protoforms are the main entry point for deploying a vault with a certain use-case determined by the modules that are enabled on a vault.
Execute vault transactions
Targets are stateless script-like contracts for executing transactions by the Vault on-behalf of a user. Only functions of a target contract that are initially set as enabled permissions for a vault can be executed by a vault.
All the contracts in this section are to be reviewed. Any contracts not in this list are to be ignored for this contest.
File | nSLOC | Lines | Description |
---|---|---|---|
src/FERC1155.sol | 195 | 398 | ERC-1155 implementation for Fractional tokens |
src/Vault.sol | 80 | 148 | Proxy contract for storing fractionalized assets |
src/VaultFactory.sol | 50 | 90 | Factory contract for deploying fractional vaults |
src/VaultRegistry.sol | 75 | 178 | Registry contract for tracking all fractional vaults and deploying token contracts |
src/constants/Memory.sol | 14 | 20 | Global list of constants used for assembly optimizations |
src/constants/Permit.sol | 10 | 17 | Global list of constants used for EIP-712 permit functionality |
src/constants/Supply.sol | 28 | 40 | List of constants used inside the Supply target contract |
src/constants/Transfer.sol | 80 | 129 | List of constants used inside the Transfer target contract |
src/interfaces/IBaseVault.sol | 6 | 46 | Interface for BaseVault protoform contract |
src/interfaces/IBuyout.sol | 38 | 159 | Interface for Buyout module contract |
src/interfaces/IERC1155.sol | 23 | 60 | Interface for generic ERC-1155 contract |
src/interfaces/IERC20.sol | 9 | 48 | Interface for generic ERC-20 contract |
src/interfaces/IERC721.sol | 18 | 63 | Interface for generic ERC-721 contract |
src/interfaces/IFERC1155.sol | 20 | 135 | Interface for FERC1155 token contract |
src/interfaces/IMigration.sol | 42 | 168 | Interface for Migration module contract |
src/interfaces/IMinter.sol | 5 | 10 | Interface for Minter contract |
src/interfaces/IModule.sol | 4 | 14 | Interface for generic Module contract |
src/interfaces/INFTReceiver.sol | 3 | 28 | Interface for NFTReceiver contract |
src/interfaces/IProtoform.sol | 4 | 20 | Interface for generic Protoform contract |
src/interfaces/ISupply.sol | 5 | 14 | Interface for Supply targert contract |
src/interfaces/ITransfer.sol | 26 | 79 | Interface for Transfer target contract |
src/interfaces/IVault.sol | 17 | 65 | Interface for Vault proxy contract |
src/interfaces/IVaultFactory.sol | 11 | 34 | Interface for VaultFactory contract |
src/interfaces/IVaultRegistry.sol | 19 | 92 | Interface for VaultRegistry contract |
src/modules/Buyout.sol | 293 | 504 | Module contract for vaults to hold buyout pools |
src/modules/Migration.sol | 305 | 548 | Module contract for vaults to migrate to a new set of permissions |
src/modules/Minter.sol | 30 | 62 | Module contract for minting a fixed supply of fractions |
src/modules/protoforms/BaseVault.sol | 68 | 138 | Protoform contract for vault deployments with a fixed supply and buyout mechanism |
src/references/SupplyReference.sol | 15 | 32 | Reference implementation for the optimized Supply target contract |
src/references/TransferReference.sol | 19 | 70 | Reference implementation for the optimized Transfer target contract |
src/targets/Supply.sol | 114 | 199 | Target contract for minting and burning fractional tokens |
src/targets/Transfer.sol | 444 | 703 | Target contract for transferring fungible and non-fungible tokens |
src/utils/MerkleBase.sol | 101 | 193 | Utility contract for generating merkle roots and verifying proofs |
src/utils/Metadata.sol | 19 | 39 | Utility contract for storing metadata of an FERC1155 token |
src/utils/Multicall.sol | 26 | 45 | Utility contract that enables calling multiple local methods in a single call |
src/utils/SafeSend.sol | 17 | 36 | Utility contract for sending Ether or WETH value to an address |
src/utils/SelfPermit.sol | 27 | 64 | Utility contract for executing a permit signature to update the approval status of an FERC1155 token |
Total: | 2274 | 4730 |
External Contracts: IERC20
, IERC721
, IERC1155
, IModule
, IVaultRegistry
External Contracts: IERC1155
, ISupply
, ITransfer
, IVault
, IVaultRegistry
External Contracts: IProtoform
External Contracts: IModule
External Contracts: IModule
External Contracts: IFERC1155
, INFTReceiver
Libraries: clones-with-immutable-args/src/Clone.sol, @rari-capital/solmate/src/tokens/ERC1155.sol
External Contracts: IBuyout
, IERC20
, IERC721
, IERC1155
, IFERC1155
, IModule
, IVaultRegistry
Libraries: @rari-capital/solmate/src/utils/ReentrancyGuard.sol
External Contracts: IVault
Libraries: @rari-capital/solmate/src/tokens/WETH.sol
External Contracts: IVaultRegistry
External Contracts: IERC20
, IERC721
, IERC1155
Libraries: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol
External Contracts: Vault
Libraries: clones-with-immutable-args/src/Create2ClonesWithImmutableArgs.sol
External Contracts: FERC1155
, IVault
, VaultFactory
Libraries: clones-with-immutable-args/src/ClonesWithImmutableArgs.sol
We would like wardens to focus on any core functional logic, boundary case errors, or similar issues which could be utilized by an attacker to take assets away from fraction holders or vault curators who deposit assets into the Vaults. Any errors may be submitted by wardens for review and potential reward as per the normal issue impact prioritization. Gas optimizations are welcome but not the main focus of this contest and thus at most 5% of the contest reward will be allocated to gas optimizations. For gas optimizations, the most important flows are BaseVault deployment, buyout claims/withdrawals, and migration flows.
If wardens are unclear on which areas to look at or which areas are important please feel free to ask in the contest Discord channel.
A full set of unit tests are provided in the repo. To run these do the following:
Required node >12
run make deps
in root directory - Installs gitmodule dependencies
create .env
file in root directory and add the following:
ALCHEMY_API_KEY=0000000000000000000000000000000000000000000000000000000000000000 DEPLOYER_PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000000 ETHERSCAN_API_KEY=0000000000000000000000000000000000000000000000000000000000000000
run npm ci
in root directory - Installs node dependencies
run make users
- Generates user proxies
run make test
- Runs foundry tests
Slither will fail when you try to run it locally due to issues with top-level constants inside Yul blocks as well as custom reverts being used from interface contracts that are not inherited. If you would still like to run it, the following commands will need to be run to fix those issues:
curl https://gist.githubusercontent.com/mehtaculous/5794ad3a8bcde2c0a52015d546acc741/raw/47210d6c67d273bbb70e558958054d678d43db5b/Supply.sol > src/targets/Supply.sol
curl https://gist.githubusercontent.com/mehtaculous/642887f238dd55dda6a20cdf9b5a5474/raw/22212bd1848d1316085371d33647f650d307c591/Transfer.sol > src/targets/Transfer.sol
curl https://gist.githubusercontent.com/mehtaculous/b17776dc0d0c5c93948c10361d37cfe1/raw/892f9ac1894f12c40cf731e047a0a328f2c4d0fa/Metadata.sol > src/utils/Metadata.sol
curl https://gist.githubusercontent.com/mehtaculous/9c094ce7d652dd7d552a6dc5501c7fef/raw/a418270fe54f61b328fa0be8a27d0dadb09a2567/Migration.sol > src/modules/Migration.sol
Name | Description |
---|---|
Blacksmith | Full-fledged contract generator to create User contracts for testing purposes |
ClonesWithImmutableArgs | Enables creating clone contracts with immutable arguments |
Forge Standard Library | Leverages forge's cheatcodes to make writing tests easier and faster in Foundry |
Foundry | Framework for Ethereum application development |
Hardhat | Development environment for deploying and interacting with smart contracts |
Multicall (Uniswap v3) | Enables calling multiple methods in a single call to the contract |
Murky | Generates merkle roots and verifies proofs in Solidity |
NatSpec Format | A special form of comments to provide rich documentation |
OpenZeppelin | Library of community-vetted code for secure smart contract development |
PRBProxy | Proxy contract to compose Ethereum transactions on behalf of the owner |
Seaport | Library for performing optimized token transfers from OpenSea's new marketplace protocol |
Solidity Style Guide | Standard coding conventions for writing Solidity code |
Solmate | Building blocks for smart contract development |