In this chapter, we're going to create a very simple smart contract that stores some information on the blockchain which we'll then retrieve.
Since it's a bit complicated to get started with Solidity on your local computer, we will use an online IDE called Remix to take our first steps as DApp programmers instead.
If you're entering the website for the first time, you'll see that there's a dummy contract called
ballot.sol there already. Let's ignore that one and instead start from scratch by creating a new file called
HelloWorld.sol in the left navigation menu.
Writing in Solidity
Now that we have a completely blank file, let's go through how Solidity works.
The first thing we need to specify is what version of Solidity our program should be interpreted in. This is done through a version pragma on the very first line:
The idea here is that we're preventing our program from being compiled by a compiler that's older than . The
^-symbol in the beginning also prevents it from being compiled by a compiler that's or higher. We do this in order to minimise the risk of bugs that can occur if the code is compiled in unexpected or incompatible ways.
Next, it's time to write the actual contract code! We do this by using the special
contract key word which declares a new contract. If you're used to object-oriented languages, you'll notice that it's similar to how classes are defined.
Contract names are usually PascalCased, so we'll call ours
HelloWorld in order to stick with this convention.
Inside our contract, we'll add a state variable that stores our name as a string. By convention, variables use camelCase, so we'll call it
Note that Solidity is statically typed, so you always need to define the type of your variable before you assign a value to it. A list of all types can be found in Solidity's documentation.
Finally, we want to be able to retrieve this value from our contract by calling a function. We'll call this function
Notice that we need to specify the return value of a function in Solidity. Since we're just returning the
myName string in this case, we write
Taming the compiler
In order to easily catch errors in our contract, we're going to add the compiler plugin to our workspace.
If you've followed along so far, you'll now see that any time you make changes to your contract file, you'll automatically see some errors from the compiler.
Every time you change something in your code, Remix will automatically try to compile it. Red fields indicate that the code failed to compile (because of syntax errors), and yellow fields indicate that it compiled with some warnings.
The first error tells us that the visibility of our function hasn't been specified (and is therefore defaulting to "public"). There are actually 4 visibility types in Ethereum:
public: anyone can call the function, including a consumer of the DApp.
private: only the contract itself can call the function (in another function).
internal: only this contract and all contracts deriving from it can call it.
external: only consumers can call the function, and no other function in the contract itself can.
In my experience,
private are by far the most used types.
Since we're currently just playing around, we don't mind setting the visibility to
public. Note that even though Solidity defaults to this, it's considered good practice to always explicitly specify the visibility of your functions, in order to avoid potentially catastrophic oversights.
We also have a second error:
The way to fix this is to simply specify that the string that we're returning is also of
memory type, e.g. that we're not interested in mutating the contract's stored
myName, we'll just return a copy of it (more on this later).
After doing this, there should only be a yellow warning left. This one is slightly harder to decrypt:
What the compiler is really saying is that it's detecting that our function never mutates any state on the blockchain – it only reads from it. Therefore, we can use the
view modifier to make that more clear:
When a function has a "view" modifier, you don't need to spend any ether to call them (even if they use operations that consume gas), since no transaction needs to be made. They are essentially "free to use".
There are 3 built-in modifiers that have an impact on the amount of ethers that are spent:
view: is free to call, since it only "views" the state of the blockchain without changing it. It was previously known as
pure: also free to call and neither reads nor writes to the blockchain. It is used for "pure" functions where one input will always return the same output.
payable: expects a certain amount of ether regardless of what the gas costs are. This is often used in token sale contracts, where the amount of money sent by the user can vary.
Running your contract
Now that the compiler is happy, we want to actually interact with our contract! In order to do that, we're going to add a new plugin:
In this new tab, you can specify some options for creating your contract, like what (fake) address to upload it from for example.
It might not seem like much, but you actually just deployed your contract to an Ethereum address (although only in a virtual environment)!
Deploying a contract also uses gas, and costs a certain amount of ether. That's why, if you check the account address in the options, your balance should have slightly gone down from 100 ether to something closer to 99. Now that the HelloWorld contract is up and running, you can click on the contract in the "Deployed contracts" section, and call its
getMyName function simply by pressing the blue button in the browser window that says "getMyName".
The grey Remix logs the call in more detail and shows something like this:
Notice that your address balance did not change when calling the function, since it's a "view" function.
Adding a writeable function
So far so good, but what we really want to do is to let anyone change the name variable to something else. For this, we're going to add a new
As you can see, this function differs from
getMyName in a few ways. It does not use the
view modifier, since it actually changes data stored on the blockchain, and it also doesn't return anything.
Arguments in Solidity functions are often prefixed with an underscore (
_) to distinguish them from global state variables like
myName. We will adopt this convention throughout the course.
Let's redeploy our contract by clicking the "Deploy" button once more.
Notice how the new "changeMyName" button is orange instead of blue, which indicates that it's a writeable function.
You should now be able to type in a new name in the input field (don't forget to add double quotes around the name), click the "changeMyName" button, and fetch it by clicking "getMyName":
Congratulations, it seems like our code works, and you've just written your first Solidity contract! Getting and setting different kinds of state variables is a key concept that we'll be using over and over again.
In the next chapter, we'll look at how we can run this code locally on our computer instead of relying on Remix in the browser.