Fraction ProtocolskeletonFacetspurchaseSkeletons

TwoClickPurchaseSkeleton

Implementation of the Purchase skeleton facet for the TMI-Fraction Protocol.

_This facet serves as a core component (skeleton) of a TMI-Fraction Platform, enabling investors to purchase fractions from campaigns.


IMPORTANT:

  • This implementation should only be utilized by Platforms that feature campaigns issuing fungible (ERC20) fractions with discount mechanism(s). It is not recommended for campaigns with semi-fungible (ERC1155) fractions.

  • This implementation features a two (2) step process for purchasing fractions:

    • Firstly, investors purchase fractions via the purchase() function and receive an NFT which represents their purchase. This NFT fully represents the owner's purchase position (amount of fractions, purchased price, etc.) and acts as a receipt that can be redeemed when the campaign reaches either the FUNDED (and its post-FUNDED states) or the NON_FUNDED state. The purpose of this NFT is to cater to scenarios where a campaign reaches a NON_FUNDED state, but there have been investors who purchased at a discounted price. Since fungible fractions are indistinguishable, and there is no way to distinguish which investors purchased with a discount based on fraction balance alone, these NFTs provide a fair principal receipt mechanism (see NonFundedSubSkeletonForTwoClick.sol) if the campaign fails and reaches NON_FUNDED state.

    • Subsequently, owners of such NFTs (i.e., the investors) can redeem them via the exchangeNftForFractions() function if the associated campaign reaches its FUNDED state (and its post-FUNDED states) to receive the amount of fungible fractions they are owed. This process involves burning their NFT in exchange for the respective amount of fractions that the NFT represents.


The first step of the purchase process is triggered when purchase() is executed, following a sequential pipeline of six phases:

  • State Check: The Platform interacts with its PurchaseState internal facet to verify that the current state of the targeted campaign is the correct state for the purchase to occur.

  • Time Check: The Platform interacts with its PurchaseTime internal facet to verify that the current timestamp is within the campaign's configured time-window during which purchases can occur.

  • Eligibility Check: The Platform interacts with its PurchaseEligibility internal facet to verify that the user (caller) meets the campaign's eligibility criteria to purchase fractions.

  • Amount Check: The Platform interacts with its PurchaseAmount Internal facet to verify that the requested amount of fractions meets the campaign's constraints (e.g., hardcap etc.).

  • Discount Application: The Platform interacts with its PurchaseDiscount internal facet to retrieve any applicable discount on the price of fractions and execute the required actions for the discount to take effect based on the provided discountOperationData (e.g., burning reputation tokens in exchange for a discount), if applicable.

  • Purchase Action: The Platform interacts with its DoPurchase internal facet to transfer the required funds from the user (caller) to the Platform. The required funds are based on either the current price (e.g., dynamic or stable) or a respective discounted price if the user has opted into any applicable discount mechanism.

  • NFT Mint Action: The Platform mints an NFT to the user representing their purchase position until FUNDED/NON_FUNDED states.


The second step of the purchase process of fractions is triggered when exchangeNftForFractions() is executed, following a sequential pipeline of four phases:

  • State Check: The Platform interacts with its PurchaseWithExchangeStates internal facet to verify that the current state of the targeted campaign is a correct state for the exchange to occur (redemption of NFT for fractions).

  • Eligibility Check: The Platform interacts with its PurchaseEligibility internal facet to verify that the user (caller) meets the campaign's eligibility criteria to purchase fractions via the NFT redemption/exchange.

  • NFT Burn Action: The Platform burns the NFT from the user in exchange for the respective amount of fractions it represents.

  • Post-Purchase Action: The Platform interacts with its PostPurchase internal facet based on the provided postPurchaseData to handle the purchased fractions accordingly (e.g., transferring them to the user's account or utilizing them in another supported manner, such as staking), thereby finalizing the purchase._

InvalidNftOwnerOnExchange

error InvalidNftOwnerOnExchange(uint256 nftId, address account)

Thrown in exchangeNftForFractions when the specified NFT is not owned by the caller.

NftPurchased

event NftPurchased(uint256 campaignId, address purchaser, uint256 amountOfFractions, uint256 pricePerFraction, uint256 nftId)

Emitted at purchase().

FractionsPurchased

event FractionsPurchased(uint256 campaignId, uint32 chainId, address purchaser, uint256 amountOfFractions)

Emitted at exchangeNftForFractions().

purchase

function purchase(uint256 campaignId, uint256 amountOfFractions, bytes discountOperationData) external

Executes the purchase of fractions via an intermediate NFT receipt (representing the purchase position) from a specified campaign.

_Users must meet eligibility criteria (see purchase Eligibility internal facets) and comply with the campaign's constraints (e.g., amount-related constraints).

Emits a {NftPurchased} event._

Parameters

NameTypeDescription
campaignIduint256The unique identifier of the targeted campaign.
amountOfFractionsuint256The number of fractions to purchase.
discountOperationDatabytesABI-encoded data required for applying discounts (if any).

exchangeNftForFractions

function exchangeNftForFractions(uint256 campaignId, uint256 nftId, bytes postPurchaseData, uint32 chainId) external payable

Executes the redemption of a purchase position NFT in exchange for the corresponding amount of fractions from a specified campaign.

_Users must own the NFT representing the purchase position and meet the campaign's eligibility criteria (see purchase Eligibility internal facets).

IMPORTANT:

  • The exchange should occur only after the campaignId reaches its FUNDED and post-FUNDED state(s) (see PurchaseWithExchangeStates Internal facets).

Emits a {FractionsPurchased} event._

Parameters

NameTypeDescription
campaignIduint256The unique identifier of the targeted campaign.
nftIduint256The ID of the NFT representing the purchase position.
postPurchaseDatabytesABI-encoded data required for the post-purchase phase.
chainIduint32The ID of the blockchain network where the purchased fractions will be received or utilized.

On this page