Deploy

Introduction

Populus provides a command line interface for contract deployments which is suitable for simple contract deployments which do not involve constructor arguments as well as APIs for performing more complex deployments using python.

Deploying A Contract with the Command Line

Deployment is handled through the $ populus deploy command. All of the following are handled automatically.

  1. Selection of which chain should be deployed to.
  2. Running the given chain.
  3. Compilation of project contracts.
  4. Derivation of library dependencies.
  5. Library linking.
  6. Individual contract deployment.

Lets deploy a simple Wallet contract. First we’ll need a contract in our project ./contracts directory.

// ./contracts/Wallet.sol
contract Wallet {
        mapping (address => uint) public balanceOf;

        function deposit() {
                balanceOf[msg.sender] += 1;
        }

        function withdraw(uint value) {
                if (balanceOf[msg.sender] < value) throw;
                balanceOf[msg.sender] -= value;
                if (!msg.sender.call.value(value)()) throw;
        }
}

We can deploy this contract to a local test chain like this:

    $ populus deploy Wallet -c local_a
    Beginning contract deployment.  Deploying 1 total contracts (1 Specified, 0 because of library dependencies).

    Wallet
    Deploying Wallet
    Deploy Transaction Sent: 0x29e90f07314db495989f03ca931088e1feb7fb0fc13286c1724f11b2d6b239e7
    Waiting for confirmation...

    Transaction Mined
    =================
    Tx Hash      : 0x29e90f07314db495989f03ca931088e1feb7fb0fc13286c1724f11b2d6b239e7
    Address      : 0xb6fac5cb309da4d984bb6145078104355ece96ca
    Gas Provided : 267699
    Gas Used     : 167699


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

Above you can see the output for a basic deployment.

If your are outside the project directory, use:

$ populus -p /path/to/my/project deploy Wallet -c local_a

Programmatically deploy a contract

You can also deploy contracts using a Python script. This is a suitable method if your contracts take constructor arguments or need more complex initialization calls.

Example (deploy_testnet.py):

"""Deploy Edgeless token and smart contract in testnet.

A simple Python script to deploy contracts and then do a smoke test for them.
"""
from populus import Project
from populus.utils.wait import wait_for_transaction_receipt
from web3 import Web3


def check_succesful_tx(web3: Web3, txid: str, timeout=180) -> dict:
    """See if transaction went through (Solidity code did not throw).

    :return: Transaction receipt
    """

    # http://ethereum.stackexchange.com/q/6007/620
    receipt = wait_for_transaction_receipt(web3, txid, timeout=timeout)
    txinfo = web3.eth.getTransaction(txid)

    # EVM has only one error mode and it's consume all gas
    assert txinfo["gas"] != receipt["gasUsed"]
    return receipt


def main():

    project = Project()

    # This is configured in populus.json
    # We are working on a testnet
    chain_name = "ropsten"
    print("Make sure {} chain is running, you can connect to it, or you'll get timeout".format(chain_name))

    with project.get_chain(chain_name) as chain:

        # Load Populus contract proxy classes
        Crowdsale = chain.get_contract_factory('Crowdsale')
        Token = chain.get_contract_factory('EdgelessToken')

        web3 = chain.web3
        print("Web3 provider is", web3.currentProvider)

        # The address who will be the owner of the contracts
        beneficiary = web3.eth.coinbase
        assert beneficiary, "Make sure your node has coinbase account created"

        # Random address on Ropsten testnet
        multisig_address = "0x83917f644df1319a6ae792bb244333332e65fff8"

        # Deploy crowdsale, open since 1970
        txhash = Crowdsale.deploy(transaction={"from": beneficiary}, args=[beneficiary, multisig_address, 1])
        print("Deploying crowdsale, tx hash is", txhash)
        receipt = check_succesful_tx(web3, txhash)
        crowdsale_address = receipt["contractAddress"]
        print("Crowdsale contract address is", crowdsale_address)

        # Deploy token
        txhash = Token.deploy(transaction={"from": beneficiary}, args=[beneficiary])
        print("Deploying token, tx hash is", txhash)
        receipt = check_succesful_tx(web3, txhash)
        token_address = receipt["contractAddress"]
        print("Token contract address is", token_address)

        # Make contracts aware of each other
        print("Initializing contracts")
        crowdsale = Crowdsale(address=crowdsale_address)
        token = Token(address=token_address)
        txhash = crowdsale.transact({"from": beneficiary}).setToken(token_address)
        check_succesful_tx(web3, txhash)

        # Do some contract reads to see everything looks ok
        print("Token total supply is", token.call().totalSupply())
        print("Crowdsale max goal is", crowdsale.call().maxGoal())

        print("All done! Enjoy your decentralized future.")


if __name__ == "__main__":
    main()

See full source code repository example.