oFT
oFT is a Fungible Token created on Oasys Hub. oFT can be bridged between the Verse Layer(L2) and the Hub Layer(L1).
When creating an oFT, it is necessary to create an ERC20 for each Hub (L1) and Verse (L2).
How to create oFT
In this tutorial, L1 is set to Oasys Testnet and L2 to Oasys SAND Verse.
// hardhat.config.ts
networks: {
l1: {
url: 'https://rpc.testnet.oasys.games/',
chainId: 9372,
accounts: [process.env.PRIVATE_KEY],
},
l2: {
url: 'https://rpc.sandverse.oasys.games/',
chainId: 20197,
accounts: [process.env.PRIVATE_KEY],
initialBaseFeePerGas: 0,
gasPrice: 0,
},
},
If you want to create an oFT, please refer to this tutorial to generate the code to create an oFT.
When you create an oFT, please also do the following.
- Set the name or symbol of the oFT
- Set network you want to create oFT at
hardhat.config.ts
(Both L1 and L2) - Please refer to the
Address
andReference Code
of Hub Layer’s Preset Contracts for L1StandardERC20Factory and Verse’s Preset Contracts for L2StandardTokenFactory. - For L1StandardERC20, please refer here, and for L2StandardERC20, please refer here.
Create L1StandardERC20 at Oasys Hub
- Switch to the Hub network where you want to create the oFT
npx hardhat console --network l1
- Create L1StandardERC20 with oFT_NAME, oFT_SYMBOL
const oFT_NAME = "MyToken"
const oFT_SYMBOL = "MTK"
const l1ERC20FactoryAbi = [ "function createStandardERC20(string memory _name, string memory _symbol) external" ]
const l1ERC20FactoryAddress = "0x5200000000000000000000000000000000000004"
const l1ERC20Factory = await ethers.getContractAt( l1ERC20FactoryAbi , l1ERC20FactoryAddress )
const tx1 = await l1ERC20Factory.createStandardERC20( oFT_NAME , oFT_SYMBOL )
const receipt1 = await tx1.wait()
const l1ERC20Address = "0x" + receipt1.logs.find((log) => log.topics[0] == '0xd714a43f627528ad95fc3dcf6c453cf595be2f4d75c58c4273f17208ed899f44').topics[2].slice(-40)
console.log(l1ERC20Address)
Mint oFT at Hub
- l1oft Mint with oFT_RECIPIENT_ADDRESS, oFT_AMOUNT
const [ signer ] = await ethers.getSigners()
const oFT_RECIPIENT_ADDRESS = signer.address
const oFT_AMOUNT = ethers.parseEther('1000')
const l1ERC20Abi = [ "function mint(address to, uint256 amount) external", "function balanceOf(address account) external view returns (uint256)" ]
const l1oft = await ethers.getContractAt( l1ERC20Abi , l1ERC20Address )
const tx2 = await l1oft.mint( oFT_RECIPIENT_ADDRESS, oFT_AMOUNT )
const receipt2 = await tx2.wait()
console.log(await l1oft.balanceOf(oFT_RECIPIENT_ADDRESS))
// 1000000000000000000000n
If token minting is successful, go to your account page in Oasys Hub Explorer. You can then click on the Tokens
menu to view tokens you own.
Create L2StandardERC20 at Verse
- Switch to the Verse network where you want to create the oFT
npx hardhat console --network l2
- Create L2StandardERC20 with L1_oFT_ADDRESS, oFT_NAME, oFT_SYMBOL
const L1_oFT_ADDRESS = "0xYourL1oFTAddress" // l1oft.target
const oFT_NAME = "MyToken"
const oFT_SYMBOL = "MTK"
const l2ERC20FactoryAbi = [ "function createStandardL2Token(address _l1Token, string memory _name, string memory _symbol) external" ]
const l2ERC20FactoryAddress = "0x4200000000000000000000000000000000000012"
const l2ERC20Factory = await ethers.getContractAt( l2ERC20FactoryAbi , l2ERC20FactoryAddress )
const tx3 = await l2ERC20Factory.createStandardL2Token( L1_oFT_ADDRESS, oFT_NAME, oFT_SYMBOL )
const receipt3 = await tx3.wait()
const l2ERC20Address = "0x" + receipt3.logs.find((log) => log.topics[0] == '0xceeb8e7d520d7f3b65fc11a262b91066940193b05d4f93df07cfdced0eb551cf').topics[2].slice(-40)
console.log(l2ERC20Address)
Import token to metamask
The token has been created but is not visible on the metamask. In this case, you must import tokens from the metamask according to how it was written in this section.
Import l1oft
address at Hub, l2oft
address at Verse.
How to bridge oFT between Hub and Verse
If you want to know about bridge oFT between Hub and Verse, please refer bridge tutorial and the code in the bridge tutorial.
How to create oFT with non-standard decimals
The decimals for oFTs created by the L1StandardERC20Factory and L2StandardTokenFactory, namely L1StandardERC20 and L2StandardERC20, default to 18.
If you wish to create a special oFT token with decimals other than 18, we recommend inheriting from L1StandardERC20 and L2StandardERC20 and overriding the decimals.
Below is an example of creating a USDC.e contract with 6 decimals on Verse.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import "./L2StandardERC20.sol";
contract USDCe is L2StandardERC20 {
/**
* @param _l2Bridge Address of the L2 standard bridge.
* @param _l1Token Address of the corresponding L1 token.
* @param _name ERC20 name.
* @param _symbol ERC20 symbol.
*/
constructor(
address _l2Bridge,
address _l1Token,
string memory _name,
string memory _symbol
) L2StandardERC20(_l2Bridge, _l1Token, _name, _symbol) {
}
function decimals() public view virtual override returns (uint8) {
return 6;
}
}