Part 2: Compilation and Tester Deployment¶
Compile¶
Solidity compiles the source to EVM bytecode, the operations codes that will actually run on the blockchain.
To compile, first check that solidity works on your machine. Try to get the latest version.
$ solc --version
solc, the solidity compiler commandline interface
Version: 0.4.13+commit.0fb4cb1a.Linux.g++
In the project directory:
$ populus compile
If you copy-pasted the Donator
contract example, you will get:
Traceback (most recent call last):
File "/usr/local/bin/populus", line 11, in <module>
sys.exit(main())
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 722, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 697, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 1066, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 895, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python3.5/dist-packages/click/core.py", line 535, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/click/decorators.py", line 17, in new_func
return f(get_current_context(), *args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/populus/cli/compile_cmd.py", line 29, in compile_cmd
compile_project(project, watch)
File "/usr/local/lib/python3.5/dist-packages/populus/api/compile_contracts.py", line 18, in compile_project
_, compiled_contracts = compile_project_contracts(project)
File "/usr/local/lib/python3.5/dist-packages/populus/compilation/__init__.py", line 54, in compile_project_contracts
import_remappings=project.config.get('compilation.import_remappings'),
File "/usr/local/lib/python3.5/dist-packages/populus/compilation/backends/solc_auto.py", line 52, in get_compiled_contracts
return self.proxy_backend.get_compiled_contracts(*args, **kwargs)
File "/usr/local/lib/python3.5/dist-packages/populus/compilation/backends/solc_standard_json.py", line 131, in get_compiled_contracts
compilation_result = compile_standard(std_input, **command_line_options)
File "/usr/local/lib/python3.5/dist-packages/solc/main.py", line 184, in compile_standard
message=error_message,
solc.exceptions.SolcError: contracts/Donator.sol:21:5: DeclarationError: Identifier not found or not unique.
uin inUsd = msg.value * usd_rate;
^-^
> command: `solc --standard-json`
> return code: `0`
> stderr:
{"contracts":{},"errors":[{"component":"general","formattedMessage":"contracts/Donator.sol:21:5: DeclarationError: Identifier not found or not unique.\n uin inUsd = msg.value * usd_rate;\n ^-^\n","message":"Identifier not found or not unique.","severity":"error","type":"DeclarationError"}],"sources":{}}
> stdout:
What’s that? actually it’s not that bad. You can ignore the Python traceback, which is just the Populus call stack until the actual call to the compiler.
To undersatnd what went wrong, just look at the compiler’s output. The error message is quite clear:
solc.exceptions.SolcError: contracts/Donator.sol:21:5: DeclarationError: Identifier not found or not unique.
uin inUsd = msg.value * usd_rate;
^-^
Oh. Ok. uin inUsd
should be uint inUsd
. Edit and fix it:
$ nano contracts/Donator.sol
The fixed line should be:
uint inUsd = msg.value * usd_rate;
Note
Try the online IDE , which has great interactive compiler and web-form like interface to call the contract and it’s funcitons.
Try to compile again:
populus compile
> Found 2 contract source files
- contracts/Donator.sol
- contracts/Greeter.sol
> Compiled 2 contracts
- contracts/Donator.sol:Donator
- contracts/Greeter.sol:Greeter
> Wrote compiled assets to: build/contracts.json
Nice. The two contracts are now compiled. Take a look at the file that Populus just added,
build/contracts.json
. The file saves some of the compilers output, which will be useful later.
Note
Compilation creates bytecode
and bytecode_runtime
. The bytecode
contains the bytecode_runtime
,
as well as additional code. The additional code is required to deploy the runtime, but once deployed
the runtime is the contract on the blockchain.
Tester Deployment¶
You now have two compiled contracts, ready for deployment.
The first deployment step is to verify that it works on the tester
chain. This is an ephemeral blockchain.
It runs localy, and resets each time is starts. The state of the chain when it runs is kept only in memory,
and cleared when done. It’s a great tool for a testing.
Deploy to the tester
chain:
$ populus deploy --chain tester Donator
> Found 2 contract source files
- contracts/Donator.sol
- contracts/Greeter.sol
> Compiled 2 contracts
- contracts/Donator.sol:Donator
- contracts/Greeter.sol:Greeter
Beginning contract deployment. Deploying 1 total contracts (1 Specified, 0 because of library dependencies).
Donator
Deploying Donator
Deploy Transaction Sent: 0xd6de5b96feb23ce2550434a46ae9c95a9ab9c76c6274cc2b1f80e0b5a6870d11
Waiting for confirmation...
Transaction Mined
=================
Tx Hash : 0xd6de5b96feb23ce2550434a46ae9c95a9ab9c76c6274cc2b1f80e0b5a6870d11
Address : 0xc305c901078781c232a2a521c2af7980f8385ee9
Gas Provided : 294313
Gas Used : 194313
Verified contract bytecode @ 0xc305c901078781c232a2a521c2af7980f8385ee9
Deployment Successful.
When you deploy a contract Populus re-compiles all the contracts, but deploys only those you asked for.
Well, deployment works. Since the tester
chain is not persistent, everything was deleted, but the deployment should work on persistent
chains: it’s the same Ethereum protocol. Check for yourself and run the deploy again, it will re-dploy exactly the same,since
each starts from a reset state.
Interim Summary¶
So far you have:
- Compiled the project contracts
- Verified that deployment works, using the tester chain
In the next step we will add some tests.