Skip to content

superfluid-finance/custom-supertokens

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

47 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Custom Super Tokens

This repository shows how to implement custom SuperTokens.

A custom SuperToken contract typically consists of:

  • (immutable) proxy contract with custom logic
  • (upgradable) logic contract containing ERC20 and SuperToken functionality

By convention, SuperToken contracts are instances of UUPSProxy. A custom Super Token has custom logic added to this proxy contract.

PureSuperTokenProxy.sol is the simplest variant of a custom SuperToken. It's a Pure SuperToken (no underlying ERC20) which has its supply minted on creation.

CustomERC20WrapperProxy.sol shows how a Wrapper SuperToken (has an unerlying ERC20) could be customized.

xchain contains more advanced variants of Custom SuperTokens, suited for cross-chain deployments (e.g. bridging ERC20 <-> SuperToken). See the dedicated section for more.

Setup

To set up the repo for development, start by cloning the repo

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

Installing Foundry

Make sure you have installed Foundry. If you don't have Foundry on your development environment, please refer to Foundry Book.

Install dependencies

Once Foundry has been installed, you can run the following command to install dependencies

forge install

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

Create your Custom Super Token

As an example of creating your own Custom Super Token, we can take a look at the PureSuperToken.sol contract.

contract PureSuperTokenProxy is CustomSuperTokenBase, UUPSProxy {
	// This shall be invoked exactly once after deployment, needed for the token contract to become operational.
	function initialize(
		ISuperTokenFactory factory,
		string memory name,
		string memory symbol,
		address receiver,
		uint256 initialSupply
	) external {
		// This call to the factory invokes `UUPSProxy.initialize`, which connects the proxy to the canonical SuperToken implementation.
		// It also emits an event which facilitates discovery of this token.
		ISuperTokenFactory(factory).initializeCustomSuperToken(address(this));

		// This initializes the token storage and sets the `initialized` flag of OpenZeppelin Initializable.
		// This makes sure that it will revert if invoked more than once.
		ISuperToken(address(this)).initialize(
			IERC20(address(0)),
			18,
			name,
			symbol
		);

		// This mints the specified initial supply to the specified receiver.
		ISuperToken(address(this)).selfMint(receiver, initialSupply, "");
	}
}

This contract simply creates a new UUPSProxy with a custom initialize method. This method calls SuperTokenFactory.initializeCustomSuperToken (which emits events facilitating discovery of the SuperToken), then mints the full supply of the token to the receiver.

For more information on the creation of Custom Super Tokens, please refer to the Technical Documentation or the Protocol Wiki.

Test your Custom Super Token Contract

Once you created your custom logic in the Custom Super Token Contract, you can now go ahead and write tests of your Custom Super Token.

Going back to the previous example of the Pure Super Token contract, we can see that the file including the tests of PureSuperToken contract is PureSuperToken.t.sol.

This file contains a deployment of the protocol in the method setUp as such:

function setUp() public {
		vm.etch(ERC1820RegistryCompiled.at, ERC1820RegistryCompiled.bin);
		SuperfluidFrameworkDeployer sfDeployer = new SuperfluidFrameworkDeployer();
		sfDeployer.deployTestFramework();
		_sf = sfDeployer.getFramework();
	}

Then the file contains 2 tests, one of deployment and the other to check the receiver's balance

	function testDeploy() public {
		_superTokenProxy = new PureSuperTokenProxy();
		assert(address(_superTokenProxy) != address(0));
	}

	function testSuperTokenBalance() public {
		_superTokenProxy = new PureSuperTokenProxy();
		_superTokenProxy.initialize(
			_sf.superTokenFactory,
			"TestToken",
			"TST",
			_OWNER,
			1000
		);
		ISuperToken superToken = ISuperToken(address(_superTokenProxy));
		uint balance = superToken.balanceOf(_OWNER);
		assert(balance == 1000);
	}

To run these tests you can run the test command from Foundry:

forge test

Deployment

There are multiple ways to manage the deployment of a Custom Super Token. One of them is using the following command line by replacing the proper arguments with your requirements:

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

Learn more about Custom Super Tokens

To learn more about Custom Super Tokens, check the following resources:

Bridging with xERC20

xERC20 is a bridge-agnostic protocol which allows token issuers to deploy crosschain native tokens with zero slippage, perfect fungibility, and granular risk settings — all while maintaining ownership of your token contracts..

BridgedSuperToken.sol extends a Pure SuperToken with the xerc20 interface. The core functions are mint and burn. They leverage the hooks selfMint and selfBurn provided by the canonical Super Token implementation. The rest of the logic is mostly about setting and enforcing rate limits per bridge. The limits are defined as the maximum token amount a bridge can mint or burn per 24 hours (rolling time window).

Optimism / Superchain Standard Bridge

L2's based on the OP / Superchain stack can use the native Standard Bridge for maximum security.

OPBridgedSuperToken.sol allows that by implementing the required ´IOptimismMintableERC20interface. Itsmint()andburn()match those of IXERC20, but it addsbridge()(address of the bridge contract),remoteToken()(address of the token on L1) andsupportsInterface()` (ERC165 interface detection).

HomeERC20

Is a plain OpenZeppelin based ERC20 with ERC20Votes extension. It's suitable for multichain token deployments which want an ERC20 representation on L1 and Super Token representations on L2s.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published