Smart Contracts
Simplified examples of common contracts
Last Updated: 30th June 2023
This page covers some common smart contract use cases. The goal is for you to get a good understanding of how these common smart contracts work. For example, what storage is used and how, how the entrypoints are used and how contracts interact with each other. This will bring you up to speed on a lot of the smart contracts you will run into on a daily basis, helping you understand the broader smart contract development landscape.
The contracts on this page are simplified contracts, provided for educational purposes only. They are not meant to be implemented and used as is, as some of them may contain potential flaws.
Prerequisites
If you haven't already, please go ahead and read Smart Contract Concepts. It also might be worth having a read through the Smart Contract Languages section to get an understanding of the options available to you - this way you can start thinking about how the implementations below might look in another of the supported smart contract languages on Tezos.
Common Contracts
- FA1.2 Fungible token
- FA2 - NFTs: Non Fungible Tokens
- NFT Marketplace
- Escrow
- DAO: Decentralized Autonomous Organisation
- DeFi: Flash loan
FA1.2 Fungible token
The goal of this contract is to create and manage a single fungible token. It implements the FA1.2 standard, which makes it compatible with wallets, decentralized exchanges and other tools.
Features
- Each user can own a certain number of tokens
- Users can transfer tokens to other users
- Users can allow another contract, for example a decentralized exchange, to transfer some amount of their tokens for them.
Entrypoints
The contract contains two main entrypoints:
transfer
- to transfer a number of token from one address to anotherapprove
- to allow another address, on behalf of the caller, to transfer a number of their tokens
To be compatible with FA1.2, and so that other contacts can access to information, it also contains three entrypoints that have no effect other than reading storage:
getBalance
- returns the current token balance.getAllowance
- returns the current token allowance amount for an approved address (viaapprove
)getTotalSupply
- returns the total number of tokens managed by this contract
FA 1.2 | |
---|---|
Storage | Entrypoint Effects |
|
|
FA2 - NFTs: Non Fungible Tokens
The FA2 standard specifies contracts that can describe:
- Single fungible token
- Multiple fungible tokens
- Non-fungible tokens (NFTs)
Implementing the FA2 standard allows the contract to be compatible with wallets, explorers, marketplaces, etc. Here, we will present an implementation for NFTs. The entrypoints for the other types are the same, but the implementation differs.
Entrypoints
FA2 contracts must have the following entrypoints:
transfer
- can be called either by the owner of tokens, or by a third party allowed to do so on their behalf. It accepts a list of transfers of different tokens from the token owner with recipient addresses.update_operator
- can be called by the owner of tokens to add or remove operators allowed to perform transfers for them. It takes a list of variants, each consisting in either adding or removing an operator for a given token.balance_of
- used to access the balance of a user for a given token.
FA 2 | |
---|---|
Storage | Entrypoint Effects |
|
|
NFT Marketplace
The goal of this example contract is to manage sales of NFTs. It pays a share of the selling price to the admin of the marketplace, in exchange for providing an application that facilitates finding and purchasing NFTs.
Entrypoints
add
- called by a seller who lists an NFT for sale for a given price. The seller must indicate which FA2 contract holds the NFT, and the ID of the NFT within that contract. This requires the marketplace to haveoperator
status within the FA2 contract.remove
- called by a seller to remove their NFT from the marketplace.buy
- called by a buyer who pays the required price to buy a given NFT. The admin account of the marketplace receives a share of the selling price.
NFT Marketplace | |
---|---|
Storage | Entrypoint Effects |
|
|
Escrow
An escrow smart contract temporarily holds funds and only unlocks them based on certain conditions, time, or an agreement from both sides. For example, tokens paid by a buyer can be locked in a smart contract, until they confirmed they received what they paid for.
An escrow provides some trust between parties of a transaction:
- when the buyer does not want to send the payment until the request has been fulfilled.
- when the seller does not want to provide the product/service without some guarantee that they will be paid.
There are a number of different types of escrow contracts. In our contract, the service to provided by the seller is data which can be verified to be valid by the escrow smart contract. For example, the request could consist in the service sending the decrypted version of some encrypted data.
Entrypoints
Our contract has three entrypoints:
send_request
- creates a new request with a deadline and also sends the payment to the escrow contract. The request contains the code that will verify the validity of the answer.fulfill_request
- called by the seller. It verifies that the request has been performed and transfers the funds to the seller.cancel_request
- called by the buyer if the request has not been fulfilled after deadline expiration. The funds are transferred back to them.
Escrow | |
---|---|
Storage | Entrypoint Effects |
|
|
DAO: Decentralized Autonomous Organisation
A DAO is a smart contract that represents an organisation with members. It provides a way for these members to collectively take decisions. A common DAO decision is how to use tokens held in the DAO's treasury i.e. tokens held in the balance of the DAO contract.
DAO contracts can be very flexible and wide-ranging, but here we will present a simple but powerful version. Our DAO stores the addresses of all its members, a list of all the current proposals, and keeps track of who voted for them.
Entrypoints
propose
- called by any member to make a new proposal, in the form of a piece of code to execute (a lambda).vote
- called by any member to vote in favour of the request. When the majority of members have voted in favour, the proposal is executed.add_member
- adds a new member to the DAO. It can only be called by the DAO itself, which means the call has to go through a proposal and be voted on.remove_member
- removes a member from the DAO. It can only be called by the DAO itself.
When deployed, an initial list of members needs to be provided, as well as some initial tez balance.
DAO | |
---|---|
Storage | Entrypoint Effects |
|
|
DeFi: Flash Loan
A flash loan is one of the many tools of decentralized finance (deFi). In essence, it provides a way for a user to temporarily get access to large amounts of tez, without any collateral. This allows them to take advantage of opportunities and make a profit, without the need to have their own funds.
Principle
The idea is that the following steps can will be done in an atomic way (all within the same transaction):
- the borrower receives the requested flash loan amount from the contract
- the borrower uses the amount in a series of calls to other contracts, that allow them to make some instant profit
- the borrower then pays the requested amount plus some interest to the contract pocketing any profit made
The key aspect to understand is that all this is done atomically, which means that if any of these step fails, and if for example the borrower is not able to pay back the borrowed amount plus interest, then the whole sequence is canceled, as if it never happened. There is no risk at all for the lender contract.This contract can even lend the same tez to multiple different people within the same block, as each loan is paid back immediately, so the tokens can be used again for another loan.
One simple example of a flash loan is arbitrage; if two different exchanges offer to buy/sell the same token but at a different price, the user can buy tokens from one exchange at the lower price, then sell it to the other exchange at a higher price, making a profit.
Entrypoints
borrow
- called by the borrower, indicating how many tez they need. The amount is transferred to the caller, then a callback they provided is executed. At the end of this entrypoint, we verify that this callback has repaid the loan.repay
- called by the callback once it times to repay the loan. The call should come with payment of the borrowed amount, plus some interest.check_repaid
- called by theborrow
entrypoint after the call to the callback.borrow
can't do the verification itself, since the execution of the callback is done after all the code of the entrypoint is executed.
Flash Loan | |
---|---|
Storage | Entrypoint Effects |
|
|