Skip to content

Contract Tutorial

Christopher Moore edited this page Jan 22, 2019 · 9 revisions

Introduction

Glyff features smart contracts : autonomous programs that live on the blockchain and execute commands exactly how they were told to. They can read other contracts, make decisions, send glyff and execute other contracts. A smart contract will exist and run as long as the whole network exists, its code and data will be permanently public and it will only stop if run out of gas or if programmed to self destruct.

Programmable privacy

Because of their nature, smart contracts cannot handle confidential data. Glyff aims to change this status-quo by providing affordable and scalable privacy technology, however, we are still in early stages of development and this feature will be present only in future releases.

Your first citizen: the greeter

The Greeter is an intelligent digital entity that lives on the blockchain and is able to have conversations with anyone who interacts with it, based on its input. It might not be a talker, but it’s a great listener. Here is its code:

contract mortal {
    /* Define variable owner of the type address*/
    address owner;

    /* this function is executed at initialization and sets the owner of the contract */
    function mortal() { owner = msg.sender; }

    /* Function to recover the funds on the contract */
    function kill() { if (msg.sender == owner) suicide(owner); }
}

contract greeter is mortal {
    /* define variable greeting of the type string */
    string greeting;
    
    /* this runs when the contract is executed */
    function greeter(string _greeting) public {
        greeting = _greeting;
    }

    /* main function */
    function greet() constant returns (string) {
        return greeting;
    }
}

You'll notice that there are two different contracts in this code: "mortal" and "greeter". This is because Solidity (the high level contract language we are using) has inheritance, meaning that one contract can inherit characteristics of another. This is very useful to simplify coding as common traits of contracts don't need to be rewritten every time, and all contracts can be written in smaller, more readable chunks. So by just declaring that greeter is mortal you inherited all characteristics from the "mortal" contract and kept the greeter code simple and easy to read.

The inherited characteristic "mortal" simply means that the greeter contract can be killed by its owner, to clean up the blockchain and recover funds locked into it when the contract is no longer needed. Contracts in ethereum are, by default, immortal and have no owner, meaning that once deployed the author has no special privileges anymore. Consider this before deploying.

Installing a compiler

Before you are able to Deploy it though, you'll need two things: the compiled code, and the Application Binary Interface, which is a sort of reference template that defines how to interact with the contract.

The first you can get by using a compiler. You should have a solidity compiler built in on your geth console. To test it, use this command:

eth.getCompilers()

If you have it installed, it should output something like this:

['Solidity' ]

If instead the command returns an error, then you need to install it.

Using an online compiler

If you don't have solC installed, we have a online solidity compiler available. But be aware that if the compiler is compromised, your contract is not safe. For this reason, if you want to use the online compiler we encourage you to host your own.

Install SolC on Ubuntu

Press control+c to exit the console (or type exit) and go back to the command line. Open the terminal and execute these commands:

sudo add-apt-repository ppa:ethereum/ethereum
sudo apt-get update
sudo apt-get install solc
which solc

Take note of the path given by the last line, you'll need it soon.

Linking your compiler in Glyff

Now go back to the console and type this command to install solC, replacing path/to/solc to the path that you got on the last command you did:

admin.setSolc("path/to/solc")

Now type again:

eth.getCompilers()

You should now have solC installed, if you don't, ask for help on our Gitter channel.

Compiling your contract

If you have the compiler installed, you need now reformat your contract by removing line-breaks so it fits into a string variable (there are some online tools that will do this):

var greeterSource = 'contract mortal { address owner; function mortal() { owner = msg.sender; } function kill() { if (msg.sender == owner) suicide(owner); } } contract greeter is mortal { string greeting; function greeter(string _greeting) public { greeting = _greeting; } function greet() constant returns (string) { return greeting; } }'

var greeterCompiled = web3.eth.compile.solidity(greeterSource)

You have now compiled your code. Now you need to get it ready for deployment, this includes setting some variables up, like what is your greeting. Edit the first line below to something more interesting than 'Hello World!" and execute these commands:

var _greeting = "Hello World!"
var greeterContract = web3.eth.contract(greeterCompiled.greeter.info.abiDefinition);

var greeter = greeterContract.new(_greeting,{from:web3.eth.accounts[0], data: greeterCompiled.greeter.code, gas: 1000000}, function(e, contract){
  if(!e) {

    if(!contract.address) {
      console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");

    } else {
      console.log("Contract mined! Address: " + contract.address);
      console.log(contract);
    }

  }
})

Using the online compiler

If you don't have solC installed, you can simply use the online compiler. Copy the source code above to the online solidity compiler and you will obtain the ABI and compiled bytecode of the contract. Copy the bytecode on the box labeled Glyff deploy to a text file. Now change the first line to your greeting:

var _greeting = "Hello World!"

Now you can paste the resulting text on your glyff window. Wait up to thirty seconds and you'll see a message like this:

Contract mined! address: 0xdaa24d02bad7e9d6a80106db164bad9399a0423e 

You will probably be asked for the password you picked in the beginning, because you need to pay for the gas costs to deploying your contract. This contract is estimated to need 172 thousand gas to deploy (according to the online solidity compiler.

Notice that the cost is not paid to the Glyff developers, instead it goes to the Miners, people who are running computers who keep the network running. Gas price is set by the market of the current supply and demand of computation. If the gas prices are too high, you can be a miner and lower your asking price.

After less than a minute, you should have a log with the contract address, this means you've successfully deployed your contract. You can verify the deployed code (compiled) by using this command:

eth.getCode(greeter.address)

If it returns anything other than "0x" then congratulations! Your little Greeter is live! If the contract is created again (by performing another eth.sendTransaction), it will be published to a new address.

Run the Greeter

In order to call your bot, just type the following command in your terminal:

greeter.greet();

Since this call changes nothing on the blockchain, it returns instantly and without any gas cost. You should see it return your greeting:

'Hello World!'

Getting other people to interact with your code

In order to other people to run your contract they need two things: the address where the contract is located and the ABI (Application Binary Interface) which is a sort of user manual, describing the name of its functions and how to call them. In order to get each of them run these commands:

greeterCompiled.greeter.info.abiDefinition;
greeter.address;

Then you can instantiate a javascript object which can be used to call the contract on any machine connected to the network. Replace 'ABI' and 'address' to create a contract object in javascript:

var greeter = eth.contract(ABI).at(Address);

This particular example can be instantiated by anyone by simply calling:

var greeter2 = eth.contract([{constant:false,inputs:[],name:'kill',outputs:[],type:'function'},{constant:true,inputs:[],name:'greet',outputs:[{name:'',type:'string'}],type:'function'},{inputs:[{name:'_greeting',type:'string'}],type:'constructor'}]).at('greeterAddress');

Replace greeterAddress with your contract's address.

Tip: if the solidity compiler isn't properly installed in your machine, you can get the ABI from the online compiler. To do so, use the code below carefully replacing greeterCompiled.greeter.info.abiDefinition with the abi from your compiler.

Cleaning up after yourself:

There are situations when contracts become obsolete or simply cease to be used. Please terminate them to help with blockchain scaling. The suicide is subsidized by the network so it will cost much less than a usual transaction.

greeter.kill.sendTransaction({from:eth.accounts[0]})

You can verify that the deed is done simply seeing if this returns 0:

eth.getCode(greeter.contractAddress)

Notice that every contract has to implement its own kill clause. In this particular case only the account that created the contract can kill it.

If you don't add any kill clause it could potentially live forever.

Tokens

Tokens are a type of smart contract which provides functionality of a tradable digital assets, or much more, depending on how you use them. Its value depends on what it used for : a token can be used for access control (an entrance ticket), to represent voting rights in an organization (a share),or be simply used as an exchange of value within a community (a currency).

Glyff token provides the benefits of decentralization :

  • Tokens ca be exchanged as long as the network functions properly. (no single point of failure)
  • Code guarantees that no tokens will ever be created other than declared in code.
  • Users have control of their funds (no risk of massive funds losses due to server hack or failures).

Standard token

This is the code for the contract we're building:

contract token { 
    mapping (address => uint) public tokenBalanceOf;
    event TokenTransfer(address sender, address receiver, uint amount);
  
  /* Initializes contract with initial supply tokens to the creator of the contract */
  function token(uint supply) {
        tokenBalanceOf[msg.sender] = supply;
    }
  
  /* Very simple trade function */
    function sendToken(address receiver, uint amount) returns(bool sufficient) {
        if (tokenBalanceOf[msg.sender] < amount) return false;
        tokenBalanceOf[msg.sender] -= amount;
        tokenBalanceOf[receiver] += amount;
        TokenTransfer(msg.sender, receiver, amount);
        return true;
    }
}

If you have ever programmed, you won't find it hard to understand what it does: it is a contract that generates 10 thousand tokens to the creator of the contract, and then allows anyone with enough balance to send it to others. These tokens are the minimum tradeable unit and cannot be subdivided, but for the final users could be presented as a 100 units subdivide-able by 100 sub-units, so owning a single token would represent having 0.01% of the total. If your application needs more fine grained atomic divisibility, then just increase the initial issuance amount.

In this example we declared the variable "tokenBalanceOf" to be public, this will automatically create a function that checks any account's balance.

Compile and Deploy

So let's run it!

var tokenSource = ' contract token { mapping (address => uint) public tokenBalanceOf; event TokenTransfer(address sender, address receiver, uint amount); /* Initializes contract with initial supply tokens to the creator of the contract */ function token(uint supply) { tokenBalanceOf[msg.sender] = supply; } /* Very simple trade function */ function sendToken(address receiver, uint amount) returns(bool sufficient) { if (tokenBalanceOf[msg.sender] < amount) return false; tokenBalanceOf[msg.sender] -= amount; tokenBalanceOf[receiver] += amount; TokenTransfer(msg.sender, receiver, amount); return true; } }'

var tokenCompiled = eth.compile.solidity(tokenSource)

Now let’s set up the contract, just like we did in the previous section. Change the "initial Supply" to the amount of non divisible tokens you want to create. If you want to have divisible units, you should do that on the user frontend but keep them represented in the minimun unit of account.

var supply = 10000;
var tokenContract = web3.eth.contract(tokenCompiled.token.info.abiDefinition);
var token = tokenContract.new(
  supply,
  {
    from:web3.eth.accounts[0], 
    data:tokenCompiled.token.code, 
    gas: 1000000
  }, function(e, contract){
    if(!e) {

      if(!contract.address) {
        console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");

      } else {
        console.log("Contract mined! Address: " + contract.address);
        console.log(contract);
      }

    }
})

Paste the text on your glyff console. Wait up to thirty seconds and you'll see a message like this:

Contract mined! address: 0xdaa24d02bad7e9d6a80106db164bad9399a0423e 

Check balance watching coin transfers

If everything worked correctly, you should be able to check your own balance with:

token.tokenBalanceOf(eth.accounts[0]) + " tokens"

It should have all the 10 000 tokens that were created once the contract was published. Since there is not any other defined way for new tokens to be issued, these are all that will ever exist.

You can set up a Watcher to react whenever anyone sends a token using your contract. Here's how you do it:

var event = token.TokenTransfer({}, '', function(error, result){
  if (!error)
    console.log("Token transfer: " + result.args.amount + " tokens were sent. Balances now are as following: \n Sender:\t" + result.args.sender + " \t" + token.tokenBalanceOf.call(result.args.sender) + " tokens \n Receiver:\t" + result.args.receiver + " \t" + token.tokenBalanceOf.call(result.args.receiver) + " tokens" )
});

Sending tokens

Now of course those tokens aren't very useful if you hoard them all, so in order to send them to someone else, use this command:

token.sendToken.sendTransaction(eth.accounts[1], 1000, {from: eth.accounts[0]})

Note that our first function tokenBalanceOf was simply called directly on the contract instance and returned a value. This was possible since this was a simple read operation that incurs no state change and which executes locally and synchronously. Our second function sendToken needs a .sendTransaction() call. Since this function is meant to change the state (write operation), it is sent as a transaction to the network to be picked up by miners and included in the canonical blockchain. As a result the consensus state of all participant nodes will adequately reflect the state changes resulting from executing the transaction. Sender address needs to be sent as part of the transaction to fund the fuel needed to run the transaction. Now, wait a minute and check both accounts balances:

token.tokenBalanceOf.call(eth.accounts[0])/100 + "% of all tokens"
token.tokenBalanceOf.call(eth.accounts[1])/100 + "% of all tokens"

This example shown you how to create a token and execute transactions between parties, however all amounts and identities of the parties involved will be exposed publicly on the blockchain as part of how the Standard token works. So, how do we conduct private token transfers ?

Atum token standard

Atum token (ATU) is the default private token standard. To test-out privacy features, you can deploy your own token ATU is compatible with glyff-wallet.

(In future releases you will be able to use the ATU credited to you during the pre-sale/ICO.)

Learn More

  • Meta token standard is a proposed standardization of function names for token contracts, to allow them to be automatically added to other glyff contracts that utilizes trading, like exchanges or escrow.

  • Atum token standard is a proposed standardization of function names for privacy-enabled token contract.