Runes Mock Bridge Contract Explanation walk through
1. Understanding the Contract Structureβ
This contract defines a new token type, RuneToken, based on the ERC-1155 standard. It also uses the Ownable contract, which restricts certain functions to the contract's owner.
Key Imports:β
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
- ERC1155: This is a token standard that supports both fungible and non-fungible tokens within the same contract.
- Ownable: This contract standard restricts certain actions to only the contract's owner (the one who deployed it or someone assigned as the owner).
- Strings: A utility library for working with string conversions.
Main Components of the Contractβ
Events:β
TokensFrozen
: Emits an event when tokens are frozen for a specific account.TokensUnfrozen
: Emits an event when tokens are unfrozen.
Data Structures:β
- Balance: Holds the account and balance of a token.
- TokenInfo: Contains details about a token, such as its URI ( Uniform Resource Identifier), name, symbol, maximum supply, current supply, default minting amount, and balance.
Mappings:β
_tokenInfos
: Stores the information about each token, keyed by the token ID._userTokens
: Tracks all tokens held by a user._frozenTokens
: Keeps track of how many tokens are frozen for each user.
2. The Constructorβ
constructor(address initialOwner) ERC1155("") Ownable(initialOwner) {}
- ERC1155 (""): This calls the ERC1155 constructor, but the URI is set as an empty string initially.
- Ownable (initialOwner): The
Ownable
contract is initialized with theinitialOwner
as the owner of the contract, allowing only this address to perform certain actions (e.g., minting).
3. The uri
Functionβ
function uri(uint256 tokenId) public view override returns (string memory) {
return _tokenInfos[tokenId].uri;
}
This function returns the URI for a given token ID. The URI typically points to a metadata file that contains additional details about the token (e.g., images, descriptions).
4. Minting Fungible Tokensβ
function mintFungible(
string memory tokenURI,
string memory runeName,
string memory symbol,
uint256 maxSupply,
uint256 initialSupply,
uint256 defaultMintAmount,
address receiver
) public onlyOwner {
// Function logic here
}
This function allows the owner of the contract to mint fungible tokens.
Steps Involved:β
- Check max supply: Ensure that the initial supply is not greater than the maximum allowed supply.
- Generate a token ID: A unique token ID is created by hashing the
runeName
usingkeccak256
. - Token ID uniqueness check: Ensure that the token ID doesn't already exist.
- Save Token Info: Store details about the token in the
_tokenInfos
mapping. - Mint the token: Mint the specified amount (
initialSupply
) to thereceiver
address. - Track ownership: Add the minted token to the user's list of owned tokens using
_addUserToken
.
5. Minting Non-Fungible Tokens (NFTs)β
function mintNonFungible(
string memory tokenURI,
string memory runeName,
string memory symbol,
address receiver
) public onlyOwner {
// Function logic here
}
This function is similar to mintFungible
but for minting non-fungible tokens. A non-fungible token is a unique token, meaning only one exists.
Key Differences:β
- Max Supply is always
1
for non-fungible tokens. - Current Supply is also set to
1
.
6. Minting More Tokensβ
function mintMore(
string memory runeName,
address receiver
) external onlyOwner {
// Function logic here
}
This function allows the contract owner to mint additional tokens of an existing fungible token, as long as the new supply doesnβt exceed the maximum supply.
Key Steps:β
- Check token existence: Ensure the token exists by checking its
maxSupply
. - Check supply limits: Ensure the current supply plus the new minting amount doesnβt exceed the max supply.
- Mint tokens: Mint more tokens to the
receiver
.
7. Token Freezing and Unfreezingβ
Freezing Tokens:β
function freezeTokens(string memory runeName, uint256 amount, address owner) external onlyOwner {
// Function logic here
}
- Freezing tokens restricts the user from transferring them.
- The function ensures that the account has sufficient tokens to freeze.
- The frozen amount is added to
_frozenTokens
.
Unfreezing Tokens:β
function unfreezeTokens(string memory runeName, uint256 amount, address owner) external onlyOwner {
// Function logic here
}
- This function unfreezes the tokens, allowing the user to transfer them again.
- The frozen amount is reduced from
_frozenTokens
.
8. Token Information Queriesβ
Get Token Information:β
function getTokenInfo(uint256 tokenId, address holder) public view returns (TokenInfo memory) {
// Function logic here
}
- This function retrieves the details about a token (such as URI, name, symbol, max supply, etc.).
- It can also include the token balance of a specific
holder
if theholder
address is provided.
Get Tokens Owned by a User:β
function getUserTokens(address user) public view returns (uint256[] memory) {
return _userTokens[user];
}
- This function returns a list of all token IDs owned by a specific user.
9. Token Transfer Functions with Freezing Considerationβ
ERC1155 includes transfer functions (safeTransferFrom
and safeBatchTransferFrom
). These are overridden in this contract to take into account frozen tokens.
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes memory data
) public virtual override {
require(balanceOf(from, id) >= amount + _frozenTokens[id][from], "Insufficient unlocked balance for transfer");
super.safeTransferFrom(from, to, id, amount, data);
}
This ensures that users cannot transfer frozen tokens. The contract checks that the unlocked balance (total balance minus frozen balance) is sufficient before allowing transfers.
10. Overriding balanceOf
to Consider Frozen Tokensβ
function balanceOf(address account, uint256 tokenId) public view override returns (uint256) {
uint256 totalBalance = super.balanceOf(account, tokenId);
uint256 frozenBalance = _frozenTokens[tokenId][account];
return totalBalance - frozenBalance;
}
This function returns the number of unfrozen tokens owned by a user for a specific token ID.