EthereansFactory fees utility methods

EthereansFactory contract

The EthereansFactory contract is an abstract utility contract that implemented in all EthereansOs custom Factories contracts with a fee-based business model.

The EthereansFactory implements the standard Factory contract, obtaining all the capabilities of Factory.

The EthereansFactory contract has the following capabilities:

  • it can be initialized with a model contract to clone

  • it provides the deploy method to clone the model contract

  • it provides the three methods to implement a fee-based business model in your custom Factory interacting with the FoF methods

  • it provides a series of initializable parameters that can be used to set the fees logic overriding the empty virtual _factoryLazyInit provided by the standard Factory contract

  • it provides the empty virtual _ethosFactoryLazyInit function. It is internally called when initializing the Factory and it can be overridden to initialize the Factory specific parameters

Unlike the standard Factory contract, a custom Factory implementing EthereansFactory, doesn't allow to change the model contract once set.

Here, you can find all the EthereansOs Factories implementing the EthereansFactory contract.

Fees methods

The EthereansFactory abstract utility contract provides three methods to implement a fee-based business model:

  • Creation Fee -> _burnOrTransferTokenAtCreation , it calls the FoF burnOrTransferTokenAmount function

  • Static usage fee (burn or transfer) -> burnOrTransferTokenAmount, it calls the FoF burnOrTransferTokenAmount function

  • Percentage usage fee -> payFee, it calls the FoF payFee function

Creation fee

The _burnOrTransferTokenAtCreation function must be used to implement a Creation Fee:

function _burnOrTransferTokenAtCreation(address sender, bytes memory permitSignature) internal returns(uint256 feeSentOrBurnt, uint256 amountTransferedOrBurnt) {

The _burnOrTransferTokenAtCreation takes as input:

  • address sender -> user address paying the fee

  • bytes permitSignature -> bytes containing the permitSignature parameter to perform an off-chain sign. If this parameter is not passed, the classic token approved is required

Static Usage fee

The burnOrTransferTokenAmount must be used in order to implement a static usage fee (burn or transfer):

function burnOrTransferToken(address sender, bytes calldata permitSignature) external payable returns(uint256 feeSentOrBurnt, uint256 amountTransferedOrBurnt);

The burnOrTransferTokenAmount takes as input:

  • address sender -> user address paying the fee

  • bytes permitSignature -> bytes containing the permitSignature parameter to perform an off-chain sign. If this parameter is not passed, the classic token approved is required

Percentage Usage fee

The payFee must be used in order to implement a percentage usage fee:

function payFee(address sender, address tokenAddress, uint256 value, bytes calldata permitSignature) external payable returns (uint256 feeSentOrBurnt, uint256 feePaid);

The payFees function takes as input:

  • address sender -> user address paying the fee

  • address tokenAddress -> token address with which the fee must be paid

  • uint256 value -> token amount transacted by a user

  • bytes permitSignature -> bytes containing the permitSignature parameter to perform an off-chain sign. If this parameter is not passed, the classic token approved is required

Set the Fee Parameters

These are the parameters to set during initialization of a Factory implementing EthereansFactory to configure fee logic:

For a Creation Fee

  • tokenToTransferOrBurnAddressInCreation -> the address of the token that must be paid as the fee

  • transferOrBurnAmountInCreation -> the (fixed) amount of the fee

  • transferOrBurnAmountInCreation -> the address of the receiver of the fee. If set as address(0), the fee is burned; if populated, it is the address of the receiver of the fee

For a Usage Fee

  • feePercentageforTransacted -> the percentage to be taken as a fee of transacted amounts (used only for % fees)

  • feeReceiver -> the address of the receiver of the fee (used only for % fees)

  • tokenToTransferOrBurnAddressInApplication -> the address of the token that must be paid as the fee (used only for static fees)

  • transferOrBurnAmountInApplication -> the (fixed) amount of the fee (used only for static fees)

  • transferOrBurnReceiverInApplication -> the address of the receiver of the fee; if set as address(0), the fee is burned; if populated, it is the address of the receiver of the fee (used only for static fees)

As you can see, for % Usage Fees, a fixed address for the token that is paid as a fee is not set, but is rather an input parameter of the payFee function.

This is because the payFee function, and therefore the % fee, is paid at the moment a user interacts with the model contract via a transaction. Depending on the logic written in the model contract, the % can be applied to any amount of transacted token.

For the example on the previous page, payFee is passed—and therefore the % of LP tokens is paid—at the moment the position is closed, partially or fully (in this case, the passed tokenAddress is the LP token address), or at the moment the rewards is claimed (in this case, the passed tokenAddress is the reward token address).

Here, you can find how to initialize your Factory.

Overridable functions

The EthereansFactory provides also two virtual utility methods that can be overridden in a Factory implementing it:

_realFeeInfo

It can be used to build a custom logic where the Fees parameters values, explained above, are retrieved from an external contract.

So if the _realFeeInfo function is not overridden, it retrieves the values of the Fees parameters set at the time of contract initialization, and it passed them to the _burnOrTransferAtCreation, burnOrTransferTokenAmount and payFee functions.

If the _realFeeInfo is overridden, you can create a custom logic where the value of those variables (or some of them) are passed from outside, rather than taken from initialized values.

Example

The Covenants Farming Factory retrieves the value of

  • feePercentageForTransacted

  • transferOrBurnAmountInApplication

from the EthereansOs Organization State Manager:

function _realFeeInfo() internal override view returns(uint256 feePercentageForTransacted, address feeReceiver, address tokenToTransferOrBurnAddressInCreation, uint256 transferOrBurnAmountInCreation, address transferOrBurnReceiverInCreation, address tokenToTransferOrBurnAddressInApplication, uint256 transferOrBurnAmountInApplication, address transferOrBurnReceiverInApplication) {
    IOrganization host = IOrganization(ILazyInitCapableElement(initializer).host());
    if(address(host) != address(0)) {
        feeReceiver = address(this);
        transferOrBurnReceiverInApplication = address(0);
        IStateManager stateManager = host.stateManager();
        if(address(stateManager) != address(0)) {

            string[] memory keys = new string[](2);
            keys[0] = EthereansOSState.STATEMANAGER_ENTRY_NAME_FARMING_FEE_PERCENTAGE_FOR_TRANSACTED;
            keys[1] = EthereansOSState.STATEMANAGER_ENTRY_NAME_FARMING_FEE_FOR_BURNING_OS;

            IStateManager.StateEntry[] memory entries = stateManager.list(keys);
            feePercentageForTransacted = entries[0].value.length > 0 ? entries[0].value.asUint256() : 0;
            transferOrBurnAmountInApplication = entries[1].value.length > 0 ? entries[1].value.asUint256() : 0;

            return (
                feePercentageForTransacted,
                feeReceiver,
                tokenToTransferOrBurnAddressInCreation,
                transferOrBurnAmountInCreation,
                transferOrBurnReceiverInCreation,
                _tokenToTransferOrBurnAddressInApplication,
                transferOrBurnAmountInApplication,
                transferOrBurnReceiverInApplication
            );
        }
    }
}

_feePaid

It can be used to build a custom logic to manage the transfer Fees amount of the Usage Percentage Fees.

Example

The Covenants Farming Factory manage the transfer Usage Percentage Fee in this way:

  • the Fee amount is sent to the Farming Factory (so the receiver parameter passed to the payFee FoF function is the Farming Factory itself)

  • the _feePaid override allows to burn the Fee amount if the Fee is expressed in $OS. Otherwise it sends the Fee amount to the treasurySplitterManager or, if a treasurySplitterManager is not attached, it sends it to the Organization Root Treasury

function _feePaid(address, address tokenAddress, uint256, uint256, uint256 feePaid, uint256, address) internal override {
    if(feePaid > 0) {
        if(tokenAddress == _tokenToTransferOrBurnAddressInApplication) {
            ERC20Burnable(tokenAddress).burn(feePaid);
        } else {
            IOrganization host = IOrganization(ILazyInitCapableElement(initializer).host());
            if(address(host) != address(0)) {
                address receiver = address(IOrganization(host).treasurySplitterManager());
                receiver = receiver != address(0) ? receiver : address(IOrganization(host).treasuryManager());
                if(receiver != address(0)) {
                    tokenAddress.safeTransfer(receiver, feePaid);
                }
            }
        }
    }
}

Last updated