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

[SmartContract] Create YiledStremerV2 contract (MVP version). #10

Open
igorsenych-cw opened this issue Oct 16, 2024 · 1 comment
Open
Assignees

Comments

@igorsenych-cw
Copy link
Collaborator

igorsenych-cw commented Oct 16, 2024

YieldStreamerV2


Key feature - streaming on D0

At any given moment, the yield is streamed based on the user's actual balance. This means that if a user's balance changes during the day, the yield calculation adjusts immediately to reflect the new balance. This real-time adjustment is possible because the YieldStreamerV2 contract is connected (hooked) to the BRLC token contract. Every time a user's balance changes, the contract accrues yield earned up to that point based on the previous balance and then begins streaming yield based on the new balance.


Yield calculation example

  • Day 1
    • 9:00 AM
      • Action: The user deposits 1,000 BRLC.
      • Balance Update: User's token balance increases from 0 BRLC to 1,000 BRLC.
      • Yield Accrual Starts: Yield begins accruing on 1,000 BRLC from this moment.
    • 3:00 PM
      • Action: The user deposits an additional 1,000 BRLC.
      • Yield Calculation Before Deposit:
        • Calculate Yield Accrued from 9:00 AM to 3:00 PM:
          • Period: 6 hours (from 9:00 AM to 3:00 PM).
          • Balance: 1,000 BRLC during this period.
          • Accrued Yield: Denote this as Y1.
      • Update Accrued Yield:
        • Store Y1 in the user's yield state.
      • Balance Update:
        • Token Balance increases to 2,000 BRLC after the deposit.
      • Yield Accrual Continues:
        • Yield now accrues on the new balance of 2,000 BRLC from 3:00 PM onward.
    • 9:00 PM
      • Action: The user withdraws 500 BRLC.
      • Yield Calculation Before Withdrawal:
        • Calculate Yield Accrued from 3:00 PM to 9:00 PM:
          • Period: 6 hours (from 3:00 PM to 9:00 PM).
          • Balance: 2,000 BRLC during this period.
          • Accrued Yield: Denote this as Y2.
        • Update Accrued Yield:
          • Total Accrued Yield is now Y1 + Y2.
        • Balance Update:
          • Token Balance decreases to 1,500 BRLC after the withdrawal.
        • Yield Accrual Continues:
          • Yield starts accruing on the new balance of 1,500 BRLC from 9:00 PM onward.
  • Day 2
    • 9:00 AM (Yield Compounding Occurs)
      • Action: The user deposits 500 BRLC.
      • Yield Calculation Before Deposit:
        • Calculate Yield Accrued from 9:00 PM to 12:00 AM (Day 1):
          • Period: 3 hours (from 9:00 PM to 12:00 AM).
          • Balance: 1,500 BRLC during this period.
          • Accrued Yield: Denote this as Y3.
        • Update Accrued Yield:
          • Total Accrued Yield for Day 1 becomes Y1 + Y2 + Y3.
          • NOTE: The total yield from Day 1 will be included in calculating the yield for Day 2 (compounding effect).
        • Calculate Yield Accrued from 12:00 AM to 9:00 AM (Day 2):
          • Period: 9 hours (from 12:00 AM to 9:00 AM).
          • Effective Balance for Yield Calculations:
            • Token Balance: 1,500 BRLC.
            • Accrued Yield from Day 1: Y1 + Y2 + Y3.
            • Effective Balance: 1,500 BRLC + (Y1 + Y2 + Y3).
          • Accrued Yield: Denote this as Y4.
        • Update Accrued Yield:
          • Total Accrued Yield becomes Y1 + Y2 + Y3 + Y4.
          • Store Y4 in the user's yield state as yield for Day 2.
        • Balance Update After Deposit:
          • Token Balance increases to 2,000 BRLC after the deposit.
        • Yield Accrual Continues:
          • New Effective Balance for Yield Calculations:
            • Token Balance: 2,000 BRLC.
            • Accrued Yield: Y1 + Y2 + Y3 (from previous periods).
            • Effective Balance: 2,000 BRLC + (Y1 + Y2 + Y3).
          • Yield starts accruing on 2,000 BRLC + (Y1 + Y2 + Y3) from 9:00 AM onward.

Migration from V1

Since we currently have YieldStreamerV1 running and it contains all the details about users' accrued yield, we can't simply switch users over to YieldStreamerV2 without also transferring their accrued yield. As YieldStreamerV2 is currently just a MVP version, migrating yield is only possible manually at this stage. You would have to provide us with a list of users to migrate from V1, and we will manually transfer these users along with their accrued yield to V2, disabling them on V1.


Limitation of V2

Just like in YieldStreamerV1, when streaming yield, we consider the user's total BRLC balance, including any frozen or preminted balances. We do not exclude these amounts from the yield calculations.


Contract ABI

Despite being in its MVP version, the YieldStreamerV2 contract is quite sophisticated and implements multiple interfaces that define all of its functionality. While the complete list of interfaces is provided below, the most commonly used functions for end users are as follows.

Storage

/**
     * @dev Structure representing a yield rate that becomes effective from a specific day.
     * Used to determine the yield accrual for accounts based on their assigned group.
     *
     * Fields:
     * - `effectiveDay`: The day index (since Unix epoch) from which this yield rate becomes effective.
     * - `value`: The yield rate value (scaled by RATE_FACTOR).
     */
    struct YieldRate {
        uint16 effectiveDay;
        uint32 value;
        // uint208 __reserved; // Reserved for future use until the end of the storage slot.
    }

    /**
     * @dev Structure representing the yield state of an account.
     * Used to store information about the account's yield accrual and balances.
     *
     * Fields:
     * - `flags`: A byte used to store boolean flags using bitwise operations (e.g., initialization status).
     * - `streamYield`: The amount of yield accrued during the current day (not yet finalized).
     * - `accruedYield`: The total amount of yield accrued and finalized up to the last update.
     * - `lastUpdateTimestamp`: The timestamp of the last yield accrual or balance update.
     * - `lastUpdateBalance`: The account's token balance at the time of the last update.
     */
    struct YieldState {
        uint8 flags;
        uint64 streamYield;
        uint64 accruedYield;
        uint40 lastUpdateTimestamp;
        uint64 lastUpdateBalance;
        // uint16 __reserved; // Reserved for future use until the end of the storage slot.
    }

    /**
     * @dev Structure representing a preview of the claimable yield for an account.
     * Used to estimate the yield that can be claimed without modifying the contract state.
     *
     * Fields:
     * - `yield`: The total claimable yield amount (rounded down) available for the account.
     * - `fee`: The fee amount that would be deducted during the claim.
     * - `timestamp`: The timestamp at which the preview was calculated.
     * - `balance`: The account's token balance used in the calculation.
     * - `rate`: The current yield rate applicable to the account.
     */
    struct ClaimPreview {
        uint256 yield;
        uint256 fee;
        uint256 timestamp;
        uint256 balance;
        uint256 rate;
    }

    /**
     * @dev Structure representing a preview of the yield accrual over a period for an account.
     * Provides detailed information about how the yield would accrue without modifying the state.
     *
     * Fields:
     * - `fromTimestamp`: The starting timestamp of the accrual period.
     * - `toTimestamp`: The ending timestamp of the accrual period.
     * - `balance`: The account's token balance at the beginning of the period.
     * - `accruedYieldBefore`: The accrued yield before the accrual period.
     * - `streamYieldBefore`: The stream yield before the accrual period.
     * - `accruedYieldAfter`: The accrued yield after the accrual period.
     * - `streamYieldAfter`: The stream yield after the accrual period.
     * - `rates`: An array of `YieldRate` structs used during the accrual period.
     * - `results`: An array of `YieldResult` structs detailing yield calculations for sub-periods.
     */
    struct AccruePreview {
        uint256 fromTimestamp;
        uint256 toTimestamp;
        uint256 balance;
        uint256 streamYieldBefore;
        uint256 accruedYieldBefore;
        uint256 streamYieldAfter;
        uint256 accruedYieldAfter;
        YieldRate[] rates;
        YieldResult[] results;
    }

    /**
     * @dev Structure representing the result of a yield calculation for a specific period.
     * Details the yield accrued during different parts of the period (partial days and full days).
     *
     * Fields:
     * - `firstDayPartialYield`: Yield accrued during the partial first day of the period.
     * - `fullDaysYield`: Total yield accrued during the full days within the period.
     * - `lastDayPartialYield`: Yield accrued during the partial last day of the period.
     */
    struct YieldResult {
        uint256 firstDayPartialYield;
        uint256 fullDaysYield;
        uint256 lastDayPartialYield;
    }

Functions

/**
     * @dev Claims a specific amount of yield for the given account.
     * Transfers the specified amount of yield (after fees) to the account.
     *
     * @param account The address of the account for which to claim yield.
     * @param amount The amount of yield to claim.
     */
    function claimAmountFor(address account, uint256 amount) external;

    /**
     * @dev Retrieves the current yield state for a given account.
     * Provides information about the account's yield accrual and balances.
     *
     * @param account The address of the account to query.
     * @return A `YieldState` struct containing the account's yield state.
     */
    function getYieldState(address account) external view returns (IYieldStreamerTypes.YieldState memory);

    /**
     * @dev Provides a preview of the claimable yield for a given account at the current time.
     * Estimates the yield amount that can be claimed without modifying the contract state.
     *
     * @param account The address of the account to query.
     * @return A `ClaimPreview` struct containing details of the claimable yield.
     */
    function getClaimPreview(address account) external view returns (IYieldStreamerTypes.ClaimPreview memory);

    /**
     * @dev Provides a preview of the yield accrual for a given account over time.
     * Estimates how the yield will accrue based on current rates without modifying the state.
     *
     * @param account The address of the account to query.
     * @return An `AccruePreview` struct containing details of the accrued yield.
     */
    function getAccruePreview(address account) external view returns (IYieldStreamerTypes.AccruePreview memory);

    /**
     * @dev Retrieves the array of yield rates associated with a specific group ID.
     *
     * @param groupId The ID of the group to query.
     * @return An array of `YieldRate` structs representing the group's yield rates.
     */
    function getGroupYieldRates(uint256 groupId) external view returns (IYieldStreamerTypes.YieldRate[] memory);

    /**
     * @dev Retrieves the group ID to which a specific account is assigned.
     *
     * @param account The address of the account to query.
     * @return The group ID of the account.
     */
    function getAccountGroup(address account) external view returns (uint256);

    /**
     * @dev Returns the address of the underlying token used by the yield streamer.
     *
     * @return The address of the underlying ERC20 token contract.
     */
    function underlyingToken() external view returns (address);

    /**
     * @dev Returns the address of the fee receiver configured in the yield streamer.
     *
     * @return The address of the fee receiver.
     */
    function feeReceiver() external view returns (address);

    /**
     * @dev Returns the current block timestamp as used by the contract.
     * May include adjustments such as negative time shifts.
     *
     * @return The current block timestamp.
     */
    function blockTimestamp() external view returns (uint256);

Events

/**
     * @dev Emitted when yield is accrued for an account.
     *
     * @param account The address of the account for which yield was accrued.
     * @param newAccruedYield The new total accrued yield after accrual.
     * @param newStreamYield The new stream yield after accrual.
     * @param oldAccruedYield The previous accrued yield before accrual.
     * @param oldStreamYield The previous stream yield before accrual.
     */
    event YieldStreamer_YieldAccrued(
        address indexed account,
        uint256 newAccruedYield,
        uint256 newStreamYield,
        uint256 oldAccruedYield,
        uint256 oldStreamYield
    );

    /**
     * @dev Emitted when yield is transferred to an account as a result of a claim.
     *
     * @param account The address of the account receiving the yield.
     * @param yield The amount of yield transferred to the account after fees.
     * @param fee The amount of fee deducted from the yield.
     */
    event YieldStreamer_YieldTransferred(
        address indexed account, // Tools: this comment prevents Prettier from formatting into a single line.
        uint256 yield,
        uint256 fee
    );

Full list of interfaces

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant