Skip to content

FeePool

Description

FeePools primary purpose is the distribution of synthetix.exchange fees in sUSD and SNX staking rewards to SNX minters aka stakers via the claimFees() function.

closeCurrentFeePeriod is an external public function anyone can call to close the current feeperiod after the `feePeriodDuration has passed. There is no incentive behind this function call as it is incentive enough that SNX Stakers want to be able to claim their fees and rewards. There is also a Fee Period Closing service that synthetix contributors opperate that will automatically call closeCurrentFeePeriod when the fee period duration has passed.

The FeePool currently maintains 2 feeperiod structs where the current open period for accumulating fees and rewards is recentFeePeriods[0] and the previos period which has been cloased and now available for SNX Stakers to claim their fees and rewards being recentFeePeriods[1]

Since SIP 56: Differential Fees it now supports the API for storing and reading the Synth Exchange Fee Rates per synth which are defined via SCCP's. The current eschange fee rates implemented in sccp-24

Source: contracts/FeePool.sol

Architecture

Libraries

Inheritance Graph

graph TD FeePool[FeePool] --> Proxyable[Proxyable] FeePool[FeePool] --> SelfDestructible[SelfDestructible] FeePool[FeePool] --> LimitedSetup[LimitedSetup] FeePool[FeePool] --> MixinSystemSettings[MixinSystemSettings] Proxyable[Proxyable] --> Owned[Owned] SelfDestructible[SelfDestructible] --> Owned[Owned] MixinSystemSettings[MixinSystemSettings] --> MixinResolver[MixinResolver] MixinResolver[MixinResolver] --> Owned[Owned]

FeePool architecture graph

Details
  • Proxy: The fee pool, being Proxyable, sits behind a CALL-style proxy for upgradeability.
  • Synthetix: The fee pool needs the Synthetix address for a onlySynthetix modifer for storing a minters issue and burn events to track their debt % of the system.
  • SynthetixState: The fee pool retrieves the global issuance ratio, and queries the debt ledger directly from the Synthetix state contract.
  • Synth: The fee pool, retrieving their addresses from the Synthetix contract, directly burns and issues sUSD when transferring fees. Fees are denominated and paid out in sUSD. Synths themselves do not know the fee pool address directly, but ask the fee pool's proxy for its target.
  • FeePoolState: The fee pool state contract holds the details of each user's most recent issuance events: when they issued and burnt synths, and their value.
  • FeePoolEternalStorage: A storage contact that holds the last fee withdrawal time for each account.
  • DelegateApprovals: A storage contract containing addresses to which the right to withdraw fees has been delegated by another account, for example to allow hot wallets to withdraw fees.
  • RewardEscrow: The contract into which inflationary SNX rewards are paid by the fee pool so that they can be escrowed for a year after being claimed.
  • RewardsDistribution: This contract, in the guise of the rewardsAuthority, distributes allocations from the inflationary supply to various recipients.
  • Depot: Allows users to exchange between Synths, SNX, and Ether. The Depot uses the fee pool to know what transfer fees were being incurred on its transfers, although the transfer fee has been nil since before SIP-19.

Structs

FeePeriod

Source

A record for a fee period, when it was opened, and the fees and rewards accrued within it. This information is maintained for the last several fee periods in recentFeePeriods.

Field Type Description
feePeriodId uint64 A serial id for fee periods which is incremented for each new fee period.
startingDebtIndex uint64 The length of SynthetixState.debtLedger at the time this fee period began.
startTime uint64 The current timestamp when this fee period began.
feesToDistribute uint256 The total of fees to be distributed in this period, in sUSD. This increases when fees are collected in the current period or when unclaimed fees roll over from the oldest period to the second oldest. See feePaid and closeCurrentPeriod.
feesClaimed uint256 The number of fees that have already been claimed during this period.
rewardsToDistribute uint256 The total of inflationary rewards to be distributed in this period, in SNX. This increases when new rewards are minted by Synthetix.mint/rewardsMinted, or when unclaimed rewards roll over from the oldest period to the second oldest (closeCurrentPeriod).
rewardsClaimed uint256 The quantity of inflationary rewards that have already been claimed during this period.

Constants

FEE_ADDRESS

Source

The address where fees are pooled as sUSD.

Value: 0xfeEFEEfeefEeFeefEEFEEfEeFeefEEFeeFEEFEeF

Type: address

FEE_PERIOD_LENGTH

Source

This is the number of weekly fee periods that are tracked by the smart contracts, hence the length of the recentFeePeriods array.

This was reduced from 6 to 3 as part of SIP-4 and now 2 periods 0 and 1, but note the inconsistency with the corresponding constant in FeePoolState, which cannot be altered.

Value: 2

Type: uint8

Constructor

constructor

Source

Details

Signature

(address payable _proxy, address _owner, address _resolver)

Visibility

public

State Mutability

nonpayable

Views

effectiveDebtRatioForPeriod

Source

Given an account and an index into recentFeePeriods, this function computes the percentage of total debt ownership of the account at the end of that period.

This uses _effectiveDebtRatioForPeriod, where the start index and ownership percentage are computed with FeePoolState.applicableIssuanceData, and the end index is one before the beginnging of the next period. Hence this function disallows querying the debt for the current period.

In principle a future version could support the current fee period by using the last debt ledger entry as the end index.

Details

Signature

effectiveDebtRatioForPeriod(address account, uint256 period) returns (uint256)

Visibility

external

State Mutability

view

Requires

feePeriodDuration

Source

This is the minimum duration of a single fee period in seconds. In practice they may be slightly longer if closeCurrentFeePeriod is not called immediately at the earliest valid moment.

Its value is one week, but it may be between MIN_FEE_PERIOD_DURATION and MAX_FEE_PERIOD_DURATION (1 to 60 days).

Type: uint256

Details

Signature

feePeriodDuration() returns (uint256)

Visibility

external

State Mutability

view

feesAvailable

Source

Return the total of fees and rewards available to be withdrawn by this account. The result is reported as a [fees, rewards] pair denominated in the requested Synth flavour and SNX, respectively.

This is the total of fees accrued in completed periods, so is simply the the sum over an account's feesByPeriod not including the current period.

Details

Signature

feesAvailable(address account) returns (uint256, uint256)

Visibility

public

State Mutability

view

feesByPeriod

Source

Returns an array of FEE_PERIOD_LENGTH [fees, rewards] pairs owed to an account for each recent fee period (including the current one). Fees are denominated in sUSD and rewards in SNX.

To compute this, for each period from oldest to newest, find the latest issuance event this account performed before the close of this period, and use it to derive the owed fees and rewards for that period.

Note that a single issuance event can result in fees accruing for several fee periods, if the issuer does not claim their fees in one or more periods.

Periods where the user has already withdrawn since that period closed are skipped, producing [0,0] entries.

Details

Signature

feesByPeriod(address account) returns (uint256[2][2])

Visibility

public

State Mutability

view

getLastFeeWithdrawal

Source

Returns from FeePoolEternalStorage the id of the fee period during which the given address last withdrew fees.

Details

Signature

getLastFeeWithdrawal(address _claimingAddress) returns (uint256)

Visibility

public

State Mutability

view

getPenaltyThresholdRatio

Source

Returns the collateralisation level a user can reach before they cannot claim fees. This is simply SynthetixState.issuanceRatio * (1 + TARGET_THRESHOLD). The result is returned as a 18-decimal fixed point number.

Details

Signature

getPenaltyThresholdRatio() returns (uint256)

Visibility

public

State Mutability

view

isFeesClaimable

Source

Details

Signature

isFeesClaimable(address account) returns (bool)

Visibility

external

State Mutability

view

issuanceRatio

Source

Details

Signature

issuanceRatio() returns (uint256)

Visibility

external

State Mutability

view

recentFeePeriods

Source

Stores fee period information for the last three weeks, from newest to olders.

recentFeePeriods[0] is always the current fee period, which is modified by ongoing issuance and fee activity. Fees cannot be claimed from the current period, only from the closed period at index 1 which is all the fees and rewards accrued in the previous fee period (week).

Type: FeePeriod[FEE_PERIOD_LENGTH] public

Details

Signature

recentFeePeriods(uint256 index) returns (uint64, uint64, uint64, uint256, uint256, uint256, uint256)

Visibility

external

State Mutability

view

targetThreshold

Source

Type: uint256

Details

Signature

targetThreshold() returns (uint256)

Visibility

external

State Mutability

view

totalFeesAvailable

Source

Computes the total fees available to be withdrawn, valued in terms of currencyKey. This simply sums the unclaimed fees over recentFeePeriods except those from the current period, because they cannot yet be claimed.

Details

Signature

totalFeesAvailable() returns (uint256)

Visibility

external

State Mutability

view

totalRewardsAvailable

Source

Computes the total SNX rewards available to be withdrawn. This simply sums the unclaimed rewards over recentFeePeriods except those from the current period, because they cannot yet be claimed.

Details

Signature

totalRewardsAvailable() returns (uint256)

Visibility

external

State Mutability

view

Restricted Functions

appendAccountIssuanceRecord

Source

Records that an account issued or burnt synths in the fee pool state.

This function merely emits an event and passes through to FeePoolState.appendAccountIssuanceRecord and is itself only invoked by Synthetix._appendAccountIssuanceRecord.

The debtRatio argument is a 27-decimal fixed point number.

Details

Signature

appendAccountIssuanceRecord(address account, uint256 debtRatio, uint256 debtEntryIndex)

Visibility

external

State Mutability

nonpayable

Modifiers

appendVestingEntry

Source

Allows the contract owner to escrow SNX rewards for particular accounts. The rewards are escrowed for one year.

The SNX is deposited into the RewardEscrow contract from the sender using the ERC20 transferFrom function. The tokens are then escrowed on behalf of the targeted account with RewardEscrow.appendVestingEntry.

Details

Signature

appendVestingEntry(address account, uint256 quantity)

Visibility

public

State Mutability

nonpayable

Modifiers

importFeePeriod

Source

During the setup period, allowed the contract owner to set a particular fee period entry in recentFeePeriods in order to migrate from a previous contract version.

Details

Signature

importFeePeriod(uint256 feePeriodIndex, uint256 feePeriodId, uint256 startingDebtIndex, uint256 startTime, uint256 feesToDistribute, uint256 feesClaimed, uint256 rewardsToDistribute, uint256 rewardsClaimed)

Visibility

public

State Mutability

nonpayable

Requires

Modifiers

recordFeePaid

Source

Allows the Synthetix._internalExchange function to record that a fee was paid whenever an exchange between Synth flavours occurs.

Adds the value in sUSD to the current fee period's pool of fees to be distributed.

Details

Signature

recordFeePaid(uint256 amount)

Visibility

external

State Mutability

nonpayable

Modifiers

Internal Functions

_claimFees

Source

Claims fees and rewards owed to the specified address.

The account's collateralisation ratio must be less than the issuance ratio, plus the target threshold, as specified by the feesClaimable function. The quantity of fees and rewards owed is computed by feesAvailable.

Upon invocation, this function updates the account's last fee withdrawal time, and removes the claimed fees and rewards from the pool. Fees are paid into the claiming address in the specified currency, while the rewards are escrowed on behalf of the claiming address in the RewardEscrow contract for one year.

The return value is always true if the transaction was not reverted.

Details

Signature

_claimFees(address claimingAddress) returns (bool)

Visibility

internal

State Mutability

nonpayable

Requires

_effectiveDebtRatioForPeriod

Source

Given entry and exit indices into the debt ledger, and a percentage of total debt ownership at the entry index, this function computes the adjusted ownership percentage at the exit index. This percentage changes due to fluctuations in Synth prices and total supply.

If \Delta_i is the value of the i^{th} entry in the debt ledger and \omega is the provided debt ownership percentage, then the result of this function is:

\omega \frac{\Delta_\text{exit}}{\Delta_\text{entry}}

See Synthetix._addToDebtRegister for details of the debt ownership percentage adjustment.

Details

Signature

_effectiveDebtRatioForPeriod(uint256 closingDebtIndex, uint256 ownershipPercentage, uint256 debtEntryIndex) returns (uint256)

Visibility

internal

State Mutability

view

_feesAndRewardsFromPeriod

Source

Computes the fees (in sUSD) and rewards (in SNX) owed at the end of a recent fee period given an entry index and the percentage of total system debt owned.

  • period is an index into the recentFeePeriods array, thus 0 corresponds with the current period.
  • debtEntryIndex should be an index into the debt ledger which was added before the close of the specified fee period.
  • ownershipPercentage should be the percentage of the account's debt ownership at that debtEntryIndex. This is a 27-decimal fixed point number.
Details

Signature

_feesAndRewardsFromPeriod(uint256 period, uint256 ownershipPercentage, uint256 debtEntryIndex) returns (uint256, uint256)

Visibility

internal

State Mutability

view

_isFeesClaimableAndAnyRatesInvalid

Source

Details

Signature

_isFeesClaimableAndAnyRatesInvalid(address account) returns (bool, bool)

Visibility

internal

State Mutability

view

_payFees

Source

Pays a quantity of fees in sUSD to a claiming address.

The quantity is burnt from the fee pool, and and then issued into the destination address.

Details

Signature

_payFees(address account, uint256 sUSDAmount)

Visibility

internal

State Mutability

nonpayable

Modifiers

_payRewards

Source

Pays a quantity of rewards to a specified address, escrowing it for one year with RewardEscrow.appendVestingEntry.

Details

Signature

_payRewards(address account, uint256 snxAmount)

Visibility

internal

State Mutability

nonpayable

Modifiers

_recentFeePeriodsStorage

Source

Details

Signature

_recentFeePeriodsStorage(uint256 index) returns (struct FeePool.FeePeriod)

Visibility

internal

State Mutability

view

_recordFeePayment

Source

Claims a quantity of fees from the recent fee periods.

Fees are deducted from each period's unclaimed fees in turn from the oldest to the most recent closed period as each is exhausted until either the entire quantity has been met, or the current fee period is reached.

As fees are not paid out from the current period, if there is any quantity left to be paid after all closed periods have been exhausted, it is simply ignored. Hence any losses due to rounding errors come out of the claim of the last person to claim. The function returns the quantity of fees actually claimed, which may be less than sUSDAmount in this case.

This is only called in _claimFees.

In pseudo-code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
remaining = sUSDAmount # The quantity to pay out.
paid = 0 # The quantity actually paid.

# Pay out fees from recent periods, from oldest to newest as they are exhausted.
# Don't traverse the current fee period.
for each closed period in reversed(recentFeePeriods):
    unclaimedFees = period.feesToDistribute - period.feesClaimed
    # Skip to the next period if this one is exhausted.
    if unclaimedFees == 0:
        continue

    # Don't pay out too much.
    payable = min(unclaimedFees, remaining)

    paid += payable
    period.feesClaimed += payable
    remaining -= payable

return paid
Details

Signature

_recordFeePayment(uint256 sUSDAmount) returns (uint256)

Visibility

internal

State Mutability

nonpayable

_recordRewardPayment

Source

Claims a quantity of SNX rewards from the recent fee periods. This is only called in _claimFees.

Its logic is identical to _recordFeePayment, except that the relevant quantities are in SNX, and are claimed from rewardsClaimed.

Details

Signature

_recordRewardPayment(uint256 snxAmount) returns (uint256)

Visibility

internal

State Mutability

nonpayable

_setLastFeeWithdrawal

Source

Stores into FeePoolEternalStorage the id of the fee period during which this address last withdrew fees.

Details

Signature

_setLastFeeWithdrawal(address _claimingAddress, uint256 _feePeriodID)

Visibility

internal

State Mutability

nonpayable

delegateApprovals

Source

Details

Signature

delegateApprovals() returns (contract IDelegateApprovals)

Visibility

internal

State Mutability

view

emitFeePeriodClosed

Source

Details

Signature

emitFeePeriodClosed(uint256 feePeriodId)

Visibility

internal

State Mutability

nonpayable

emitFeesClaimed

Source

Details

Signature

emitFeesClaimed(address account, uint256 sUSDAmount, uint256 snxRewards)

Visibility

internal

State Mutability

nonpayable

emitIssuanceDebtRatioEntry

Source

Details

Signature

emitIssuanceDebtRatioEntry(address account, uint256 debtRatio, uint256 debtEntryIndex, uint256 feePeriodStartingDebtIndex)

Visibility

internal

State Mutability

nonpayable

etherCollateralsUSD

Source

Details

Signature

etherCollateralsUSD() returns (contract IEtherCollateralsUSD)

Visibility

internal

State Mutability

view

exchanger

Source

Details

Signature

exchanger() returns (contract IExchanger)

Visibility

internal

State Mutability

view

feePoolEternalStorage

Source

The FeePoolEternalStorage key-value store that holds account last withdrawal times.

Type: FeePoolEternalStorage public

Details

Signature

feePoolEternalStorage() returns (contract FeePoolEternalStorage)

Visibility

internal

State Mutability

view

feePoolState

Source

The FeePoolState contract associated with this fee pool, which holds historical issuance data for the last several periods.

Type: FeePoolState public

Details

Signature

feePoolState() returns (contract FeePoolState)

Visibility

internal

State Mutability

view

issuer

Source

Details

Signature

issuer() returns (contract IIssuer)

Visibility

internal

State Mutability

view

rewardEscrow

Source

The RewardEscrow instance which holds inflationary rewards.

Type: RewardEscrow public

Details

Signature

rewardEscrow() returns (contract IRewardEscrow)

Visibility

internal

State Mutability

view

rewardsDistribution

Source

Details

Signature

rewardsDistribution() returns (contract IRewardsDistribution)

Visibility

internal

State Mutability

view

synthetix

Source

The main Synthetix contract.

Type: Synthetix public

Details

Signature

synthetix() returns (contract ISynthetix)

Visibility

internal

State Mutability

view

synthetixState

Source

The associated SynthetixState contract.

Type: SynthetixState public

Details

Signature

synthetixState() returns (contract ISynthetixState)

Visibility

internal

State Mutability

view

systemStatus

Source

Details

Signature

systemStatus() returns (contract ISystemStatus)

Visibility

internal

State Mutability

view

External Functions

claimFees

Source

The message sender claims their fees in sUSD.

This is equivalent to _claimFees(messageSender).

Details

Signature

claimFees() returns (bool)

Visibility

external

State Mutability

nonpayable

Modifiers

claimOnBehalf

Source

The message sender claims fees in sUSD for a specified address; the funds are remitted to that address, and not to the sender.

This function first checks with the DelegateApprovals contract that the sender is approved to claim fees on behalf of the specified address, but is otherwise equivalent to _claimFees(claimingForAddress).

Details

Signature

claimOnBehalf(address claimingForAddress) returns (bool)

Visibility

external

State Mutability

nonpayable

Requires

Modifiers

closeCurrentFeePeriod

Source

If the current fee period has been open for longer than feePeriodDuration, then anyone may call this function to close it and open a new one.

The new fee period is added to the beginning of the recentFeePeriods list, and the last one is discarded. Any unclaimed fees from the last fee period roll over into the penultimate fee period.

The new fee period's feePeriodId is the previous id incremented by 1, and its startingDebtIndex is the length of SynthetixState.debtLedger at the time the fee period rolls over. Note that before a new minting event occurs this index will be one past the end of the ledger.

Details

Signature

closeCurrentFeePeriod()

Visibility

external

State Mutability

nonpayable

Requires

Modifiers

setRewardsToDistribute

Source

Adds a quantity of SNX to the current fee period's total of rewards to be distributed.

Details

Signature

setRewardsToDistribute(uint256 amount)

Visibility

external

State Mutability

nonpayable

Requires

Modifiers

issuanceActive

Source

notFeeAddress

Source

Reverts the transaction if account is the fee address.

Signature: notFeeAddress(address account)

onlyInternalContracts

Source

onlyIssuer

Source

Events

FeePeriodClosed

Source

Signature: FeePeriodClosed(uint256 feePeriodId)

FeesClaimed

Source

Records that an account claimed the fees and rewards owed to them.

This event is emitted from the FeePool's proxy with the emitFeesClaimed function.

Signature: FeesClaimed(address account, uint256 sUSDAmount, uint256 snxRewards)

IssuanceDebtRatioEntry

Source

Records that a new account issuance record was appended to the account's issuance ledger in FeePoolState.

This event is emitted from the FeePool's proxy with the emitIssuanceDebtRatioEntry function.

Signature: IssuanceDebtRatioEntry(address account, uint256 debtRatio, uint256 debtEntryIndex, uint256 feePeriodStartingDebtIndex)