Skip to content

Commit

Permalink
Added more verification stuff, made ure the provided example deploys …
Browse files Browse the repository at this point in the history
…on Kovan and has an example acceptance test.
  • Loading branch information
miohtama committed Aug 23, 2017
1 parent 20c440a commit db37eaa
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 84 deletions.
86 changes: 46 additions & 40 deletions crowdsales/allocated-token-sale-example.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
# To deploy this file
#
# deploy-contracts --address=[my deploy account address account on geth having some Kovan ETH] --deployment-file=crowdsales/allocated-token-sale-example.yml --deployment-name=kovan

kovan:

chain: kovan

# Use automated Chrome to verify all contracts on etherscan.io
# You need to install Splinter package:
# pip install splinter
verify_on_etherscan: yes
browser_driver: chrome

# This is the Solidity version tag we verify on EtherScan.
# For available versions see
# https://etherscan.io/address/0xa8659f5af01796b39e0dfb3323acc00d8fe97ea2#code
# Click Verify and Publish
# See values in Compiler drop down.
# You can also get the local compiler version with:
#
# solc --version
#
# Note that for EtherScan you need to add letter "v" at the front of the version
#
# Note: You need to have correct optmization settings for the compiler
# in populus.json that matches what EtherScan is expecting.
#
solc_version: v0.4.14+commit.c2215d46
solc:

# This is the Solidity version tag we verify on EtherScan.
# For available versions see
# https://kovan.etherscan.io/verifyContract2
#
# See values in Compiler drop down.
# You can also get the local compiler version with:
#
# solc --version
#
# Note that for EtherScan you need to add letter "v" at the front of the version
#
# Note: You need to have correct optmization settings for the compiler
# in populus.json that matches what EtherScan is expecting.
#
version: v0.4.14+commit.c2215d46

#
# We supply these to EtherScan as the solc settings we used to compile the contract.
# They must match values in populus.json compilication / backends section.
#
optimizations:
optimizer: true
runs: 500

contracts:
# This is the address of the multisig wallet where the paymnts eventually land
Expand All @@ -44,7 +50,7 @@ kovan:
# We create the whole token supply upfront and no more token minting
# happens ever.
#
# Token has 18 decimals.
# Token has 18 decimals and supply of 1B tokens.
#
# Token supply is one billion tokens.
#
Expand Down Expand Up @@ -72,26 +78,26 @@ kovan:
contract_file: EthTranchePricing.sol
arguments:
_tranches:
# This trance starts instantly.
# How many weis one token costs. 20% bonus tier.
# Price is base_price / 1.2
- 0
- 2272727272727
# This trance starts instantly.
# How many weis one token costs. 20% bonus tier.
# Price is base_price / 1.2
- 0
- 2272727272727

# This trance starts when we have sold 45k worth of tokens.
# Token price is 10% bonus tokens (base price / 1.1)
- "{{ to_wei('45000.00', 'ether') }}"
- 2380952380952
# This trance starts when we have sold 45k worth of tokens.
# Token price is 10% bonus tokens (base price / 1.1)
- "{{ to_wei('45000.00', 'ether') }}"
- 2380952380952

# This is the base price that is effective until the token
# sale ends.
- "{{ to_wei('90000.00', 'ether') }}"
- 2500000000000
# This is the base price that is effective until the token
# sale ends.
- "{{ to_wei('90000.00', 'ether') }}"
- 2500000000000

# Dummy milestone marker to mark the end
# of the array.
- "{{ to_wei('999999999999999', 'ether') }}"
- 0
# Dummy milestone marker to mark the end
# of the array.
- "{{ to_wei('999999999999999', 'ether') }}"
- 0


#
Expand All @@ -107,8 +113,8 @@ kovan:
_token: "{{contracts.token.address}}"
_pricingStrategy: "{{contracts.pricing_strategy.address}}"
_multisigWallet: "{{contracts.team_multisig.address}}"
_start: "{{ timestamp(datetime(2017, 7, 12, 13, 00)) }}"
_end: "{{ timestamp(datetime(2017, 7, 26, 13, 00)) }}"
_start: "{{ timestamp(datetime(2099, 7, 12, 13, 00)) }}"
_end: "{{ timestamp(datetime(2099, 7, 26, 13, 00)) }}"
_minimumFundingGoal: "{{ to_wei(15000, 'ether') }}"
_beneficiary: "{{deploy_address}}"
#
Expand All @@ -126,7 +132,7 @@ kovan:
post_actions: |
# Allow crowdsale contract to sell its token
token.transact({"from": deploy_address}).approve(crowdsale.address, 70000000000*10**8)
token.transact({"from": deploy_address}).approve(crowdsale.address, 70000000000*10**18)
# Make sure crowdsale contract and these accounts
# can transfer tokens despite transfer lock up
Expand Down
39 changes: 25 additions & 14 deletions crowdsales/example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,31 @@ testnet:
# This is a semi automatic process using a Firefox browser.
verify_on_etherscan: yes

# For available versions see
# https://etherscan.io/address/0xa8659f5af01796b39e0dfb3323acc00d8fe97ea2#code
# Click Verify and Publish
# See values in Compiler drop down.
# You can also get the local compiler version with:
#
# solc --version
#
# Note that for EtherScan you need to add letter "v" at the front of the version
#
# Note: You need to have correct optmization settings for the compiler
# in populus.json that matches what EtherScan is expecting.
#
solc_version: v0.4.14+commit.c2215d46
solc:

# This is the Solidity version tag we verify on EtherScan.
# For available versions see
# https://kovan.etherscan.io/verifyContract2
#
# See values in Compiler drop down.
# You can also get the local compiler version with:
#
# solc --version
#
# Note that for EtherScan you need to add letter "v" at the front of the version
#
# Note: You need to have correct optmization settings for the compiler
# in populus.json that matches what EtherScan is expecting.
#
version: v0.4.14+commit.c2215d46

#
# We supply these to EtherScan as the solc settings we used to compile the contract.
# They must match values in populus.json compilication / backends section.
#
optimizations:
optimizer: true
runs: 500

#
# Contracts section defines different smart contracts that
Expand Down
27 changes: 25 additions & 2 deletions crowdsales/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,31 @@ unit_test:
# This is a semi automatic process using a Firefox browser.
verify_on_etherscan: no

# Not used in unit tests
solc_version: v0.4.14+commit.c2215d46
solc:

# This is the Solidity version tag we verify on EtherScan.
# For available versions see
# https://kovan.etherscan.io/verifyContract2
#
# See values in Compiler drop down.
# You can also get the local compiler version with:
#
# solc --version
#
# Note that for EtherScan you need to add letter "v" at the front of the version
#
# Note: You need to have correct optmization settings for the compiler
# in populus.json that matches what EtherScan is expecting.
#
version: v0.4.14+commit.c2215d46

#
# We supply these to EtherScan as the solc settings we used to compile the contract.
# They must match values in populus.json compilication / backends section.
#
optimizations:
optimizer: true
runs: 500

#
# Contracts section defines different smart contracts that
Expand Down
2 changes: 2 additions & 0 deletions docs/source/commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ deploy-contracts

Scripted deployment of multiple related Ethereum smart contracts.

See also :ref:`contract-verification`.

Example YAML deployment scripts

* `allocated-token-sale <https://github.com/TokenMarketNet/ico/blob/master/crowdsales/allocated-
Expand Down
69 changes: 61 additions & 8 deletions docs/source/verification.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.. _contract-verification:

=================================
Contract source code verification
=================================
Expand All @@ -16,16 +18,67 @@ Benefits of verification

* You prove that there are deterministic and verifiable builds for your deployed smart contracts

How verification works
======================
Prerequisites
=============

* You need to have Chrome and `chromedriver <http://brewformulas.org/Chromedriver>`_ installed for the browser automation

* You need to have `Splinter <http://splinter.readthedocs.io/en/latest/>`_ Python package installed:

.. code-block:: shell
pip install Splinter
How automatic verification works
================================

You need to specify the verification settings in your YAML deployment script for :ref:`deploy-contracts` command.

You need to make sure that you have your Solidity version and optimization parameters correctly.

Example how to get Solidity version:

.. code-block:: shell
solc --version
Here is an example YAML section:

.. code-block:: yaml
# Use automated Chrome to verify all contracts on etherscan.io
verify_on_etherscan: yes
browser_driver: chrome
solc:
# This is the Solidity version tag we verify on EtherScan.
# For available versions see
# https://kovan.etherscan.io/verifyContract2
#
# See values in Compiler drop down.
# You can also get the local compiler version with:
#
# solc --version
#
# Note that for EtherScan you need to add letter "v" at the front of the version
#
# Note: You need to have correct optmization settings for the compiler
# in populus.json that matches what EtherScan is expecting.
#
version: v0.4.14+commit.c2215d46
* You need to have Firefox installed with necessary Selenium drivers
#
# We supply these to EtherScan as the solc settings we used to compile the contract.
# They must match values in populus.json compilication / backends section.
# These are the defaults supplied with the default populus.json.
#
optimizations:
optimizer: true
runs: 500
* Give `--verify` option to a :ref:`deployment script <command-line>`
When you run `deploy-contracts` and `verify_on_etherscan` is turned `on`, a Chrome browser will automatically open after a contract has been deployed. It goes to Verify page on EtherScan and automatically submits all verification information, including libraries.

* After the command line script has deployed the contract a browser will open
In the case there is a problem with the verification, `deploy-contracts` will stop and ask you to continue. During this time, you can check what is the actual error from EtherScan on the opened Chrome browser.

* The script autofills the verification page details (source code, construction arguments, linked libraries)

.. image:: screenshots/etherscan_verify.png
:width: 600
36 changes: 28 additions & 8 deletions ico/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def deploy_contract(project: Project, chain, deploy_address, contract_def: dict,
return contract


def deploy_crowdsale(project: Project, chain, source_definitions: dict, deploy_address) -> Tuple[dict, dict, dict]:
def deploy_crowdsale(project: Project, chain, yaml_filename: str, source_definitions: dict, deploy_address) -> Tuple[dict, dict, dict]:
"""Deploy multiple contracts from crowdsale definitions.
:param chain: Populus chain object
Expand All @@ -102,7 +102,7 @@ def deploy_crowdsale(project: Project, chain, source_definitions: dict, deploy_a
chain_name = runtime_data["chain"]
verify_on_etherscan = asbool(runtime_data["verify_on_etherscan"])
browser_driver = runtime_data.get("browser_driver", "chrome")
solc_version = runtime_data["solc_version"]
solc = runtime_data["solc"]

need_unlock = runtime_data.get("unlock_deploy_address", True)

Expand Down Expand Up @@ -145,25 +145,45 @@ def deploy_crowdsale(project: Project, chain, source_definitions: dict, deploy_a
constructor_args=runtime_data["contracts"][name]["constructor_args"],
libraries=runtime_data["contracts"][name]["libraries"],
browser_driver=browser_driver,
compiler=solc_version,
optimization=False)
compiler=solc["version"],
optimization=asbool(solc["optimizations"]["optimizer"]),
optimizer_runs=int(solc["optimizations"]["runs"])
)
runtime_data["contracts"][name]["etherscan_link"] = get_etherscan_link(chain_name, runtime_data["contracts"][name]["address"])

# Write out our expanded contract
expanded_path = os.path.join(os.getcwd(), "build", "expanded", fname)
with open(expanded_path, "wt") as out:
out.write(src)

# Write the ongoing output, so we can use it e.g. to debug EtherScan verification
write_deployment_report(yaml_filename, runtime_data, partial=True)

return runtime_data, statistics, contracts


def write_deployment_report(yaml_filename: str, runtime_data: dict):
"""Write run-time data to a result file, so that it can easily inspected and shared."""
def write_deployment_report(yaml_filename: str, runtime_data: dict, partial=False):
"""Write run-time data to a result file, so that it can easily inspected and shared.
:param partial: Don't override existing successful deployment report by accident
"""

partial_report_filename = yaml_filename.replace(".yml", ".partial-report.yml")

if partial:
report_filename = partial_report_filename
print("Writing partial report", report_filename)
else:
report_filename = yaml_filename.replace(".yml", ".deployment-report.yml")

report_filename = yaml_filename.replace(".yml", ".deployment-report.yml")
with open(report_filename, "wt") as out:
out.write(ruamel.yaml.round_trip_dump(runtime_data))

if not partial:
# Delete the partial file name after successfully deploying everything
if os.path.exists(partial_report_filename):
os.unlink(partial_report_filename)


def exec_lines(lines: str, context: dict, print_prefix=None):
"""Exec python code line-by-line and stop on error.
Expand Down Expand Up @@ -249,7 +269,7 @@ def _deploy_contracts(project, chain, web3, yaml_filename, chain_data, deploy_ad
start_balance = from_wei(web3.eth.getBalance(address), "ether")
print("Owner balance is", start_balance, "ETH")

runtime_data, statistics, contracts = deploy_crowdsale(project, chain, chain_data, deploy_address)
runtime_data, statistics, contracts = deploy_crowdsale(project, chain, yaml_filename, chain_data, deploy_address)
perform_post_actions(chain, runtime_data, contracts)
perform_verify_actions(chain, runtime_data, contracts)
write_deployment_report(yaml_filename, runtime_data)
Expand Down

0 comments on commit db37eaa

Please sign in to comment.