Web3 platform enabling fractional investment in luxury assets, allowing users to invest in high-value items such as cars, watches, and yachts starting from just $100. Whether you're a web3 degen or a newbie, pieces.market welcomes you to explore fractionalized luxury assets. With intuitive features like traditional login methods and a built-in self-custody wallet, pieces.market extends a welcoming hand to individuals new to the web3 world.
At pieces.market you can find many brokers, such as auction houses, specialized agents or producers, offering a wide selection of luxury assets from all over the world. Each broker is carefully screened and each document related to the broker or the asset is verified by independent legal officers and placed on the blockchain. Thanks to this, you can verify all the most important information about the auction and rules of asset management before purchasing.
-
Aleph Zero Testnet
- Auctioner: 0x3293c12a0E0A107f8eed5517558B494c290d949b
- Governor: 0xAc8578b94a5c1A70F40ce7270ce840d0ea1AF777
-
Aleph Zero Testnet Development Contracts
- Auctioner: 0xb15Ca6B9438a0F425a5933B16B8f061dE5ed26a4
- Governor: 0x86115882c55b284476d98A97D8dA889a75C10569
-
Sepolia Testnet Development Contracts
- Auctioner: 0xbD1A8dE0d2B979bD45E4F6B65D2f32e93dae51eC
- Governor: 0xA6745DD89dCbdAd754A1bBE08Cda003A3B24f2B5
- Mock transactions on Aleph Zero testnet blockchain to reproduce all possible states of auction along with proposals and other possible transactions and branches
- Implement fee's into 'Auctioner' 'buy' function
- Refactor 'Auctioner' functions to check equivalent of USD value instead of native blockchain currency (we will be using Oracles to get proper price feeds here)
- Implement Vlayer solution into 'Auctioner' 'fulfill' function to ensure cryptographic proof has been provided via email or other credentials
- Implement Cross Chain solution
- Consider implementing starting/minimal price for example 100 USD per piece
- Consider refactor for 'Propose' events on 'Auctioner' and 'Governor' to keep 'ProposalType' only in one of those and avoid duplication
This project is a decentralized auction system that uses smart contracts to manage auctions, mint NFTs (assets), and facilitate user interactions such as buying, proposing changes, voting on those changes, claiming revenues, and more. The system comprises several key contracts: Auctioner
, Asset
, and Governor
. Whole blockchain part has been built and fully tested using Solidity
language and Foundry
framework. Libraries used to build this project were fully audited and are free and save to use. All contracts has been already optimized gas wise, tested and are protected with solid usage restrictions.
-
Auction Preparation:
- The auction preparation is carried out by a broker, who inputs the detailed information about the asset being auctioned and uploads all relevant investment documents associated with the investment.
-
Auction Creation:
- The Contract Owner (admin of the platform) reviews the details prepared by the broker. If the admin has no objections, the auction is approved on the platform. This approval triggers the creation of the necessary smart contracts and the upload of documents to IPFS, ensuring they are linked to the specific smart contract and enabling immutable and decentralized storage.
-
Purchasing Pieces:
- At a predefined moment, the auction opens, allowing users to purchase pieces by sending the required funds. Once all pieces are sold, the auction is automatically closed, and the funds from the sale are transferred directly to the broker.
-
Refunds:
- If the auction does not succeed (not all pieces are sold within the specified timeframe), users who participated are eligible for a refund. The amount returned to each participant is proportional to their contribution, ensuring that all funds are safely returned if the auction does not reach its goal.
-
Proposals:
- Users have the ability to propose two types of changes: buyouts or descriptive updates to the auction. These proposals are managed and voted on through the Governor contract.
- Buyout Proposals: Enable users to propose an immediate purchase of the entire asset by transferring the required funds.
- Descriptive Proposals: Allow updates to the auction’s description, but only the Foundation is permitted to make these changes.
- Users have the ability to propose two types of changes: buyouts or descriptive updates to the auction. These proposals are managed and voted on through the Governor contract.
-
Withdrawals:
- If a buyout proposal is rejected, the user who made the offer can withdraw the funds.
-
Auction Finalization:
- If the asset is sold according to the initial investment terms or through a successful buyout proposal, and the funds are deposited into the smart contract, users can claim their share of the revenue by burning the pieces they hold.
Gelato automation system periodically checks the state of auctions and execute required functions, such as finalizing auctions updating their states etc.
The Auctioner contract is responsible for managing auctions within the platform. It includes functionality to start new auctions, place orders, and close auctions once a buying period is over. It also tracks the state of each auction and ensures that the auction rules (e.g., minimum bid increments, auction duration) are enforced. This contract interacts with assets and governs their sale or transfer based on auction outcomes.
UNINITIALIZED:
Auction has not been initialized and does not exist on blockchainSCHEDULED:
Auction has been initialized on blockchain and awaits its start dateOPENED:
Auction ready to get orders for asset piecesCLOSED:
Auction finished positively - all asset pieces soldFAILED:
Auction finished negatively - not all asset pieces sold in given time, buyers can refundFINISHED:
All funds gathered from closed auction have been transferred to broker and broker transferred revenues to contract, buyers can claim revenuesARCHIVED:
Everyone claimed their revenues, investment ultimately closed
BUYOUT:
Proposal option to buy the entire asset instantly for a specified amountDESCRIPT:
Proposal option for anything typed in description
address asset:
Address of NFT related to auctioned assetuint256 price:
Single piece of asset priceuint256 pieces:
Total number of pieces available for saleuint256 max:
Maximum number of pieces one user can buyuint256 openTs:
Timestamp when the auction opensuint256 closeTs:
Timestamp when the auction endsaddress recipient:
Wallet address where funds from asset sale will be transferredbool buyoutProposalActive:
Boolean indicating if there is a buyout proposal in progress as there is one proposal of each type allowed at the timebool descriptProposalActive:
Boolean indicating if there is a descript proposal in progress as there is one proposal of each type allowed at the timeaddress offerer:
Wallet address of the buyout offerermapping(address offerer => uint amount) offer:
Mapping to track the amount that has been offeredmapping(address offerer => bool) withdrawAllowed:
Mapping to track if the offerer is allowed to withdraw the offerAuctionState state:
Current state of the auction
Create:
Emitted when a new auction is created on blockchainSchedule:
Emitted when auction is created with open timestamp in futurePurchase:
Emitted when pieces of an auction are boughtPropose:
Emitted when proposal request has been sent to Governor contractBuyout:
Emitted when voting passes for buyout proposalDescript:
Emitted when voting passes for descript proposalReject:
Emitted when proposal failsRefund:
Emitted when a refund has been executed successfully by userWithdraw:
Emitted when a withdraw has been executed successfully by userFulfill:
Emitted when a fulfill has been executed successfullyClaim:
Emitted when revenue is claimed from an auctionTransferToBroker:
Emitted when funds are transferred to the brokerStateChange:
Emitted when the state of an auction changes
AuctionDoesNotExist:
Error thrown when attempting to interact with a non-existent auctionAuctionNotOpened:
Error thrown when attempting to perform an action on an auction that hasn't opened yetAuctionNotClosed:
Error thrown when attempting to perform an action on an auction that hasn't closed yetAuctionNotFailed:
Error thrown when user tries to refund but auction is not in failed stateAuctionNotFinished:
Error thrown when user tries to claim but auction is not in finished stateInsufficientPieces
: Error thrown when there aren't enough pieces left to fulfill an orderInsufficientFunds:
Error thrown when there are insufficient funds for an actionTransferFailed:
Error thrown when a fund transfer operation failsAuctionAlreadyInitialized:
Error thrown when admin calls create on existing auctionZeroValueNotAllowed:
Error thrown when a zero value is provided as parameter where it is not allowedIncorrectTimestamp:
Error thrown when a provided timestamp is incorrect or invalidZeroAddressNotAllowed:
Error thrown when a zero address is provided where it is not allowedOverpayment:
Error thrown when an overpayment is detected in buy or buyout functionsBuyLimitExceeded:
Error thrown when the buy limit of pieces for an auction is exceededProposalInProgress:
Error thrown when there is a proposal in progressUnauthorizedCaller:
Error thrown when function called by unauthorized addressInvalidProposalType:
Error thrown when function called with incorrect proposal typeIncorrectDescriptionSize:
Error thrown when proposal description provided is too short or too longIncorrectFundsTransfer:
Error thrown when funds value sent to contract is too low or too high
The Asset contract represents the NFTs minted during auction creation. Each auctioned asset is minted as an NFT, with users able to buy pieces of the asset. These NFTs can be bought, transferred, and burned based on user interactions with the auction system. The Asset contract also manages the creation, storage, and transfer of assets within the auction system. It handles the minting and burning of tokens (pieces) of assets, and ensures that ownership is properly tracked throughout the lifecycle of the asset. It also implements voting system strictly connected with Governor
contract.
Each asset is linked to IPFS (InterPlanetary File System) via a unique URI, which points to its metadata and visual representation. All assets are based on the ERC721 standard for non-fungible tokens (NFTs) and include standard functions such as mint, transfer, and burn. In this project, we are using the Azuki implementation of ERC721 (ERC721A), which significantly reduces the costs associated with minting, transferring, and burning providing the only such solution in the web3 world where, despite the fractionalization of the asset, the user receives a full-fledged NFT and not a cryptocurrency substitute, i.e. the ERC20 standard.
The Governor contract is responsible for managing proposals, including buyout proposals and descriptive changes to auctions. It oversees the voting process and determines whether a proposal should be accepted or rejected. Functions from this contract can only be called by the Auctioner
contract itself, with the exception of the castVote
function, which allows users to cast votes for each proposal if they hold any linked asset tokens.
INACTIVE:
Proposal does not existACTIVE:
Proposal is currently open for votingSUCCEEDED:
Proposal successfully executedFAILED:
Proposal did not pass and awaits cancellation
FOR:
Indicates a vote in favor of the proposalAGAINST:
Indicates a vote against the proposal
uint256 auctionId:
The id of the auction that received offeraddress asset:
Address of the asset (NFT) linked to the proposaluint256 voteStart:
Timestamp when voting startsuint256 voteEnd:
Timestamp when voting endsstring description:
Description of the proposalbytes encodedFunction:
Function to be called on execution expressed in bytesuint256 forVotes:
Number of votes in favor of the proposaluint256 againstVotes:
Number of votes against the proposalmapping(address => bool) hasVoted:
Mapping to track if an address has voted on the proposalProposalState state:
Current state of the proposal
Propose:
Emitted when a new proposal is createdProcessProposal:
Emitted when proposal has been executed or cancelled and removed from ongoing proposals arrayCastVote:
Emitted when vote has been castedStateChange:
Emitted when the state of a proposal changes
ProposalDoesNotExist:
Error thrown when interacting with a non-existent proposalProposalNotActive:
Error thrown when attempting to vote on a non-active proposalAlreadyVoted:
Error thrown when attempting to vote more than onceZeroVotingPower:
Error thrown when a user with zero voting power attempts to voteExecuteFailed:
Error thrown if execute function revert
This contract is licensed under the GNU General Public License v3.0 or later.