Skip to content

About Custom Super Token

0xdavinchee edited this page Feb 2, 2022 · 8 revisions

Background

Super Token created through the Super Token Factory is also called the "managed super tokens". There are two types of managed super tokens supported , one is ERC20 Wrapper type, the other is Custom Super Token type. Custom Super Token is assumed to be of a Superfluid Variant😷 of UUPS proxy, and it is initialized with the current Super Token Logic contract address through the Super Token Factory.

Self-call Pattern

To be able to implement useful custom super token logic, you would need to provide some custom logic which call upon the functions that exist in the current base Super Token implementation contract. The self-call pattern was developed exactly for this purpose.

This pattern allows you to write custom logic in your proxy Super Token logic contract with access control and permissions considered. Normally, when you make a call to a proxy contract, this contract redirects the call with a delegateCall to the implementation contract, where msg.sender is the original caller. With the self-call pattern, the msg.sender becomes the Super Token contract, thus creating a layer between the initial caller and the implementation contract. The self-call pattern enables the creation of custom functions on the proxy contract where the msg.sender is not the original caller, but the Super Token contract.

All the self-call functions have a modifier, onlySelf that enforces the self-call pattern:

modifier onlySelf() {
    require(msg.sender == address(this), "SuperToken: only self allowed");
    _;
}

An example of a function which follows the self-call pattern is selfMint:

function selfMint(
    address account,
    uint256 amount,
    bytes memory userData
)
    external override
    onlySelf
{
    _mint(msg.sender, account, amount,
        false /* requireReceptionAck */, userData, new bytes(0));
}

function _mint(
    address operator,
    address account,
    uint256 amount,
    bool requireReceptionAck,
    bytes memory userData,
    bytes memory operatorData
)
    internal
{
    require(account != address(0), "SuperToken: mint to zero address");
    SuperfluidToken._mint(account, amount);
    _callTokensReceived(operator, address(0), account, amount, userData, operatorData, requireReceptionAck);
    emit Minted(operator, account, amount, userData, operatorData);
    emit Transfer(address(0), account, amount);
}

The self-call pattern functions which we support:

  • selfMint
  • selfBurn
  • selfApprove
  • selfTransferFrom

Possible Custom Features

TO BE COMPLETED...

Upgradability of the Custom Logic

TO BE COMPLETED...

Clone this wiki locally