Smart Contracts are pieces of codes that automatically execute blockchain transactions based on a set of inputs given. These are basically used to automate activities such as crypto swaps, NFT minting, token sale, liquidity pools, escrow funds, etc.
Smart Contracts feature decentralized execution of tasks on a blockchain without the need of a central party as a guarantor.
#NOTE: All interactions with a smart contract are in the form of transactions and require necessary gas fees.
Table of Contents
Definition, Working and Example
A smart contract is basically a program that facilitates the execution of transactions on a blockchain. Once programmed smart contracts basically become tamper-proof and fully automated.
Smart contracts can be used to automate tasks such as Decentralized Exchanges, Auctions, Crypto Swaps, NFT trading, etc.
Working of a Smart Contract in Simple Terms
A smart contract works in a very simple way:
- The creator of a smart contract creates a logic. It can be based on agreement between parties(such as Escrow) or in case of a solo creator, their needs and wishes(such as a Legal Will).
- The smart contract is programmed based on the requirements.
- Triggering conditions are set. These conditions can either be based on time or on specific actions.
- In case of external conditions triggering smart contracts, a blockchain oracle is required to feed data to it.
- The smart contract is executed based on its conditions.
- The resulting transaction, for example, transfer of funds, is recorded on the blockchain.
Example
Let me use the example of an auction to show how a smart contract works.
Suppose there is an auction where people are bidding for an iconic piece of art. Now this art can be an NFT or a real world painting. To ensure that the auction goes free and fair, the auctioneers have used a smart contract.
They have programmed it in a certain way that whoever is the highest bidder at 09:00 AM on February 7th, will automatically be the winner of the auction,
In real life, there could emerge a problem in such situations. If several people are betting on the same thing just before it ends, it would be impossible to accurately judge who did the last and the highest bid.
Even if you use a digital bidding system, the trust on them would be zero. I observed this when there was an allegation on Rarible for insider trading.
In such situations, blockchain-based bidding makes absolute sense since it can be verified and its history is immutable.
Working of a Smart Contract in Technical Terms
A smart contract uses various functions and logic to execute its actions. These functions and logic trigger actions such as transfer or funds, NFTs, Asset Tokens or other actions.
The transfers take place via public addresses on the blockchain. There are 4 types of addresses which are required to execute such transfer-based smart contracts.
- Public address of the creator (Master Address).
- Public address of the Smart Contract.
- Public address of the beneficiary.
- Public address of other parties (for example in smart contracts for auctions or governance).
After that, the smart contract is coded and works in this way.
- The logic is coded based on the agreement between parties or the will of the creator.
- The structures(user defined data types) are created for entities which are present in the smart contract. In the below example they are: Voter and Proposal. The item for which the smart contract is created is also an entity. Example of such entities are NFTs in Auctions.
- Then the functions are defined along with their logic. A function is the piece of code which defines the working of a smart contract if its conditions are met.
- A failsafe function is also created which gets executed when no other function is executed. Such as return funds to XYZ address if an auction fails.
Example of a Solidity Smart Contract Code for Governance
Below is a sample smart contract code of a voting system built using the Solidity programming language. Source: Remix IDE.
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Ballot
* @dev Implements voting process along with vote delegation
*/
contract Ballot {
struct Voter {
uint weight; // weight is accumulated by delegation
bool voted; // if true, that person already voted
address delegate; // person delegated to
uint vote; // index of the voted proposal
}
struct Proposal {
// If you can limit the length to a certain number of bytes,
// always use one of bytes1 to bytes32 because they are much cheaper
bytes32 name; // short name (up to 32 bytes)
uint voteCount; // number of accumulated votes
}
address public chairperson;
mapping(address => Voter) public voters;
Proposal[] public proposals;
/**
* @dev Create a new ballot to choose one of ‘proposalNames’.
* @param proposalNames names of proposals
*/
constructor(bytes32[] memory proposalNames) {
chairperson = msg.sender;
voters[chairperson].weight = 1;
for (uint i = 0; i < proposalNames.length; i++) {
// ‘Proposal({…})’ creates a temporary
// Proposal object and ‘proposals.push(…)’
// appends it to the end of ‘proposals’.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
/**
* @dev Give ‘voter’ the right to vote on this ballot. May only be called by ‘chairperson’.
* @param voter address of voter
*/
function giveRightToVote(address voter) public {
require(
msg.sender == chairperson,
“Only chairperson can give right to vote.”
);
require(
!voters[voter].voted,
“The voter already voted.”
);
require(voters[voter].weight == 0);
voters[voter].weight = 1;
}
/**
* @dev Delegate your vote to the voter ‘to’.
* @param to address to which vote is delegated
*/
function delegate(address to) public {
Voter storage sender = voters[msg.sender];
require(!sender.voted, “You already voted.”);
require(to != msg.sender, “Self-delegation is disallowed.”);
while (voters[to].delegate != address(0)) {
to = voters[to].delegate;
// We found a loop in the delegation, not allowed.
require(to != msg.sender, “Found loop in delegation.”);
}
sender.voted = true;
sender.delegate = to;
Voter storage delegate_ = voters[to];
if (delegate_.voted) {
// If the delegate already voted,
// directly add to the number of votes
proposals[delegate_.vote].voteCount += sender.weight;
} else {
// If the delegate did not vote yet,
// add to her weight.
delegate_.weight += sender.weight;
}
}
/**
* @dev Give your vote (including votes delegated to you) to proposal ‘proposals[proposal].name’.
* @param proposal index of proposal in the proposals array
*/
function vote(uint proposal) public {
Voter storage sender = voters[msg.sender];
require(sender.weight != 0, “Has no right to vote”);
require(!sender.voted, “Already voted.”);
sender.voted = true;
sender.vote = proposal;
// If ‘proposal’ is out of the range of the array,
// this will throw automatically and revert all
// changes.
proposals[proposal].voteCount += sender.weight;
}
/**
* @dev Computes the winning proposal taking all previous votes into account.
* @return winningProposal_ index of winning proposal in the proposals array
*/
function winningProposal() public view
returns (uint winningProposal_)
{
uint winningVoteCount = 0;
for (uint p = 0; p < proposals.length; p++) {
if (proposals[p].voteCount > winningVoteCount) {
winningVoteCount = proposals[p].voteCount;
winningProposal_ = p;
}
}
}
/**
* @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then
* @return winnerName_ the name of the winner
*/
function winnerName() public view
returns (bytes32 winnerName_)
{
winnerName_ = proposals[winningProposal()].name;
}
}
Benefits of Using Smart Contracts
- Smart Contracts are fast in execution and barely take a few seconds or a few minutes to execute.
- They are free of any bias. No third party involvement eliminates the question of bias.
- They are transparent as blockchain transactions are open for verification by anyone.
- Encryption of data provides a high degree of security.
- Smart contracts save money as the fees for a third party is not required.
Disadvantage – Non-Editable
In my experience, the greatest disadvantage of using a smart contract comes when there is a need to change them. Even for the smallest changes, I have seen developers deleting and re-deploying an new smart contract.
I am well aware that these feature contributes to their security but deploying a new smart contract every time changes its address and tokens sent to the old address are simply lost.
Applications and Use
Smart contracts are used extensively these days in Decentralized Exchanges, DApps, Swap Protocols, Liquidity Protocols, Blockchain Bridges, Escrow Accounts, etc.
Decentralized Exchanges
Perhaps the most widely used application of a smart contract is its usage in the decentralized exchanges. Since, these exchanges are automated they need some tool to facilitate the automated exchange of cryptocurrencies. This role is fulfilled by smart contracts.
With some DEXes, you might also get an option to do cross chain transfers.
Swap and Liquidity Protocols
These protocols rely on smart contracts to provide swap features and generate LP tokens.
Smart contracts facilitate the swapping of assets on the same blockchain (such as between USDT and WBTC on Ethereum).
They also help generate Liquidity Provider Tokens(LP Tokens)
LP tokens are those cryptocurrencies which you get once you deposit some liquidity(popular cryptocurrencies) to a liquidity pool. These LP tokens are required to claim back your original crypto along with its rewards.
Blockchain Bridges
Blockchain Bridges use two sets of smart contracts to transfer assets between different blockchains. One smart contract locks the assets on one chain and another smart contract mints them on another blockchain. While redeeming the tokens, the same method is followed.