Tutorial

Introduction

The following tutorial picks up where the quickstart leaves off. You should have a single solidity contract named Greeter located in ./contracts/Greeter.sol and a single test module ./tests/test_greeter.py that contains two tests.

Modify our Greeter

Lets add way for the Greeter contract to greet someone by name. We’ll do so by adding a new function greet(bytes name) which you can see below. Update your solidity source to match this updated version of the contract.

contract Greeter {
    string public greeting;

    function Greeter() {
        greeting = "Hello";
    }

    function setGreeting(string _greeting) public {
        greeting = _greeting;
    }

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

    function greet(bytes name) constant returns (bytes) {
        // create a byte array sufficiently large to store our greeting.
        bytes memory namedGreeting = new bytes(
            name.length + 1 + bytes(greeting).length
        );

        // push the greeting onto our return value.
        // greeting.
        for (uint i=0; i < bytes(greeting).length; i++) {
            namedGreeting[i] = bytes(greeting)[i];
        }

        // add a space before pushing the name on.
        namedGreeting[bytes(greeting).length] = ' ';

        // loop over the name and push all of the characters onto the
        // greeting.
        for (i=0; i < name.length; i++) {
            namedGreeting[bytes(greeting).length + 1 + i] = name[i];
        }
        return namedGreeting;
    }
}

Testing our changes

Now we’ll want to test our contract. Lets add another test to ./tests/test_greeter.py so that the file looks as follows.

def test_greeter(chain):
    greeter = chain.get_contract('Greeter')

    greeting = greeter.call().greet()
    assert greeting == 'Hello'

def test_custom_greeting(chain):
    greeter = chain.get_contract('Greeter')

    set_txn_hash = greeter.transact().setGreeting('Guten Tag')
    chain.wait.for_receipt(set_txn_hash)

    greeting = greeter.call().greet()
    assert greeting == 'Guten Tag'

def test_named_greeting(chain):
    greeter = chain.get_contract('Greeter')

    greeting = greeter.call().greet('Piper')
    assert greeting == 'Hello Piper'

Deploying the contract

Since the Greeter contract is so simple, we can deploy it using the $ populus deploy command. Lets deploy the contract to a local test chain. We can use the $ populus chain config command to setup the chain via an interactive prompt.

$ populus chain config local_test
Configuring **new** chain: local_test
-------------------------------------


Populus can run the blockchain client for you, including connecting to the public main and test networks.

 Should populus manage running this chain? [Y/n]: y


Web3 Provider Choices:
1) IPC socket (default)
2) RPC via HTTP

How should populus connect web3.py to this chain? [ipc]: ipc


Will this blockchain be running with a non-standard `geth.ipc`path?

 [y/N]: n
This chain will default to sending transactions from 0xeb4036b556275f55a1a7e3cabda93df317f37459.  Would you like to set a different default account? [y/N]: n
Writing configuration to populus.ini ...
Success!

Now lets deploy our contract.

$ populus deploy Greeter --chain local_test
Accounts
-----------------
0 - 0xeb4036b556275f55a1a7e3cabda93df317f37459

Enter the account address or the number of the desired account [0xeb4036b556275f55a1a7e3cabda93df317f37459]:
Would you like set the address '0xeb4036b556275f55a1a7e3cabda93df317f37459' as the default`deploy_from` address for the 'local_test' chain? [y/N]: y
Wrote updated chain configuration to 'populus.ini'
Beginning contract deployment.  Deploying 1 total contracts (1 Specified, 0 because of library dependencies).

Greeter
Deploying Greeter
Deploy Transaction Sent: 0xb0864c64ed4fc6ef77ff7e747b4bc8db3f1ac235ea2d78a9f2bcf07b95f97115
Waiting for confirmation...

Transaction Mined
=================
Tx Hash      : 0xb0864c64ed4fc6ef77ff7e747b4bc8db3f1ac235ea2d78a9f2bcf07b95f97115
Address      : 0x0b9539f881c846b13978c91d0e83730796dc9873
Gas Provided : 655977
Gas Used     : 555977


Verifying deployed bytecode...
Verified contract bytecode @ 0x0b9539f881c846b13978c91d0e83730796dc9873 matches expected runtime bytecode
Deployment Successful.

Lets take a minute to discuss what just occurred under the hood.

First we configured a new private blockchain that we can use for testing. This is a real Ethereum blockchain in the sense that it will use the go-ethereum binary to run the blockchain, and that you can interact with it the same way you woult the public networks.

Next, we used the deploy command to deploy our Greeter contract onto this blockchain. Under the hood, Populus did the following things.

  • Ran the test chain in a subprocess.
  • Compiled your contracts.
  • Sent the deploy transaction and waited for it to be mined.
  • Verified that the deployment was successful by checking the on-chain bytecode against the expected value.