Contest ran 7 July 202214 July 2022

7 day contest

Fractional v2 contest

A collective ownership platform for NFTs on Ethereum.

$75,000 USDC

Total Awards

Fractional v2 contest details

Contest Scope

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).

Protocol Overview

Gitbook

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).

Vaults

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.

Permissions

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.

Modules

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

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.

Targets

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.

Smart Contracts

All the contracts in this section are to be reviewed. Any contracts not in this list are to be ignored for this contest.

FilenSLOCLinesDescription
src/FERC1155.sol195398ERC-1155 implementation for Fractional tokens
src/Vault.sol80148Proxy contract for storing fractionalized assets
src/VaultFactory.sol5090Factory contract for deploying fractional vaults
src/VaultRegistry.sol75178Registry contract for tracking all fractional vaults and deploying token contracts
src/constants/Memory.sol1420Global list of constants used for assembly optimizations
src/constants/Permit.sol1017Global list of constants used for EIP-712 permit functionality
src/constants/Supply.sol2840List of constants used inside the Supply target contract
src/constants/Transfer.sol80129List of constants used inside the Transfer target contract
src/interfaces/IBaseVault.sol646Interface for BaseVault protoform contract
src/interfaces/IBuyout.sol38159Interface for Buyout module contract
src/interfaces/IERC1155.sol2360Interface for generic ERC-1155 contract
src/interfaces/IERC20.sol948Interface for generic ERC-20 contract
src/interfaces/IERC721.sol1863Interface for generic ERC-721 contract
src/interfaces/IFERC1155.sol20135Interface for FERC1155 token contract
src/interfaces/IMigration.sol42168Interface for Migration module contract
src/interfaces/IMinter.sol510Interface for Minter contract
src/interfaces/IModule.sol414Interface for generic Module contract
src/interfaces/INFTReceiver.sol328Interface for NFTReceiver contract
src/interfaces/IProtoform.sol420Interface for generic Protoform contract
src/interfaces/ISupply.sol514Interface for Supply targert contract
src/interfaces/ITransfer.sol2679Interface for Transfer target contract
src/interfaces/IVault.sol1765Interface for Vault proxy contract
src/interfaces/IVaultFactory.sol1134Interface for VaultFactory contract
src/interfaces/IVaultRegistry.sol1992Interface for VaultRegistry contract
src/modules/Buyout.sol293504Module contract for vaults to hold buyout pools
src/modules/Migration.sol305548Module contract for vaults to migrate to a new set of permissions
src/modules/Minter.sol3062Module contract for minting a fixed supply of fractions
src/modules/protoforms/BaseVault.sol68138Protoform contract for vault deployments with a fixed supply and buyout mechanism
src/references/SupplyReference.sol1532Reference implementation for the optimized Supply target contract
src/references/TransferReference.sol1970Reference implementation for the optimized Transfer target contract
src/targets/Supply.sol114199Target contract for minting and burning fractional tokens
src/targets/Transfer.sol444703Target contract for transferring fungible and non-fungible tokens
src/utils/MerkleBase.sol101193Utility contract for generating merkle roots and verifying proofs
src/utils/Metadata.sol1939Utility contract for storing metadata of an FERC1155 token
src/utils/Multicall.sol2645Utility contract that enables calling multiple local methods in a single call
src/utils/SafeSend.sol1736Utility contract for sending Ether or WETH value to an address
src/utils/SelfPermit.sol2764Utility contract for executing a permit signature to update the approval status of an FERC1155 token
Total:22744730

BaseVault.sol

External Contracts: IERC20, IERC721, IERC1155, IModule, IVaultRegistry

Buyout.sol

External Contracts: IERC1155, ISupply, ITransfer, IVault, IVaultRegistry

IBaseVault.sol

External Contracts: IProtoform

IBuyout.sol

External Contracts: IModule

IMinter.sol

External Contracts: IModule

FERC1155.sol

External Contracts: IFERC1155, INFTReceiver

Libraries: clones-with-immutable-args/src/Clone.sol, @rari-capital/solmate/src/tokens/ERC1155.sol

Migration.sol

External Contracts: IBuyout, IERC20, IERC721, IERC1155, IFERC1155, IModule, IVaultRegistry

Libraries: @rari-capital/solmate/src/utils/ReentrancyGuard.sol

Minter.sol

External Contracts: IVault

SafeSend.sol

Libraries: @rari-capital/solmate/src/tokens/WETH.sol

Supply.sol

External Contracts: IVaultRegistry

Transfer.sol

External Contracts: IERC20, IERC721, IERC1155

Vault.sol

Libraries: @openzeppelin/contracts/utils/cryptography/MerkleProof.sol

VaultFactory.sol

External Contracts: Vault

Libraries: clones-with-immutable-args/src/Create2ClonesWithImmutableArgs.sol

VaultRegistry.sol

External Contracts: FERC1155, IVault, VaultFactory

Libraries: clones-with-immutable-args/src/ClonesWithImmutableArgs.sol

Areas of concern for Wardens

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.

Tests

A full set of unit tests are provided in the repo. To run these do the following:

Prepare Environment

  1. install node, refer to nodejs

  2. install foundry, refer to foundry

Setup Environment

Required node >12

  1. run make deps in root directory - Installs gitmodule dependencies

  2. create .env file in root directory and add the following:

ALCHEMY_API_KEY=0000000000000000000000000000000000000000000000000000000000000000
DEPLOYER_PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000000
ETHERSCAN_API_KEY=0000000000000000000000000000000000000000000000000000000000000000
  1. run npm ci in root directory - Installs node dependencies

  2. run make users - Generates user proxies

  3. run make test - Runs foundry tests

Slither

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

Glossary

NameDescription
BlacksmithFull-fledged contract generator to create User contracts for testing purposes
ClonesWithImmutableArgsEnables creating clone contracts with immutable arguments
Forge Standard LibraryLeverages forge's cheatcodes to make writing tests easier and faster in Foundry
FoundryFramework for Ethereum application development
HardhatDevelopment environment for deploying and interacting with smart contracts
Multicall (Uniswap v3)Enables calling multiple methods in a single call to the contract
MurkyGenerates merkle roots and verifies proofs in Solidity
NatSpec FormatA special form of comments to provide rich documentation
OpenZeppelinLibrary of community-vetted code for secure smart contract development
PRBProxyProxy contract to compose Ethereum transactions on behalf of the owner
SeaportLibrary for performing optimized token transfers from OpenSea's new marketplace protocol
Solidity Style GuideStandard coding conventions for writing Solidity code
SolmateBuilding blocks for smart contract development