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.