Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: existing contract docs improvements #1324

Conversation

rackstar
Copy link
Contributor

@rackstar rackstar commented Feb 18, 2025

Description

  • StakingPool
  • StakingProducts

Testing

Explain how you tested your changes to ensure they work as expected.

Checklist

  • Performed a self-review of my own code
  • Made corresponding changes to the documentation

@rackstar rackstar requested a review from MilGard91 February 18, 2025 16:38
@rackstar rackstar self-assigned this Feb 18, 2025
@rackstar rackstar force-pushed the docs/existing-contract-docs-improvements branch 4 times, most recently from 20fe35a to e8bbc15 Compare February 18, 2025 17:14
@rackstar rackstar force-pushed the docs/existing-contract-docs-improvements branch from e8bbc15 to 0b736f7 Compare February 18, 2025 17:31
@rackstar
Copy link
Contributor Author

Relates to: #1228 #1264

@rackstar
Copy link
Contributor Author

StakingPool Contract Developer Documentation

Table of Contents


Overview

The StakingPool contract manages NXM staking and allocates capacity for purchased covers within the staking pool.

Each StakingPool contract represents its own distinct pool that manages the staked NXM tokens and the allocations of those staked NXM to cover products. This allows for precise management of stakes and cover allocations specific to that pool

When a user stakes NXM, the contract mints an NFT, which serves as a proof of stake ownership.

This contract handles:

  • NXM Staking & tracking: Users deposit NXM, with stakes tracked over time.
  • Tranches (91-day staking periods): Stakes are locked per tranche, determining withdrawals and staking rewards.
  • Cover Allocations: When cover products are purchased, capacity is allocated across multiple tranches to ensure sustained coverage and balanced reward distribution.
  • Stake Management: Users can extend stakes to future tranches or withdraw after expiration.

Key Concepts

Tranches

  • Fixed 91-day staking periods, each with its own stake & reward shares.
  • Staking early locks for 91 days; mid-tranche staking locks for the remaining duration.
  • Staked NXM in an active tranche contributes to cover capacity.
  • Once expired (after 91 days), stakes no longer provide capacity.
  • Users can withdraw rewards and either unstake or extend to a new tranche.
struct Tranche {
  uint128 stakeShares;
  uint128 rewardsShares;
}
Parameter Description
stakeShares Proportional representation of stake ownership in the tranche.
rewardsShares Proportional share of the pool's rewards allocated to the tranche.

Formula for current tranche ID:

uint currentTrancheId = block.timestamp / TRANCHE_DURATION;

Buckets

  • Groupings used to track rewards & cover expirations.
  • A bucket's duration lasts 28 days.
  • Covers expire only at bucket intervals (28 days), enforcing a minimum cover period of 28 days.
  • Shorter than tranches to allow more frequent reward updates and allocation adjustments.

Formula for current bucket ID:

uint currentBucketId = block.timestamp / BUCKET_DURATION;

Allocations

  • Tracks how much of a pool's capacity is used for purchased cover.
  • Allocations are distributed across multiple active tranches to ensure sustained coverage
  • Balances capacity across tranches, maintaining sufficient capacity across all active tranches

Functions

Mutative Functions

depositTo

Allows users to deposit NXM into the pool, creating stake and rewards shares in return. Supports deposits to specific tranches and allows reusing the same nft for deposits in multiple tranches to an existing deposit.

function depositTo(uint amount, uint trancheId, uint requestTokenId, address destination) external;
Parameter Description
amount The amount to deposit.
trancheId The ID of the tranche to deposit into.
requestTokenId The ID of the request token (0 for a new deposit, or use an existing token ID to add to a previous deposit)
destination The address to send the Staking NFT token to.
  • Creates stake & reward shares.
  • Emits StakeDeposited.

withdraw

Allows users to withdraw their stake and/or rewards from specific tranches. Withdrawing the stakes can be done only on expired tranches, while rewards can be withdrawn at any time.

function withdraw(uint tokenId, bool withdrawStake, bool withdrawRewards, uint[] memory trancheIds) external;
Parameter Description
tokenId The ID of the staking NFT token.
withdrawStake Whether to withdraw the stake.
withdrawRewards Whether to withdraw the rewards.
trancheIds The IDs of the tranches to withdraw from.
  • Stake can only be withdrawn from expired tranches.
  • Rewards can be withdrawn at any time.
  • Emits Withdraw.

extendDeposit

Extends the duration of a deposit by moving it from an tranche to a future tranche.

function extendDeposit(uint tokenId, uint initialTrancheId, uint targetTrancheId, uint topUpAmount) external;
Parameter Description
tokenId The ID of the staking NFT token.
initialTrancheId The ID of the initial tranche.
targetTrancheId The ID of the target tranche.
topUpAmount The amount to top up the deposit by.
  • Tranche must be active to extend.
  • Emits DepositExtended.

View Functions

getDeposit

Get deposit details for a given NFT and tranche.

function getDeposit(uint tokenId, uint trancheId) external view returns (
  uint lastAccNxmPerRewardShare,
  uint pendingRewards,
  uint stakeShares,
  uint rewardsShares
);
Parameter Description
tokenId The ID of the product.
trancheId The ID of the tranche.

getTranche

Get details of a specific tranche.

function getTranche(uint trancheId) external view returns (
  uint stakeShares,
  uint rewardsShares
);
Parameter Description
trancheId The ID of the tranche.

getExpiredTranche

Get data of an expired tranche.

function getExpiredTranche(uint trancheId) external view returns (
  uint accNxmPerRewardShareAtExpiry,
  uint stakeAmountAtExpiry,
  uint stakeSharesSupplyAtExpiry
);
Parameter Description
trancheId The ID of the tranche.

getActiveAllocations

Returns an array with the allocated amounts in the currently active tranches for a product.

function getActiveAllocations(uint productId) external view returns (uint[] memory trancheAllocations);
Parameter Description
productId The ID of the product.

getActiveTrancheCapacities

Returns an array of the active tranche capacities and total capacity for a product.

function getActiveTrancheCapacities(
  uint productId,
  uint globalCapacityRatio,
  uint capacityReductionRatio
) public view returns (
  uint[] memory trancheCapacities,
  uint totalCapacity
);
Parameter Description
productId The ID of the product.
globalCapacityRatio Global Capacity Ratio
capacityReductionRatio Capacity Reduction Ratio.

getTrancheCapacities

Returns an array with the total capacities for the currently active tranches for a product.

function getTrancheCapacities(
  uint productId,
  uint firstTrancheId,
  uint trancheCount,
  uint capacityRatio,
  uint reductionRatio
) external view returns (uint[] memory trancheCapacities);
Parameter Description
productId The ID of the product.
globalCapacityRatio Global Capacity Ratio
capacityReductionRatio Capacity Reduction Ratio.

Miscellaneous View Functions

  • getPoolId() – Returns the pool ID.
  • getPoolFee() – Returns the current pool fee.
  • getMaxPoolFee() – Returns the max pool fee.
  • getActiveStake() – Returns the active stake.
  • getStakeSharesSupply() – Returns total stake shares.
  • getRewardsSharesSupply() – Returns total reward shares.
  • getRewardPerSecond() – Returns reward emission rate.
  • getAccNxmPerRewardsShare() – Returns accumulated NXM per reward share.

Events

  • StakeDeposited(address indexed user, uint256 amount, uint256 trancheId, uint256 tokenId)

    • Emitted when a user deposits stake.
  • Withdraw(address indexed user, uint indexed tokenId, uint tranche, uint amountStakeWithdrawn, uint amountRewardsWithdrawn)

    • Emitted when a user withdraws stake or rewards.
  • PoolFeeChanged(address indexed manager, uint newFee)

    • Emitted when the pool fee is updated.
  • PoolPrivacyChanged(address indexed manager, bool isPrivate)

    • Emitted when the pool’s privacy setting is changed.

FAQ

How is cover capacity allocated from tranches?

Only tranches that remain active for the full duration of the cover plus a grace period are eligible for allocation. This ensures that covers are backed by active stakes for their entire lifespan, maintaining the security of the coverage.

What happens when I deposit NXM?

You receive an NFT representing your stake, which can be used across multiple tranches.

Can I withdraw my stake at any time?

No, you can only withdraw stake from expired tranches. Rewards can be withdrawn at any time.

How are rewards distributed?

Rewards are proportional to stake size in a tranche.

Can I move my stake to a different tranche?

Yes, use extendDeposit() to move stake from one tranche to another.

What happens if my allocation is used for cover?

Once capacity is allocated for cover, your stake remains locked until the cover expires.


Contact and Support

If you have questions or need assistance integrating with the StakingPool contract or other parts of the protocol, please reach out through the official support channels or developer forums.

  • Developer Forums: Join our community forums to discuss with other developers and seek help.
  • Official Support Channels: Contact us via our official support email or join our Discord server.
  • Documentation Resources: Access additional documentation, tutorials, and FAQs on our official website.
  • GitHub Repository: Report issues or contribute to the codebase through our GitHub repository.

Disclaimer: This documentation provides a high-level overview of the StakingPool contract's functionality. It is intended for developers integrating with the protocol and may omit internal details not relevant to external interactions. Always refer to the latest contract code and official resources

@rackstar
Copy link
Contributor Author

StakingProducts Contract Developer Documentation

Table of Contents


Overview

The StakingProducts contract manages cover products and their integration into staking pools. It handles dynamic pricing, capacity allocation, and staking pool management. This contract enables:

  • Creating and managing staking pools (public or private).
  • Allowing pool managers to list and configure products within their pools (e.g., target price, target weight).
  • Dynamically calculating premiums based on capacity usage.
  • Adjusting product allocations and weights per pool to optimize stake distribution.

Key Concepts

Product Weights

Each product within a staking pool has two weight metrics:

  • Target Weight (targetWeight) – Set by the pool manager, defining the ideal allocation for the product.
  • Effective Weight (lastEffectiveWeight) – The actual allocation, dynamically adjusted based on available stake, product utilization, and global constraints.

The contract attempts to reach the target weight but may assign a lower effective weight if:

  1. Insufficient capacity – The pool does not have enough total staking.
  2. Low product utilization – If the product isn't being used as much.
  3. Other products take priority – If their target weights must be met first.

The effective weight never exceeds the target weight.


Pricing Mechanism

The pricing system adjusts dynamically based on usage and capacity, ensuring fair pricing and market-driven price discovery:

  • Initial Price (initialPrice) – The starting price set for a product. This can be higher than the minimum price (minPrice).
  • Target Price (targetPrice) – The price pool managers set as the preferred price for their product. Pricing gradually adjusts toward this value. Must be equal to or higher than Minimum Price.
  • Minimum Price (minPrice) – A product-specific minimum price that overrides the global 1% minimum price if needed.
  • Price Bumps – When cover is purchased, the price increases slightly (+0.05% per 1% of capacity used).
  • Pricing Decay – After a price bump, the price gradually decreases over time (0.5% per day) to allow for price discovery.
  • Dynamic Adjustments – Pricing fluctuates based on demand, ensuring fairness while preventing extreme volatility.

Functions

Mutative Functions

setProducts

Configures products for a specific staking pool and updates their parameters.

function setProducts(uint poolId, StakedProductParam[] memory params) external;
Parameter Description
poolId ID of the staking pool.
params Array of StakedProductParam structs with product settings.

Purpose:

  • Creates, updates, or removes products from the staking pool.
  • Adjusts weights and pricing parameters.
  • Recalculates effective weights if necessary.

recalculateEffectiveWeights

Dynamically adjusts effective weights for specified products based on current capacity and utilization.

function recalculateEffectiveWeights(uint poolId, uint[] calldata productIds) external;
Parameter Description
poolId Staking pool ID.
productIds List of product IDs to update.

Purpose:

  • Ensures fair capacity allocation by dynamically adjusting product weights.
  • Recommended after significant changes in usage or pricing.

recalculateEffectiveWeightsForAllProducts

Recalculates effective weights for all products within a staking pool.

function recalculateEffectiveWeightsForAllProducts(uint poolId) external;
Parameter Description
poolId The ID of the staking pool.

Purpose:

  • Ensures fair capacity allocation by dynamically adjusting all product weights.
  • Recommended after significant changes in usage or pricing.

createStakingPool

Creates a new staking pool.

function createStakingPool(
  bool isPrivatePool,
  uint initialPoolFee,
  uint maxPoolFee,
  ProductInitializationParams[] memory productInitParams,
  string calldata ipfsHash
) external returns (uint poolId, address stakingPoolAddress);
Parameter Description
isPrivatePool true for a private pool, false for public.
initialPoolFee Initial staking pool fee.
maxPoolFee Maximum allowed pool fee.
productInitParams Initial product parameters.
ipfsHash IPFS hash for metadata.

Purpose:

  • Creates a new staking pool with customizable settings.
  • Assigns pool manager role to the caller.

setPoolMetadata

Updates the metadata for a staking pool.

function setPoolMetadata(uint poolId, string calldata ipfsHash) external;
Parameter Description
poolId ID of the staking pool.
ipfsHash New IPFS hash for metadata.

View Functions

getProduct

Retrieves product details.

function getProduct(uint poolId, uint productId) external view returns (
  uint lastEffectiveWeight,
  uint targetWeight,
  uint targetPrice,
  uint bumpedPrice,
  uint bumpedPriceUpdateTime
);

getPoolManager

Returns the pool manager address.

function getPoolManager(uint poolId) public view returns (address);
Parameter Description
poolId The ID of the staking pool.

getPoolMetadata

Retrieves metadata IPFS hash.

function getPoolMetadata(uint poolId) external view returns (string memory ipfsHash);
Parameter Description
poolId The ID of the staking pool.

Pricing Functions

getPremium

Calculates the premium for a cover product.

function getPremium(
    uint poolId,
    uint productId,
    uint period,
    uint coverAmount,
    uint totalCapacity,
    uint productMinPrice,
    bool useFixedPrice,
    uint nxmPerAllocationUnit
) public returns (uint premium);
Parameter Description
poolId The ID of the staking pool.
productId The ID of the specific cover product.
period The cover duration in seconds.
coverAmount The coverage amount requested (in the protocol's units).
initialCapacityUsed The capacity already used before this cover.
totalCapacity The total capacity available in the pool.
globalMinPrice The global minimum price ratio for the cover product.
useFixedPrice Boolean indicating if a fixed price should be used.
nxmPerAllocationUnit The amount of NXM per allocation unit.
allocationUnitsPerNXM The number of allocation units per NXM token.

Description: Typically called internally by the staking pool during cover purchase. Updates the product's bumped price and timestamp.

Includes:

  • Base pricing and price bumps (as capacity is used).
  • Uses product-specific minPrice instead of the global minimum price.
  • Cover period and amount affect final premium.

Events

  • ProductUpdated(uint indexed productId, uint targetWeight, uint targetPrice)
    • Emitted when a product is updated.

FAQ

How are product weights determined?

Each product has two weight metrics:

  • Target Weight (targetWeight) – Set by the pool manager, representing the ideal weight for the product in the pool.
  • Effective Weight (lastEffectiveWeight) – The actual weight dynamically calculated based on staked capacity, utilization, and platform-wide constraints.

The contract tries to meet the target weight but may assign a lower effective weight if the pool lacks sufficient stake or if constraints (like global capacity limits) affect the allocation.

Can effective weight be higher than the target weight?

No, the effective weight is capped at the target weight. If the available stake is low, the effective weight may be lower than the target weight, but it will never exceed the target.

Can I create a private or public staking pool?

Yes:

  • Private pools (isPrivatePool = true) restrict who can interact.
  • Public pools (isPrivatePool = false) allow open participation.

How often should effective weights be recalculated?

Effective weights must be manually recalculated whenever staking pool conditions change. This can be done by calling:

  • recalculateEffectiveWeights(poolId, productIds[]) – Recalculates specific products in a pool.
  • recalculateEffectiveWeightsForAllProducts(poolId) – Updates all products in a pool.

Recalculations should be triggered:

  • Significant cover purchases that affect capacity.
  • Stake changes (new stakes, stake withdrawals, or stake extensions).
  • Periodically (e.g., daily or weekly) to reflect evolving conditions.

How is the premium calculated?

Premiums are calculated dynamically based on:

  1. Base Price – The product's target price set by the pool manager.
  2. Price Bumps – As more capacity is used, the price increases slightly (+0.05% per 1% capacity used).
  3. Pricing Decay – Over time, the price gradually decreases (0.5% per day), allowing for price discovery.
  4. Minimum Price (minPrice) – Ensures the price never falls below a predefined level (overrides the global minimum if set).
  5. Cover Details – The amount of cover purchased and coverage duration also impact the final premium.

This dynamic model ensures pricing reflects demand and supply, preventing underpricing while keeping costs fair for buyers.

How does StakingProducts integrate with StakingPoolFactory to create a new staking pool?

The StakingProducts contract uses the StakingPoolFactory to deploy and initialize new staking pools.

How is a new staking pool created?

  1. The createStakingPool() function is called on StakingProducts.

  2. This interacts with StakingPoolFactory, which deploys a new StakingPool contract.

  3. The caller becomes the staking pool manager, who can then:

    • Set pool parameters (e.g., fees, private/public status).
    • Choose which cover products to allow in the pool.
    • Set initial target weights for products in the pool.
  4. The staking pool is linked to StakingProducts, enabling capacity allocation for covers.

How can I update pool metadata?

Call setPoolMetadata(poolId, ipfsHash), where ipfsHash contains updated metadata.


Contact and Support

If you have questions or need assistance integrating with the StakingProducts contract, reach out through:

  • Developer Forums: Discuss with other developers.
  • Official Support Channels: Contact us via email or Discord.
  • Documentation Resources: Access tutorials and FAQs.
  • GitHub Repository: Report issues or contribute to the codebase.

Disclaimer: This documentation provides an overview of the StakingProducts contract. It does not cover internal logic—always refer to the latest contract code and official resources.

@rackstar rackstar merged commit 3e605ce into docs/smart-contracts-documentation Feb 20, 2025
6 checks passed
@rackstar rackstar deleted the docs/existing-contract-docs-improvements branch February 20, 2025 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant