Options trading for fractionalized NFTs using a peer-to-pool AMM Model.
🖌️ UI/UX Design: https://www.figma.com/file/3LVfwAKZuh5fqvdXdAwuxS/BlueBirdSwap
🖥️ Backend + Subgraph: https://github.com/Web3Rizzards/bluebirdswap
🖥️ Frontend: https://github.com/Web3Rizzards/new-frontend
💡 Live Site: https://bluebirdswap.vercel.app
Our motivation for creating Bluebird Swap is to provide investors with a new asset class that combines the benefits of non-fungible tokens (NFTs) with the flexibility of options trading. NFTs are unique digital assets that have gained popularity in recent years due to their ability to represent ownership and provenance of digital content. However, the high cost of some NFTs may make them inaccessible to many investors.
Fractionalization of NFTs can help address this issue by allowing investors to purchase a fraction of an NFT. This allows investors to gain exposure to high-value NFTs without having to pay the full price. Fractionalization can also increase liquidity in the NFT market, making it easier for investors to buy and sell NFTs.
Options trading can further enhance the flexibility and potential returns for investors in fractionalized NFTs. Options contracts provide the holder with the right, but not the obligation, to buy or sell an underlying asset at a predetermined price (the strike price) at or before a specific date (the expiration date). This means investors can use options to hedge against price fluctuations or generate additional income from their fractionalized NFT holdings.
In summary, a product for options trading of fractionalized NFTs can provide investors with a new asset class that combines the benefits of NFTs and options trading. This can increase accessibility to high-value NFTs, increase liquidity in the NFT market, and provide investors with more flexibility in managing their investments.
- User sees Product Logo + Login Button
- User logs in
- User sees interface
- User sees balance of BLUEBIRD $BB and ETH/MATIC
- Fade into main screen
- User logs in to the NFT fractionalization platform.
- User navigates to the "Fractionalize NFT" section of the platform.
- User selects an NFT from a dropdown collection that they own
- User selects the NFT they want to fractionalize
- User clicks the "Fractionalize" button.
- Platform creates a new ERC20 token for the shards and mints the total supply of shards corresponding to the NFT.
- Platform deposits the NFT into a secure smart contract and locks it until the shards are fully redeemed.
- Platform sends the newly created ERC20 tokens to the user's wallet and updates the user's NFT and ERC20 token balances on the platform dashboard.
- User can now trade their fractionalized NFT shards on the platform
- User logs in to the options trading platform.
- User navigates to the "Trade" section of the platform.
- Platform displays a list of available NFT collections, including the name of the collection, volume of options, and a status bar of puts vs pulls, and the stage of the option (Maker, Taker, Exercise)
- User selects the NFT collection they want to trade options on.
-
Platform displays a list of available options contracts for the selected NFT collection, including the expiration date, strike price, and premium.
-
Strike prices available would be (-30%, -20%, -10%, +10%, +20%, +30%) from at the money when the option starts retrieved from chainlink.
-
Platform shows the historical floor price of the collection from chainlink.
-
User selects the options contract they want to trade and clicks the "Buy" button.
-
Platform prompts the user to input the number of options contracts they want to purchase and shows the premium of buying those contracts
-
User inputs the quantity of contracts to buy
-
User places an order and signs a metamask transaction.
- If user wins, they should be able to see the tweets that they won
- On the tweet, there should be a claim button for the user to collect their prize
- User clicks on the claim button
- User signs metamask
- User sees updated balance
- User should be able to see the total amount bet
- User should see P/L
- User should be able to see the amount long / short on a particular tweet
An option premium is the price of an option contract. It is thus the income received by the seller (writer) of an option contract.
Options are priced based on the Black-Scholes formula:
where:
-
$C(S_t, t)$ is the price of a call option at time$t$ with strike price$K$ and expiry$T$ on an underlying asset with current price$S_t$ . -
$r$ is the risk-free interest rate -
$N$ is the cumulative distribution function of the standard normal distribution$d_1 = \frac{\ln(S_t/K) + (r + \frac{\sigma^2}{2})(T-t)}{\sigma \sqrt{T-t}}$ $d_2 = d_1 - \sigma \sqrt{T-t}$
Here,
- Setup new GitHub organization
- Create Monorepo
- frontend
- subgraph
- blockchain
- Create new private key for hackathon.
- Fund Account with testnet ETH/Matic
- Create Infura account and get API Key
- Create Figma
Link To Work (Github repo, Google Drive Dropbox etc):
https://github.com/Web3Rizzards/bluebirdswap
Demo URL
// TODO
Video URL
// TODO
Project Name
BluebirdSwap
Project Short Bio
Options trading for fractionalized NFTs using a peer-to-pool AMM Model.
Project Long Description
Project logo
Goerli Testnet
| Name | Description | Addresses |
|---|---|---|
| BluebirdManager | Manage the creation of option smart contracts | 0xcd32229b3D60990C75597009D8398367bCd77D8E |
| BluebirdGrinder | Fractionalize NFT and Reconstruct NFT from fragments | 0x503F5104361D4e0be9874D90d24Fdfd3c88e248F |
| BluebirdOptions - Azuki | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0x6e42ed27C4470aD83250Fb6947F4AfBCd6bac98e |
| BluebirdOptions - BBYC | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0x98aa30Ce2f37B230A065B5b1E39cF447122F675c |
| OptionPricing | Contract that holds the logic to price options with BlackScholes | 0x31dd4FD29b4e2DeeE184E2F05a179c922804A261 |
| MockOracle | Mock Chainlink oracle in place of any NFT price feeds that are not available on that specific chain | 0x3b2B8eD017Df41113E592fff03ab7F7Ca98d118F |
| Azuki | Mock Azuki contract, used in conjunction with actual Chainlink price feed oracle | 0xE88Fc6063B09D822b12Fcab33f77e5ab6336E1c0 |
| BBYC | Blue Bird Yacht Club contract, used as our sample NFT in this protocol | 0xd12C158F9CFf1a252B463F2c419Dca1f92872356 |
| bbBBYC | Fractionalised BBYC nft tokens | 0x2e02E42872550329ec835c99a00ad9903d72a1DC |
| bbAzuki | Fractionalised Azuki nft tokens | 0x525bb6caFeD1b97A654b250bb0a962578A8d2cf6 |
Base Testnet
| Name | Description | Addresses |
|---|---|---|
| BluebirdManager | Manage the creation of option smart contracts | 0xA960261A0926F02822543561f3ae0f86839b2Ea2 |
| BluebirdGrinder | Fractionalize NFT and Reconstruct NFT from fragments | 0x4aB59d8D18298261560aFcAf780E17Dc69B877d0 |
| BluebirdOptions - BBYC | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0xC9885Bfbc06a723d9C0627a4140B27810C1C62AB |
| OptionPricing | Contract that holds the logic to price options with BlackScholes | 0xc2a33a404e1fd76eddbF841A9327CD0e1BB4353e |
| MockOracle | Mock Chainlink oracle in place of any NFT price feeds that are not available on that specific chain | 0xfA3422b99515d78D889C0a8Ce866A8444A589fB8 |
| BBYC | Blue Bird Yacht Club contract, used as our sample NFT in this protocol | 0x07A583000b1C86b159e065D16c05fbD5A14f92A8 |
| bbBBYC | Fractionalised BBYC nft tokens | 0x52E25E5911b2003d4cfe572f374e20d8FF313F5E |
Mumbai Testnet
| Name | Description | Addresses |
|---|---|---|
| BluebirdManager | Manage the creation of option smart contracts | 0xbF0f6C964656D9493B831E72606E4b192AE82cA2 |
| BluebirdGrinder | Fractionalize NFT and Reconstruct NFT from fragments | 0x7A5A68f723000b6F99863464d1C3483a4A1A549c |
| BluebirdOptions - BBYC | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0x547b6c1A306f341CBc46766f73D5523dA8E476F5 |
| OptionPricing | Contract that holds the logic to price options with BlackScholes | 0xd79EEB728Fe4Fb7229Fa30D0e15A5C91a1D63C63 |
| MockOracle | Mock Chainlink oracle in place of any NFT price feeds that are not available on that specific chain | 0x3F7f1ACDe99F262A9200D220Bb1839bDAbDaA8a3 |
| BBYC | Blue Bird Yacht Club contract, used as our sample NFT in this protocol | 0x77f359C9e1F5a1264B931fca77523d99a7807b50 |
| bbBBYC | Fractionalised BBYC nft tokens | 0x7321aE89644aBD8b69e68479E5b59ada5FccDc80 |
Mantle Testnet
| Name | Description | Addresses |
|---|---|---|
| BluebirdManager | Manage the creation of option smart contracts | 0xA960261A0926F02822543561f3ae0f86839b2Ea2 |
| BluebirdGrinder | Fractionalize NFT and Reconstruct NFT from fragments | 0x4aB59d8D18298261560aFcAf780E17Dc69B877d0 |
| BluebirdOptions - BBYC | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0xC9885Bfbc06a723d9C0627a4140B27810C1C62AB |
| OptionPricing | Contract that holds the logic to price options with BlackScholes | 0xc2a33a404e1fd76eddbF841A9327CD0e1BB4353e |
| MockOracle | Mock Chainlink oracle in place of any NFT price feeds that are not available on that specific chain | 0xfA3422b99515d78D889C0a8Ce866A8444A589fB8 |
| BBYC | Blue Bird Yacht Club contract, used as our sample NFT in this protocol | 0x07A583000b1C86b159e065D16c05fbD5A14f92A8 |
| bbBBYC | Fractionalised BBYC nft tokens | 0x52E25E5911b2003d4cfe572f374e20d8FF313F5E |
Metis Testnet
| Name | Description | Addresses |
|---|---|---|
| BluebirdManager | Manage the creation of option smart contracts | 0x9c84b49574DBBe735B1ade34DBdA06C8e055eb36 |
| BluebirdGrinder | Fractionalize NFT and Reconstruct NFT from fragments | 0xeBCbEe60876e4481DcFBAE8A2983ebBc49AD624c |
| BluebirdOptions - BBYC | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0xd73df9049DE5e04a1Bb03893e0ee266f0544bf66 |
| OptionPricing | Contract that holds the logic to price options with BlackScholes | 0x1588996B29513f00C63c979A1b28b1454B1639F6 |
| MockOracle | Mock Chainlink oracle in place of any NFT price feeds that are not available on that specific chain | 0x3ca839f1E7E456464e2CEF5bd43E4e64aBFcFBff |
| BBYC | Blue Bird Yacht Club contract, used as our sample NFT in this protocol | 0xA960261A0926F02822543561f3ae0f86839b2Ea2 |
| bbBBYC | Fractionalised BBYC nft tokens | 0x92aB41E00310077603254D0D7b4B0BD9Ef60C996 |
Scroll Alpha Testnet
| Name | Description | Addresses |
|---|---|---|
| BluebirdManager | Manage the creation of option smart contracts | 0xB7FC58dA365D6E328362B5799ec8E9a7Ae13cA07 |
| BluebirdGrinder | Fractionalize NFT and Reconstruct NFT from fragments | 0x05CE628bFfB7be936bB659274210AFeefd454Dff |
| BluebirdOptions - BBYC | Contract that holds the logic for peer-to-pool automated options writing for a single NFT collection. | 0x45947030980cE2594b766F138F3D0174f0265cB9 |
| OptionPricing | Contract that holds the logic to price options with BlackScholes | 0xe41A822fA1F2Cb9823bd4654830CE8c59754537f |
| MockOracle | Mock Chainlink oracle in place of any NFT price feeds that are not available on that specific chain | 0x7A5A68f723000b6F99863464d1C3483a4A1A549c |
| BBYC | Blue Bird Yacht Club contract, used as our sample NFT in this protocol | 0xd79EEB728Fe4Fb7229Fa30D0e15A5C91a1D63C63 |
| bbBBYC | Fractionalised BBYC nft tokens | 0x3A29F2D351D56d5717dbc77fFca6749ee4A17Bbb |
Only can be issued by the BluebirdGrinder
address grinderAddress of the BluebirdGrinder contract
modifier onlyGrinder()Modifier to check if is called by the BluebirdGrinder
constructor(string _name, string _symbol, address _grinder) publicConstructor of the BB20 contract
| Name | Type | Description |
|---|---|---|
| _name | string | Name of the token |
| _symbol | string | Symbol of the token |
| _grinder | address | Address of the BluebirdGrinder contract |
function mint(address _receipient, uint256 _amount) externalMint BB20 Tokens
Only can be called by the BluebirdGrinder
| Name | Type | Description |
|---|---|---|
| _receipient | address | Address of the receipient |
| _amount | uint256 | Amount of tokens to mint |
function burn(uint256 amount) external returns (bool)Burn amount tokens and decreasing the total supply.
Only can be called by the BluebirdGrinder
| Name | Type | Description |
|---|---|---|
| amount | uint256 | Amount of tokens to burn |
function _isFactory() internal viewUsed in modifier to check if is called by the BluebirdGrinder
uint256 FRACTIONALISED_AMOUNTAmount of BB20 tokens to mint per NFT
1 NFT = 1 million BB20 tokens
mapping(address => struct EnumerableSet.UintSet) collectionToTokenIdsMapping of collection address to enumerable token Ids
mapping(address => contract BB20) nftAddressToTokenAddressMapping of NFT collection address to BB20 token address
mapping(address => bool) whitelistedMapping of collection address to boolean to check if collection is whitelisted
constructor() publicfunction fractionalizeNFT(address _collectionAddress, uint256 _tokenId) externalFunction to fractionalize NFTs into BB20 tokens
| Name | Type | Description |
|---|---|---|
| _collectionAddress | address | Address of NFT collection |
| _tokenId | uint256 | Token Id of NFT to fractionalize |
function reconstructNFT(address _collectionAddress, uint256 _tokenId) externalFunction to reconstruct NFTs from BB20 tokens
| Name | Type | Description |
|---|---|---|
| _collectionAddress | address | Address of NFT collection |
| _tokenId | uint256 | Token Id of NFT to reconstruct |
function whitelistNFT(address _collectionAddress) externalFunction to whitelist NFT collection
| Name | Type | Description |
|---|---|---|
| _collectionAddress | address | Address of NFT collection |
function getTokenFromCollection(address _collectionAddress) external view returns (contract IBB20)Function to get token address from collection address
| Name | Type | Description |
|---|---|---|
| _collectionAddress | address | Address of NFT collection |
function getIds(address _collectionAddress) external view returns (uint256[])Function to get all token ids from collection address that are in the contract
| Name | Type | Description |
|---|---|---|
| _collectionAddress | address | Address of NFT collection |
function concatenate(string _a, string _b) internal pure returns (string)Returns a concatenated string of a and b
| Name | Type | Description |
|---|---|---|
| _a | string | string a |
| _b | string | string b |
struct EnumerableSet.AddressSet optArrayArray of all options contract addresses
contract IOptionPricing optionPricingOption Pricing Contract
contract IBluebirdGrinder grinderBluebird Grinder Contract
mapping(address => bool) optionExistsMapping of NFT token address to boolean to check if options have been created
constructor(contract IOptionPricing _optionPricing, contract IBluebirdGrinder _grinder) publicConstructor for Bluebird Manager
| Name | Type | Description |
|---|---|---|
| _optionPricing | contract IOptionPricing | Option Pricing Contract |
| _grinder | contract IBluebirdGrinder | Bluebird Grinder Contract |
modifier onlyOptions()Modifier to check if msg.sender is an Options Contract
function createOptions(address _collectionAddress, address _nftFeedAddress) publicCreate a Put and Call Options for a specified collection for the current epoch
| Name | Type | Description |
|---|---|---|
| _collectionAddress | address | Collection Address |
| _nftFeedAddress | address | Chainlink Feed Address |
function getOptArray() external view returns (address[])Function to retrieve options array
function emitCallOptionCreatedEvent(address _contractAddress, uint256 _optionId, uint256 _epoch, address _nftToken, uint256 _strikePrice, uint256 _start, uint256 _expiry) externalProxy function to emit event from options contract
| Name | Type | Description |
|---|---|---|
| _contractAddress | address | Address of options contract |
| _optionId | uint256 | Option ID |
| _epoch | uint256 | Epoch |
| _nftToken | address | NFT Token Address |
| _strikePrice | uint256 | Strike Price |
| _start | uint256 | Start Time |
| _expiry | uint256 | Expiry Time |
function emitPutOptionCreatedEvent(address _contractAddress, uint256 _optionId, uint256 _epoch, address _nftToken, uint256 _strikePrice, uint256 _start, uint256 _expiry) externalProxy function to emit event from options contract
| Name | Type | Description |
|---|---|---|
| _contractAddress | address | Address of options contract |
| _optionId | uint256 | Option ID |
| _epoch | uint256 | Epoch |
| _nftToken | address | NFT Token Address |
| _strikePrice | uint256 | Strike Price |
| _start | uint256 | Start Time |
| _expiry | uint256 | Expiry Time |
function emitBoughtEvent(address _contractAddress, address _user, uint256 _order, uint256 _amount, uint256 _premium, uint256 _timestamp, uint256 _epoch) externalProxy function to emit event from options contract
| Name | Type | Description |
|---|---|---|
| _contractAddress | address | Address of options contract |
| _user | address | User Address |
| _order | uint256 | Order ID |
| _amount | uint256 | Amount |
| _premium | uint256 | Premium |
| _timestamp | uint256 | Timestamp |
| _epoch | uint256 | Epoch |
function emitExerciseEvent(address _contractAddress, address _user, uint256 _id, uint256 _pnl, bool _profit) externalProxy function to emit event from options contract
| Name | Type | Description |
|---|---|---|
| _contractAddress | address | Address of options contract |
| _user | address | User Address |
| _id | uint256 | Order ID |
| _pnl | uint256 | PnL |
| _profit | bool | Profit |
Only can be issued by the BluebirdManager
contract AggregatorV3Interface nftFeedPrice feed interface used for getting the latest price
contract IERC20 nftTokenFractionalised NFT Token
contract IBluebirdManager bluebirdManagerBluebird Manager contract
contract IOptionPricing optionPricingOption pricing contract
uint256 EXPIRYExpiry time of options in seconds
uint256 startTimeEpochStart time of epoch in seconds
uint256 intervalInterval of chainlink round update
uint256 epochCurrent epoch number
uint256 liquidityProvidingTimeAmount of time in which market makers can provide liquidity
uint256 currentIdCurrent Id of options
uint256 maxBuyCallMaximum amount of options that a user can buy for calls
uint256 maxBuyPutMaximum amount of options that a user can buy for puts
mapping(address => mapping(uint256 => uint256)) userDepositsMapping of user to amount of NFT tokens or ETH deposited to providing liquidity
mapping(uint256 => struct IBluebirdOptions.Option) nftOptsMapping to track each option
mapping(address => mapping(uint256 => uint256)) userToOptionIdToAmountMapping of user to option id to amount of options bought
mapping(address => mapping(uint256 => bool)) exercisedMapping which checks if current id has been exercised
mapping(uint256 => mapping(bool => uint256[])) epochToStrikePricesMapping of epoch to isPut to strike prices
constructor(contract AggregatorV3Interface _nftFeed, contract IBB20 _nftToken, address _bluebirdManager, contract IOptionPricing _optionsPricing, address _owner) publicConstructor of Bluebird Options
| Name | Type | Description |
|---|---|---|
| _nftFeed | contract AggregatorV3Interface | Price feed of NFT |
| _nftToken | contract IBB20 | Fractionalised NFT Token |
| _bluebirdManager | address | Bluebird Manager contract |
| _optionsPricing | contract IOptionPricing | Option pricing contract |
| _owner | address | Owner of contract |
function setLiquidityProvidingTime(uint256 _liquidityProvidingTime) externalSet liquidity providing time
| Name | Type | Description |
|---|---|---|
| _liquidityProvidingTime | uint256 | Time to provide liquidity |
function setExpiry(uint256 _expiry) externalSet expiry
| Name | Type | Description |
|---|---|---|
| _expiry | uint256 | Expiry of options |
function setInterval(uint256 _interval) externalSet interval
| Name | Type | Description |
|---|---|---|
| _interval | uint256 | interval of chainlink round update |
function _calculateStrikePrices(uint256 _floorPrice, bool _isPut) internal pure returns (uint256[])Function to calculate strike prices
| Name | Type | Description |
|---|---|---|
| _floorPrice | uint256 | Floor price of NFT |
| _isPut | bool | Whether option is put or call |
function startEpoch() publicFunction to start epoch
function writeOption() publicWrites options
Only owner/controller should be able to trigger this
function getPremium(uint256 _id) public view returns (uint256)Get premium of an option
| Name | Type | Description |
|---|---|---|
| _id | uint256 | Id of contract |
function getNftPrice() public view returns (uint256)Returns the price of NFT from oracle
| Name | Type | Description |
|---|---|---|
| [0] | uint256 | Price of NFT |
function getStage() public view returns (uint256 _stage)Get current stage of contract
| Name | Type | Description |
|---|---|---|
| _stage | uint256 | Stage of contract |
function getHistoricalPrices() public view returns (uint256[])Returns the historical prices of NFT
| Name | Type | Description |
|---|---|---|
| [0] | uint256[] | Historical prices of NFT |
function getStrikes(uint256 _epoch, bool _isPut) external view returns (uint256[])Returns the strike prices of an epoch
| Name | Type | Description |
|---|---|---|
| [0] | uint256[] | uint256[] memory Array of strike prices |
function depositNftToken(uint256 amount) publicProvide liquidity by depositing NFT tokens
| Name | Type | Description |
|---|---|---|
| amount | uint256 | Amount of NFT tokens to deposit |
function depositETH() public payableProvide liquidity by depositing ETH
function buy(uint256 _id, uint256 _amount) externalBuy an option based on _id
| Name | Type | Description |
|---|---|---|
| _id | uint256 | Index of the option |
| _amount | uint256 | Amount of options to buy |
function calculateAmountETH(uint256 _id) public view returns (uint256)Calculate amount of ETH to be received when exercising an option, for calls only
| Name | Type | Description |
|---|---|---|
| _id | uint256 | Index of the option |
| Name | Type | Description |
|---|---|---|
| [0] | uint256 | Amount of ETH to be received |
function exercise(uint256 _id) external payableExercise an option based on _id
| Name | Type | Description |
|---|---|---|
| _id | uint256 | Id of option to exercise |
Only can be issued by the BluebirdGrinder
event Minted(address to, uint256 amount)function mint(address _receipient, uint256 _amount) externalMint BB20 Tokens
function burn(uint256 amount) external returns (bool)Burn amount tokens and decreasing the total supply.
| Name | Type | Description |
|---|---|---|
| amount | uint256 | Amount of tokens to burn |
