Yield Smart Contract

Overview

The Yield contract enables participants to enroll for sBTC rewards, distribute those rewards, and manage snapshots and cycles for accurate balance and reward tracking. The main operations include:

  1. Initialization: The contract can be initialized with parameters like tenure height and block height to set up the reward cycles.

  2. Enrollment: Users can enroll for participation, with custom reward addresses. Participants can opt-out or change their reward addresses.

  3. Snapshots and Cycles: Periodic snapshots and cycles calculate participant balances based on predefined block intervals and aggregate data for reward distribution.

  4. Rewards: Rewards are distributed every cycle based on participant holdings, with functionality for administrators to update configurations like APR, snapshot length, and number of snapshots per cycle.

  5. Administrative Controls: Admins can enroll DEXs, update cycle parameters, and finalize reward distributions.


Cycle Structure

  • Each cycle consists of a fixed number of snapshots (default 14).

  • Each snapshot occurs after a set number of tenures (default 140).

  • The total cycle length is thus 1960 tenures by default (14 snapshots of 140 tenures).

  • These defaults are set for easier local integration testing, for production they should be updated to higher values (eg. 1 snapshot per day => nr-blocks-snapshot = 140)

Cycle Workflow

The Yield smart contract operates in cycles, each divided into snapshots. The process ensures accurate reward distribution. For each cycle:

  1. Compute balances for enrolled users after each snapshot using compute-current-snapshot-balances.

  2. Transition to the next snapshot with head-to-next-snapshot.

  3. Conclude all snapshot data for the last snapshot of a cycle using conclude-cycle-snapshots.

  4. Enable reward distribution by calling set-can-distribute-rewards.

  5. Distribute rewards to enrolled users based on their pool percentage using distribute-rewards.

  6. Finalize reward distribution after all the participants were rewarded using finalize-reward-distribution.

  7. Finalize the cycle and move to the next one with head-to-next-cycle.


Public Functions

1. Contract Initialization

initialize-contract

Activates the contract with an initial cycle. To initialize the contract successfully, pass the first Stacks block height of the activation tenure. For synchronization with PoX, use the first Stacks block height from the first tenure of a PoX cycle. The activation tenure height can be updated using update-initialize-block.

  • Parameters: stx-block-height (uint)

  • Assertions:

    • Tenure height conditions must be met.

    • The contract must not be active.

  • Effect:

    • Initializes state variables for the first cycle and marks the contract as active.

update-initialize-block

Updates the initialization tenure height. For synchronization with PoX, use the first tenure height of a PoX cycle.

  • Parameters: new-tenure-height (uint)

  • Assertions:

    • Contract must not be active.

    • Caller must be the admin.

  • Effect:

    • Updates the initialization tenure height to the new value.

2. Enrollment

enroll

Enrolls the caller for rewards.

  • Parameters: rewarded-address (optional principal)

  • Assertions:

    • Caller must not already be enrolled.

    • Caller must not be blacklisted.

  • Effect:

    • Adds the caller to the participants map and increments the participant count.

change-reward-address

Changes the reward address for the caller.

  • Parameters: new-address (principal)

  • Assertions:

    • Caller must be enrolled.

  • Effect:

    • Updates the reward address in the participants map.

opt-out

Allows the caller to opt out of participation.

  • Assertions:

    • Caller must be enrolled.

  • Effect:

    • Removes the caller from the participants map.

3. Snapshots and Cycles

compute-current-snapshot-balances

Computes snapshot balances for a list of participants.

  • Parameters: principals (list of up to 900 principals)

  • Assertions:

    • The current snapshot block height must exist.

  • Effect:

    • Computes balances for each participant and updates totals.

head-to-next-snapshot

Advances the contract to the next snapshot.

  • Parameters: new-stx-block-height (uint)

  • Assertions:

    • The contract must be active.

    • All participants must be snapshotted.

    • Cycle and block height conditions must be met.

  • Effect:

    • Updates snapshot-specific state variables.

conclude-cycle-snapshots

Concludes all snapshots within a cycle and aggregates their totals.

  • Assertions:

    • The contract must be active.

    • All snapshots in the cycle must be taken.

    • All participants must be accounted for in the snapshots.

  • Effect:

    • Aggregates snapshot totals into the cycle total.

    • Updates state variables to reflect snapshot conclusions.

head-to-next-cycle

Advances the contract to the next cycle.

  • Parameters: stx-block-height (uint)

  • Assertions:

    • The contract must be active.

    • All rewards must be finalized.

    • Cycle and block height conditions must be met.

  • Effect:

    • Resets and updates cycle-specific state variables.

4. Rewards

set-can-distribute-rewards

Prepares the contract to distribute rewards by determining the available reward pool.

  • Assertions:

    • The contract must be active.

    • Snapshots for the cycle must be concluded.

  • Effect:

    • Computes the rewards-to-distribute value based on pool and cap constraints.

    • Marks rewards as ready for distribution.

distribute-rewards

Distributes rewards to participants based on their holdings.

  • Parameters: principals (list of up to 900 principals)

  • Assertions:

    • Rewards must be distributable.

  • Effect:

    • Distributes rewards proportionally.

finalize-reward-distribution

Marks reward distribution as finalized.

  • Assertions:

    • The contract must be active.

    • All rewards must be distributed.

  • Effect:

    • Finalizes the reward distribution state.

5. Administrative Controls

enroll-dex

Enrolls a decentralized exchange (DEX) contract for rewards.

  • Parameters: dex-contract (principal), rewarded-address (optional principal)

  • Assertions:

    • Caller must be the admin.

    • DEX must not already be enrolled or blacklisted.

  • Effect:

    • Adds the DEX to the participants map and increments the participant count.

update-snapshot-length

Updates the number of blocks per snapshot for the next cycle.

  • Parameters: updated-nr-blocks-snapshot (uint)

  • Assertions:

    • The caller must be the admin.

  • Effect:

    • Sets the new snapshot length.

update-nr-snapshots-cycle

Updates the number of snapshots per cycle for the next cycle.

  • Parameters: updated-nr-snapshots-cycle (uint)

  • Assertions:

    • The caller must be the admin.

  • Effect:

    • Sets the new number of snapshots per cycle.

update-APR

Updates the APR value for the next cycle.

  • Parameters: new-apr-one-six (uint)

  • Assertions:

    • The caller must be the admin.

    • New APR must be within defined limits.

  • Effect:

    • Sets the new APR.


Private Functions

update-snapshot-for-new-cycle

Updates snapshot variables for a new cycle.

  • Parameters: stx-block-height (uint)

reset-state-for-cycle

Resets state variables for a new cycle.

  • Parameters: stx-block-height (uint)

compute-and-update-balances-one-user

Computes and updates the balance for a single user during a snapshot.

  • Parameters: address (principal), current-total (uint)

  • Effect:

    • Updates balances and counts for eligible participants.

distribute-reward-user

Distributes rewards to a single user.

  • Parameters: user (principal)

  • Effect:

    • Sends the rewards to the user. Updates holding and rewards state for the user.

remove-participant

Removes a participant from the participants map.

  • Parameters: address (principal)


Read-Only Functions

nr-cycles-year

Returns the approximate number of cycles per year. This value is obtained by dividing the number of Bitcoin blocks in a year by the total number of Bitcoin blocks in a cycle.

cycle-percentage-rate

Returns the cycle percentage rate, scaled by 10^6. This value is obtained by dividing the APR by the number of cycles per year.

block-height-to-tenure-height

Returns the tenure height corresponding to the provided Stacks block height.

  • Parameters: stx-block-height (uint)

is-enrolled-in-next-cycle

Checks if the given address is enrolled for the next cycle.

  • Parameters: address (principal)

  • Returns: true if the address is enrolled, otherwise false.

is-enrolled-this-cycle

Checks if the given address is enrolled in the current cycle.

  • Parameters: address (principal)

  • Returns: true if the address is enrolled, otherwise false.

cycle-data

Returns detailed data about the current and next cycles.

current-cycle-id

Returns the ID of the current cycle.

snapshot-data

Returns data about the current snapshot.

rewarded-data

Returns data about rewards, including the count and distribution status.

check-can-distribute-rewards

Indicates whether rewards can be distributed in the current cycle.

  • Returns: true if rewards can be distributed, otherwise false.

tenure-height-for-next-state

Returns the tenure height for the next snapshot or cycle.

current-overview-data

Returns an overview of the current cycle and snapshot data.

get-admin

Returns the administrator's address.

get-is-contract-active

Checks whether the contract is active.

  • Returns: true if the contract is active, otherwise false.

get-current-tenure-height

Returns the current tenure height.

get-latest-reward-address

Retrieves the latest reward address associated with the given principal.

  • Parameters: address (principal)

get-stacks-block-height-for-cycle-snapshot

Returns the Stacks block height for a specific cycle and snapshot.

  • Parameters: checked-cycle-id (uint), checked-snapshot-id (uint)

get-tenure-height-for-cycle-snapshot

Returns the tenure height for a specific cycle and snapshot.

  • Parameters: checked-cycle-id (uint), checked-snapshot-id (uint)

stx-block-height-distribution-finalized

Verifies if the reward distribution for the specified cycle has been finalized.

  • Parameters: wanted-cycle-id (uint)

  • Returns: If finalized, it returns the finalized block height wrapped in some. Otherwise, it returns none.

reward-amount-for-cycle-and-address

Retrieves the reward amount for a specific cycle and address.

  • Parameters: wanted-cycle-id (uint), address (principal)

  • Returns: The reward amount for the specified cycle and address.

reward-amount-for-cycle-and-reward-address

Retrieves the reward amount for a specific cycle and reward address.

  • Parameters: wanted-cycle-id (uint), reward-address (principal)

  • Returns: The reward amount for the specified cycle and reward address.

check-new-cycle-valid-stacks-block-height

Verifies if the provided Stacks block height is valid for starting a new cycle.

  • Parameters: stx-block-height (uint)

  • Returns: true if the block height is valid, otherwise an error code.

check-new-snapshot-valid-stacks-block-height

Verifies if the provided Stacks block height is valid for starting a new snapshot.

  • Parameters: stx-block-height (uint)

  • Returns: true if the block height is valid, otherwise an error code.

Last updated