You are about to wield the full power of the blockchain. All hail the all mighty censorship-resistent integer. Okay, the contract you will make is not going to be very useful for any real world applications, but it will be useful for the knowledge you gain from it. You may not solve all the world’s problems with this smart contract, but your journey can start with the small step you take here.
The road to learning Solidity smart contract programming
Example code
In this example, we will be walking through a contract that stores a number. The main contract is called Counter.sol
and it inherits from Ownable.sol
. You can read them below:
Solidity
Solidity is a contract-oriented programming language, which is most often used on the Ethereum blockchain. Ethereum is a blockchain that has a virtual machine where the state of the virtual machine is copied over thousands of computers. To run programs on the ethereum virtual machine, you pay for the cost of computation and storage with the ether token. It is a global shared computer that enables us to create programs that are virtually impossible to shut down or stop. It is the platform that brought us ICOs, or initial coin offerings, a tool used to fund development of new ideas. You also can build dapps, or decentralized applications, using Solidity. Dapps are like websites that interact with Ethereum smart contracts. Lets get started with Remix.
Remix - Solidity IDE
For this example, we will be using Remix. Remix is a web integrated development environment (IDE). Remix is a great tool for learning Solidity smart contract development. It is very easy to get started because you do not have to install anything. You can get coding right away.
Example Smart Contract
In this example, we will create a contract that stores a number. We will also let anyone add one to this number. We will also let the owner reset the number if they choose. We will create a powerful, unstoppable, censorship-resistant number. We will create two contracts: Ownable
and Counter
. Counter
will inherit from Ownable
. In other words, Counter
is Ownable
, which means Counter
gains access to the data and functions of Ownable
.
Importing into Remix
- To begin, open this link and the code for this example will be automatically imported.
- In Remix, click gist on left to show the contracts in this example
- In Remix, click
Counter.sol
andOwnable.sol
to open and read them.
Read through the code and get a feel for it. Ownable.sol
and Counter.sol
are used together to create an integer counter
that can only be reset by the creator of the contract.
Playing with the code
- In compile tab, click compile. You need to open the files first before Remix will compile them. Once they are compiled, Remix will look like this:
- In the run tab, change your settings to look like this:
- Click the deploy button to deploy the Counter contract. You should see this:
This creates the contract and calls the constructor. At the bottom you can interact with your deployed contract and call functions defined earlier. Try pressing buttons and see what they do. You can also change which address you are sending from by selecting a different account near the top:
Try seeing what happens if you try to call Reset
from a different address.
Walking through code: Ownable
pragma solidity^0.4.24;
Every programming language is continually evolving. Sometimes changes to the design of a language can make it incompatible with previous syntax. Therefore, Solidity and other programming languages like it use a pragma
statement to let the compiler know which version of the programming language this code is expected to run with. This statement means that the code not compile with a solidity compiler version below 0.4.24. The carrot ^
means it also will not compile with a version starting with 0.5.0 and above.
contract Ownable {
Contracts in solidity store data and allow functions to be defined that return or modify the data it stores. In this example, we define a contract named Ownable
.
/* Define owner of the type address */
address owner;
We create a variable named owner of type address
to keep track of the contract owner. An address
in Ethereum is a 20-byte value. Every ether token is associated with an address
. When you send ether to someone else, you send it to their address
. Your ether tokens in the Ethereum network are attributed to a public address
, generated from a private key. Your private key allows you to sign messages that the network can verify. Others cannot spend your ether without your private key.
modifier onlyOwner {
require (msg.sender == owner);
_;
}
Modifiers in Solidity partially define functions. This modifier is named onlyOwner
, and any other function can add onlyOwner
to the end of it to add the above code to the function. require
is a built-in function in solidity that is used to check for conditions and throw an exception if it is not met. msg.sender
is the address
of the person who created the transaction that called this function. Every time any code is ran in solidity, it is ran by a transaction with a sender.
/* This function is executed at initialization and sets the owner of the contract */
constructor() public {
owner = msg.sender;
}
When a contract is created, the constructor
is called exactly one time and never called again. Ownable
’s constructor
sets the owner
variable to msg.sender
. The variable msg.sender
is the address of the transaction calling this code. Since the constructor
is only called once upon creation, msg.sender
is the address of the creator of this contract in this context.
Walking through code: Counter
import "./Ownable.sol";
import
statements copy the code from the contract it is importing so that this contract can use it when compiled. The Counter
contract import
s Ownable
because we want to make this Counter
contract Ownable
.
contract Counter is Ownable {
Solidity supports inheritance, which defines an “is a” relationship between the contracts. In this case, Counter
is
Ownable
. Counter
gains access to all data and functions defined in Ownable
. It makes it easier to define other contracts where you only want the owner to be able to take action.
int counter;
This is where we store the unstoppable, uncensorable all-powerful counter
. What you choose to do when you wield this power is your choice. counter
is an int
, or integer, a number that is stored by the contract.
constructor() public {
counter = 0;
}
As explained earlier, the constructor
is called exactly one time when the contract is first created. In this case, it sets counter
to 0. Since this contract inherits from Ownable
, it also means the Ownable
constructor
is called.
// From Ownable.sol:
modifier onlyOwner {
require (msg.sender == owner);
_;
}
// From Counter.sol:
function reset() public onlyOwner {
counter = 0;
}
The reset
function shows an example of using a modifier to change the behavior of a function. In this example, the reset
function is modified by the onlyOwner
modifier. In the modifier, the _;
is where the rest of the function is called. If someone tries to call the reset
function and they are not the owner, it will fail. If they are owner
, it will set counter
to zero again.
function add() public {
counter += 1;
}
Functions can be defined that modify data stored in the contract. In this example, add()
will add 1 to the counter stored in the contract.
function getCounter() public view returns (int) {
return counter;
}
Adding the view
keyword to a function means that the function will not cost any gas to execute because it does not modify any data. It does not require every other computer on the Ethereum network to do anything. You can read the data locally. returns (int)
means this function will return an integer when you call it. In this case, we return counter.
Going “live” on Rinkeby test net
You can deploy this contract on the Rinkeby Ethereum test net. Rinkeby is the name of one of Ethereum’s test networks. It is designed as a testing ground for creating smart contracts. It allows you to code for Ethereum without having to spend real money while you develop. Here is how you can get started:
- Install metamask https://metamask.io/
- At the top of Metamask, switch your network to the Rinkeby test net:
- Create an address and copy it
- Create public post with your address, for example:
- Go to the Rinkeby faucet, paste the link to post with your address
- In the run tab of Remix, change Environment to “Injected web3”
- Click deploy again:
- Metamask should ask you to confirm. If it fails, try increasing your gas limit.
- Once it is published, Remix will give a link where you can see the transaction published:
It usually is accepted by the network within about a minute. Deploying to live works pretty much exactly the same, except it costs you main net ether instead of free test ether.
Next steps
It is up to you now to use your wit and creativity to create an awesome smart contract. What will you do with the unstoppable integer? You can learn more about ERC20, which is the most popular standard for creating tokens on Ethereum. You can also find a local meetup in your area and ask for help there. Hope you have fun on your blockchain adventures.
See also
- Creating a Virtual Time Capsule in Solidity, shows you how the payable modifier works in Solidity, the Ethereum smart contract programming language.
- Getting Started with Solidity - If you would like to learn how to get started with Solidity
Other resources
- Truffle Suite - Sweet tools for developing Ethereum dapps