This project demonstrates a basic NFT fractional ownership protocol.
The contract allows you to deposit, fractionalize NFT and then sell/buy the fractions.
Deposit NFT, before the transfer should be approved for the contract address.
Fractionalize already deposited NFT.
Publish for selling ERC20 fractions.
Execute all three the above operations in single call.
Buy ERC20 fractions.
Allows you to buy the NFT after you have all the ERC20 fractions.
Returns all NFTs fractions for sale from all users.
Returns all deposited NFTs for the given user.
Returns all fractions that user bought.
Returns the user profit from NFT fractions sales.
Withdraws the user profit from NFT sales fractions sales.
Returns the minimum withdraw.
Set the minimum withdraw amount.
Generates unique token id from NFT contract address and NFT token id.
All deposited NFTs are stored inside mapping(address => mapping(uint => Token)) private usersTokens
first key is the address of the NFT owner and second is unique token id that is generated by getUniqueTokenId
function. When we sell/buy tokens we will use the unique token id to refer to specific token.
The TokenLink structure is used to reference a given NFT Token structure.
struct TokenLink {
address owner;
uint uniqueTokenId;
}
owner
- first key in usersTokens
, address of the token owner.
uniqueTokenId
- second key in usersTokens
.
The Token structure contains all necesssary properties for fractionalization and selling the tokens.
struct Token {
bool initialized;
address tokenContract;
uint tokenId;
bool fractionalized;
ERC20 fractionsContract;
uint weiPricePerToken;
bool forSale;
bool soldOut;
TokenLink prev;
TokenLink next;
}
initialized
- used to check if token was deposited for this user already.
tokenContract
- NFT token contract address.
tokenId
- NFT token id.
fractionalized
- used to check if token was fractionalized.
fractionsContract
- Contract that will be initialized during fractionalization and will hold supply of ERC20 tokens (NFT fractions) for selling.
weiPricePerToken
- price per ERC20 token in wei.
forSale
- used to check if token is currently for sale.
soldOut
- used to check if this token fractions were already sold.
prev
- points to previous token in the list, used for iteration of all NFTs.
next
- points to next token in the list, used for iteration of all NFTs.
When NFT is deposited usersTokens
entry is created, after that when its fractionalized, fractionsContract
is initialized, next when its published for sale, weiPricePerToken
is set.
To allow iteration over usersTokens
the mapping itself is also doubly linked list. usersTokensTail
is pointing to the last element of the list and all new elements are appended after it.
During buy
execution if all tokens are sold out, soldOut
property will be set to true
. The entry will be deleted when the NFT is bought back by someone who holds all the fractions.
These are structures that are used only to return data to the UI.
struct TokenUI {
address tokenContract;
uint tokenId;
uint fractionsTotalSupply;
uint availableFractions;
uint weiPricePerToken;
uint uniqueTokenId;
bool forSale;
bool soldOut;
}
struct UserNFTUI {
bool fractionalized;
TokenUI token;
}
struct BoughtFractionUI {
uint amount;
TokenUI token;
}
Simple contract that generates ERC721 and is used only for testing the FractionalizeNFT contract.