Fee Sharing

The FeeSharingCollector contract. This contract withdraws fees to be paid to SOV Stakers from the protocol. Stakers call withdraw() to get their share of the fees.

Staking is not only granting voting rights, but also access to fee sharing according to the own voting power in relation to the total. Whenever somebody decides to collect the fees from the protocol, they get transferred to this contract and converted when possible into rBTC. The fee sharing contract is set as feesController of the protocol contract. This allows the fee sharing contract to withdraw the fees. The fee sharing proxy holds the pool tokens and keeps track of which user owns how many tokens.

A similar dynamics happens with the AMM network of converters, and with the ZERO protocol. Also there was a program earning rewards from the "MYNT Bootstrap" protocol. So, the fee sharing contract can distribute rBTC, ZUSD, SOV and for some old stakers, some MYNT yet.

In order to know how many tokens a user owns, the fee sharing proxy needs to know the user’s weighted stake in relation to the total weighted stake (aka total voting power). Because both values are subject to change, they may be different on each fee withdrawal. To be able to calculate a user’s share of tokens when he wants to withdraw, we need checkpoints in time.

This contract is intended to be set as the protocol fee collector. Anybody can invoke the withdrawFees function which uses the protocol.withdrawFees function to obtain available fees from operations on a certain token. These fees are deposited in the corresponding loanPool. When a user calls the withdraw function, the contract transfers the fee sharing rewards in proportion to the user’s weighted stake since the last withdrawal.

EXTRACTING REWARDS FROM CORE PROTOCOL, AMM AND ZERO

Essentially, all fees distributed from the ZERO protocol are sent to the fee sharing contract each time a set of transaction of such protocol are performed. This is intimately related to the history of the Sovryn protocol: FeeSharingCollector was implemented after the AMM and the core protocol, so the fee distribution code was already set on those protocols, and we need a lump transfer from the fees collected from those protocols to the fee sharing; while in the ZERO protocol, this setting was done in the process of implementing it on our ecosystem.

The extraction of fees from the core protocol is done by feeSharingCollector.withdrawFees function:

function withdrawFees(address[] calldata _tokens) external

Arguments

Name
Type
Description

_tokens

address[]

Array address of the underlying tokens of each lending pool of the core protocol This involves lendingFee + tradingFee + borrowingFee

he extraction of fees from the AMM network protocol is done by feeSharingCollector.withdrawFeesAMM function:

function withdrawFeesAMM(address[] memory _converters) public

Arguments

Name
Type
Description

_converters

address[]

Array addresses of the AMM converters -No of the assets-

While a cronjob execute the former transactions once per week, anybody can execute them.

CLAIMING REWARDS

Currently there are two functions a user can execute in order to retrieve their rewards from Sovryn's protocol:

function withdraw(
        address _token,
        uint32 _maxCheckpoints,
        address _receiver
    ) public nonReentrant 

This function will withdraw accumulated fees per asset to the message sender. This method is suited for users that regularly withdraw their fees. When time has passed since the last withdrawal, gas fees can easily exceed the block gas limit of RSK network.

Arguments

Name
Type
Description

_token

address

Asset reward address; for rBTC, we use the dummy address: 0xeabd29be3c3187500df86a2613c6470e12f2d77d

_maxCheckpoints

uint32

Maximum number of checkpoints to be processed. Must be positive value, and recommended to be less than 100.

_receiver

address

The receiver of tokens or msg.sender .

However, when to many assets per checkpoint are left to claim, the withdraw function becomes unfeasible, then we can use the following:

function claimAllCollectedFees(
        address[] calldata _nonRbtcTokensRegularWithdraw,
        address[] calldata _rbtcTokensRegularWithdraw,
        TokenWithSkippedCheckpointsWithdraw[] calldata _tokensWithSkippedCheckpoints,
        uint32 _maxCheckpoints,
        address _receiver
    ) external nonReentrant

Arguments

Name
Type
Description

_nonRbtcTokensRegularWithdraw

address[]

array of non-rbtc token address with no skipped checkpoints that will be withdrawn

_rbtcTokensRegularWithdraw

address[]

array of rbtc token address with no skipped checkpoints that will be withdrawn

_tokensWithSkippedCheckpoints

TokenWithSkippedCheckpointsWithdraw[] an array of parameters of struct type: TokenWithSkippedCheckpointsWithdraw

array of rbtc & non-rbtc TokenWithSkippedCheckpointsWithdraw struct, which has skipped checkpoints that will be withdrawn

_maxCheckpoints

uint32

Maximum number of checkpoints to be processed. Must be positive value, and recommended to be less than 100.

_receiver

address

The receiver of tokens or msg.sender

The former function is complex to execute, so in order to get more details on how to implement it in an interface, the user can check the unit tests of this function.

Last updated