Anatomy of a smart contract
Anatomy of a smart contract
💡INFO
What is a smart contract?
Deep dive into smart contract types:
Fungible
Non-fungible
Use cases of fungible and non-fungible tokens
What is a smart contract?
A smart contract is a class of code that is deployed to and runs on the blockchain. They can be made up of any arrangement of code and perform a wide range of functionality.
Examples of some common smart contracts:
Settlement contracts: Facilitates the sale of assets from one user (seller) to another (buyer) by handling the filling of an order, payment and transfer of assets. Typically used by marketplaces in conjunction with an orderbook service.
Token contracts: Facilitates the creation (minting) of tokens that can be used and transferred between users in the open market.
The main type of smart contract that we are mostly concerned about as developers of blockchain games and NFT applications are token smart contracts.
Token smart contracts
These are smart contracts that govern the issuance (creation) of tokens. These contracts are typically defined by standards, which specify the functions that it needs to have to ensure that there is a standard way that games, applications and other contracts can interact with it.
The two main kinds of token smart contracts that we are concerned with when building games or NFT applications on XpansionChain are:
Non-fungible (defined by the ERC-721 standard) - these produce tokens with unique properties from other tokens in their collection. For example, Bored Ape #1 isn't interchangeable for Bored Ape #2 because they differ across a range of characteristics (ie. image, rarity) that different users will value differently.
Fungible (defined by the ERC-721 standard) - these produce commodity-like tokens that are interchangeable with another token in its category, ie. ETH, IMX. If you lend someone ETH, it doesn't matter whether they send you back the exact same tokens that you lent them. All ETH tokens are identical and their value is the same.
There are also semi-fungible contracts (defined by the ERC-1155 standard), which can be very useful for blockchain games, however, they are not fully supported by XpansionChain yet.
As you might expected, non-fungible token contracts produce non-fungible tokens (NFTs), fungible contracts produce fungible tokens and... well, you get the drift 😉
Key components of fungible and non-fungible token contracts:
Information stored about tokens
How many tokens in total can this contract create?
Contract function:
totalSupply()
returns this value
How many tokens in total can this contract create?
Contract function (in ERC-721 enumerable, which is an extension of the ERC-721 standard):
totalSupply()
returns total tokens in the contract
Metadata containing each token's characteristics
Contract function:
tokenURI()
returns the URL with the metadata JSON containing the details of each token
Information stored about token ownership
How many tokens does a given user own? Contract function:
Mapping of
address -> token amount
Retrieved by calling
balanceOf(
address
)
which returns the number of tokens owned by this user
Who owns the token at a given token ID? Contract function:
Mapping of
token ID -> address
Retrieved by calling
ownerOf(
tokenID
)
that returns the address of the user who owns this token
What happens when the mint()
function is called?
Function call
mint(
address
,
tokenAmount
)
is executed, which specifies the amount of tokens to mint for a particular userWhen new tokens are minted, the
totalSupply
is decremented by the amount.If the mint function is called with an amount of tokens to mint that exceeds the remaining total supply, then it will fail.
When minting is successful, the mapping
address -> token amount
is updated.
Function call
mint(
tokenID
,
address
)
is executed, which specifies the token ID to mint for a particular user.It will then attempt to update mapping
token ID -> address
.If the token ID already exists in the mapping (which means that a token has already been minted), then minting will fail.
If not, then a new token ID is created and the mapping updated with the address of the token ID owner.
Other useful functions
transfer(
tokenAmount
,
address
)
- which transfers a specified amount of tokens from the caller's account to another user'sapprove(
address
,
tokenAmount
)
(fungible) /approve(
address
,
tokenID
)
(non-fungible) - the caller may approve another user to spend or transfer tokens on their behalf
For the full list of standard functions, see:
Fungible (ERC-20) token standard
Non-fungible (ERC-721) token standard
Example contract
Our imx-contracts repo on GitHub contains some templates for smart contracts that are compatible with XpansionChain.
Asset.sol
Asset.sol is an example of a non-fungible (ERC-721 standard) contract that contains the functions required so that tokens can be minted from it on XpansionChain.
It implements the _mintFor
function which is called when the asset is minted on L1 when it is withdrawn from XpansionChain to Ethereum (see step 4 here). This function calls _safeMint
, which is an inherited function from the ERC-721 contract that mints the NFT in a safe way.
Asset.sol
The Mintable.sol contract that Asset.sol inherits from provides the token-minting functionality:
Mintable.sol
Things to note about the examples above:
owner
is the wallet address you choose to be the minter of the contract, so it should be a very safe, secure wallet.transferOwnership(_owner)
does exactly as described, and transfers the ownership of the contract from the contract deployer to the specific wallet address.The address named
imx
refers to the XpansionChain contract address that is interacting with your smart contract to perform minting operations. You can find the address for each environment in the README of the imx-contracts repository. This address is used in theonlyIMX
modifier, which checks if the sender of the transaction is our contract or not. This is a way of whitelisting our contract and ensuring that no one else can mint assets through your smart contract.The
mintFor
function is called by the XpansionChain smart contract at the time of withdrawing the NFT to Ethereum. The function has theonlyIMX
modifier, as explained above. Because you’re minting NFTs, which are unique, ensure that quantity = 1.The blueprint is saved as on-chain, XpansionChain metadata in the mapping blueprints. For custom blueprint decoding, you can override the mintFor function in Asset.sol to save it in something like tokenURI, or split the string into different components.
The function emits an event
AssetMinted
when the mintFor completes successfully, and this can be listened on by applications.
Fungible tokens
Use cases
Staking: This process allows individuals to lock specified amounts of their tokens to earn a yield. This is not available to all cryptocurrencies, and those who offer this operate under a Proof of Stake (PoS) consensus mechanism that requires specified amounts of a token to validate transactions.
Voting: Holders of tokens are often offered voting rights by DAOs, also known as Decentralized Autonomous Organizations, who control ownership of certain token contracts. There are a variety of voting mechanisms, each outlining different requirements, however, it can generally be understood that the weight of a vote is proportional to the number of tokens owned.
User acquisition: Many projects reward their community with their native tokens. This practice is common within many Web3 organizations, whereby constructive actions within an ecosystem may grant community members ecosystem rewards such as its native token.
Game rewards: Many Web3 games are governed by a proprietary native token which they leverage to reward their users. These token rewards can then be spent to purchase items and cosmetics that help to drive the in-game economy.
Consider the IMX token: It has the potential to be staked, used for governance, trading rewards, developer incentivization, and in-game rewards as seen in its native projects such as Gods Unchained and Guild of Guardians.
Minting on XpansionChain
Currently, L2 minting of fungible tokens are not supported by XpansionChain. To transact with these tokens on L2, they must be minted first on L1 then deposited to L2 to be used.
Non-fungible tokens
Use cases
Ownership: Demonstrate authenticity and ownership of assets (artwork, fashion, licenses, certificates, collectibles).
Gaming: In game assets can be tokenised enabling players to own their assets and exchange them with others.
Recurring revenue: Capture royalties from every transaction after the initial sale. This benefits all creators including: artists, designers, musicians, developers.
Customer insight: Access to transaction data of NFT owners within apps and across platforms.
Funding source: Increase the scale of investments by enabling fans to coinvest in their favourite artists and projects. NFTs can also be leveraged to reward these users in the future.
New product lines: Create and sell merchandise which can give access to unique and personalised experiences eg tickets for events, backstage passes.
Minting on XpansionChain
You can mint NFTs on XpansionChain.
More information:
For a conceptual overview, see Deep dive into minting
Guide on how to use our API/SDKs to mint
Guide to how to use the command line to mint tokens from your own collection
Last updated