Skip to main content

Deploying a Custom Super Token

This guide will walk you through the process of deploying a Custom Super Token for the Superfluid protocol. Custom Super Tokens allow you to create tokens with additional functionality while maintaining compatibility with the Superfluid protocol.

This documentation contains different guides if you are looking to easily deploy a simple Wrapped Super Token or a simple Pure Super Token from your interface with no code. We strongly recommend to check those guides first before this one.

For the purposes of this guide, we'll explore two examples:

Prerequisites

Before we begin, make sure you have the following:

  • Foundry installed on your system
  • Basic knowledge of Solidity and smart contract development

Getting Started

First, let's clone the Custom Super Tokens repository:

git clone https://github.com/superfluid-finance/custom-supertokens
cd custom-supertokens

This repository is structured as a Foundry project and contains multiple examples of custom Super Tokens.

Once you've cloned the repository, install the dependencies:

forge install

This command will install the required packages, including @superfluid-finance, @openzeppelin-contracts (v4.9.3), and forge-std.

Example 1: Pure Super Token

Let's start with the Pure Super Token example. This is a simple custom Super Token implementation.

Understanding the Contract

The PureSuperToken.sol file contains the contract for our Pure Super Token:

contract PureSuperTokenProxy is CustomSuperTokenBase, UUPSProxy {
function initialize(
ISuperTokenFactory factory,
string memory name,
string memory symbol,
address receiver,
uint256 initialSupply
) external {
ISuperTokenFactory(factory).initializeCustomSuperToken(address(this));
ISuperToken(address(this)).initialize(
IERC20(address(0)),
18,
name,
symbol
);
ISuperToken(address(this)).selfMint(receiver, initialSupply, "");
}
}

This contract creates a new UUPSProxy which is initialized as a Pure Super Token. The initialize function sets up the token using the SuperTokenFactory and mints the initial supply to the specified receiver.

Testing

To test the Pure Super Token, run:

forge test --match testDeploy testSuperTokenBalance

This will execute the tests in PureSuperToken.t.sol, which include deploying the token and checking the receiver's balance.

Deployment

To deploy the Pure Super Token, use the following Foundry command:

forge create --rpc-url <RPC_URL> --private-key <YOUR_PRIVATE_KEY> --etherscan-api-key <YOUR_API_KEY> --verify --via-ir src/PureSuperToken.sol:PureSuperTokenProxy

Replace <RPC_URL>, <YOUR_PRIVATE_KEY>, and <YOUR_API_KEY> with your actual values.

Initialization

After deployment, you need to initialize the token by calling the initialize function with the appropriate parameters:

pureSuperToken.initialize(
superTokenFactory,
"MyToken",
"MTK",
initialReceiver,
initialSupply
);

Example 2: Bridged Super Token

The Bridged Super Token is a more complex example that includes additional functionality for cross-chain operations.

Understanding the Contract

The BridgedSuperToken.sol file contains the contract for our Bridged Super Token. This implementation includes features like minting and burning limits for bridges.

Testing

To test the Bridged Super Token, run:

forge test

This will execute the tests in BridgedSuperTokenTest.t.sol, which cover various aspects of the token's functionality, including limit setting, minting, and burning.

Deployment and Initialization

The deployment and initialization process for the Bridged Super Token is similar to the Pure Super Token. Use the forge create command for deployment, and then call the initialize function to set up the token.

Creating Your Own Custom Super Token

When creating your own custom Super Token, you can use the following functions from the ISuperToken Interface

selfMint

function selfMint(
address account,
uint256 amount,
bytes memory userData
) external;

This function mints new tokens for the specified account. If userData is not empty, it invokes the tokensReceived hook according to ERC777 semantics.

selfBurn

function selfBurn(
address account,
uint256 amount,
bytes memory userData
) external;

This function burns existing tokens for the specified account. If userData is not empty, it invokes the tokensToSend hook according to ERC777 semantics.

selfTransferFrom

function selfTransferFrom(
address sender,
address spender,
address recipient,
uint256 amount
) external;

This function transfers tokens from the sender to the recipient. If spender isn't the same as sender, it checks if spender has allowance to spend tokens of sender.

selfApproveFor

function selfApproveFor(
address account,
address spender,
uint256 amount
) external;

This function gives spender the amount allowance to spend the tokens of account.

These functions allow you to customize the behavior of your Super Token while maintaining compatibility with the Superfluid protocol.

Conclusion

By following this guide, you should now be able to deploy and initialize custom Super Tokens for the Superfluid protocol. Remember to thoroughly test your custom implementations and consider the security implications of any additional functionality you add to your tokens.

For more information on Custom Super Tokens, check out the Custom Super Token Wiki and the Deploy a Custom Super Token Guide.