How to Write a Smart Contract in Solidity
A beginner’s guide to writing smart contracts in Solidity
What is a Smart Contract?
A smart contract contains business logic and a state. It’s written in a high-level language like Solidity, gets compiled into Ethereum Virtual Machine (EVM) bytecode, and deployed to an EVM-compatible Blockchain like Ethereum, Polygon, Binance Smart Chain, Cardano, Tron, and more.
A contract in the sense of Solidity is a collection of code (its functions) and data (its state) that resides at a specific address on the EVM compatible blockchain.
By calling smart contract functions that modify the state, a transaction is generated, and transactions are traceable, transparent, and irreversible.
A smart contract is a computerized transaction protocol that executes the terms of a contract.
The general objectives of smart contract design are to satisfy common contractual conditions (such as payment terms, liens, confidentiality, and even enforcement), minimize exceptions both malicious and accidental, and minimize the need for trusted intermediaries.
Related economic goals include lowering fraud loss, arbitration and enforcement costs, and other transaction costs — Nick Szabo
What does a Smart Contract (Solidity) look like?
The first line tells you under which license the contract is published and therefore in which conditions you are allowed to use the code. You can find a list of licenses here.
In the second line, you find the supported compiler version.
State variables, all variables that are defined outside of functions are state variables. In the contract above only _proposalVotes is a state variable.
Afterward, an enum is declared that holds a list of named constants, each constant gets an integer value starting with 0. For example Against = 0, For = 1 and Abstain = 2.
Struct is a composite data type that consists of multiple variables, related variables can be grouped together like a User or here a Vote.
Mappings are a key-value store and return a default value for non-existing entries. A more simple mapping:
mapping(address => uint256) public userBalances;
If you try to enter an address that’s not been added yet you will receive 0 the default initialization for uint.
Functions encapsulate the logic for contracts. They have access to state and inline-defined memory variables. Can be altered by modifiers. Have visibility and can have an access level defined. Can raise Events and can hold control statements. And they can return values to the caller.
The function in the example proposalVotes has the access level view, which means it doesn’t change the state and therefore doesn’t generate a transaction that’s been recorded on the blockchain.
If a function has the access level view it cannot perform the following actions:
- writing into state variables
- receive a payment
- rasing events
- creating a new contract
- calling another function that’s not marked with access level view or pure
What is Gas?
Whenever a contract is deployed or a transaction will be recorded on the blockchain, fees are charged in the form of Gas.
The amount of Gas depends on the computational resources that the EVM spends while executing the transaction or deploying the contract.
At the moment Ethereum Gas Fees are quite high, while other Blockchains like Polygon and Binance Smart Chain have much lower Gas Fees.
You can check the actual Gas Fees in the list below, I add the normal Gas Fee at the time of writing for a quick impression, these Fees and execution times are on average:
- Ethereum (Normal $0,50 and execution time 1 Minute)
- Polygon (Normal $0.0006948991 and execution time 5 Seconds)
- Binance Smart Chain (Normal $0.0323 and execution time 5 Seconds)
Ethereum is more expensive and slower compared to other Blockchains at the moment, but also in comparison the most secure Network.
You can dive deeper into the basics of smart contracts here.