solc
Before we can start work on our contract we first need to setup the compiler, solc
.
There are several methods for installing solc
that can be found here
https://solidity.readthedocs.io/en/latest/installing-solidity.html,
my personal favourite for keeping my environment clean is to use the official docker
image. To do this I create the following alias:
This mounts your local directory into the containers working directory and so the
solc
can be used as normal. For example:
This will compile the bin and abi files for your contract (defined in contract.sol
)
and saves them to the target
directory.
Now we have setup the solidity compiler we can create our first contract.
As our first example lets create a simple escrow contract where a trusted third party (the arbitrator) can validate sending an amount of ETH from a sender to a receiver taking a small fee. The arbitrator will control the creation, cancellation and transferal of funds and the sender is responsible for adding funds to the contract.
To create the escrow contract we will need to create a contract that knows the sender, the receiver and the arbitrator as well as the amount to send and the arbitrators cut:
There are a few important features to point out, the first line tells the compiler which
version of the solidity spec to use. Next we have the contract definition starting with
the variable definitions. addresses
are used to records the addresses for the
transaction and uints
are used to store values. Next we construct the contract taking
parameters for the sender, receiver and value. We take the arbitrator from the address
creating the contract (msg.sender
).
While this is enough to create a contract it's a little dull. Currently the contract has no funds or methods for adding funds. Let's fix that:
The function adding the funds is deposit
even though it's content is empty. There are
2 important modifiers specified, the first is onlySender
defined above, this ensures
that only the sender can add funds to the contract, if the address adding the funds does
not match the sender then the function will exit without adding the funds. The second is
the built-in modifier payable
which takes a transaction and adds the funds to the
contract.
Now we need to add methods for the arbitrator to interact with:
Here we have added 2 functions and 2 new modifiers. The first modifier
(onlyArbitrator
) acts in a very similar way to onlySender
but checks the
transaction sender is the arbitrator not the sender. The second modifier (walletIsFull
)
checks that the contract has enough funds to cover the transaction and arbitrator fees.
The first function cancel
can only be performed by the arbitrator and calls the
built-in function selfdestruct
. This destroys the contract on the blockchain and
returns any remaining funds to the address in the first argument (in this case the sender).
The second function send
ensures everyone gets their share. Firstly it can only be fired
by the arbitrator and secondly it can only be performed if the wallet has enough funds to
cover everybody's share. If these conditions are met it will send the correct amount to the
receiver, the arbitrators cut to the arbitrator and finally destroys the contract sending any
excess back to the sender.
To interact with the network we will be using geth
, a post on setting up geth and a
temporary test network here
https://wildfish.com/blog/2019/06/19/creating-an-ethereum-testing-network/.
To load the contract in geth
we must first build it and wrap the result in javascript.
To build the contract (assuming it is saved in escrow.sol
) run:
This will create a new directory, target
containing Escrow.abi
and Escrow.bin
,
to make this content available to geth
we need to wrap it in a javascript function to
create a contract, this will look something like this (saved to escrow.js
):
Assuming we have multiple accounts setup on your network we can then create our first
contract from a geth
interactive console we call:
escrow
is an instance of our contract that we can interact with. If we want to load
this instance again we must record the contracts address and use:
Once we have an instance of the contract we can then interact with it using the functions we defined in the solidity file, to add funds:
Now we have enough funds in the escrow the arbitrator is free to transfer the funds:
Now the value has been sent to the receiver, the arbitrators cut has been paid to the arbitrator and the excess has been paid back to the sender.