$ nvm install --lts
$ node -v v8.9.4 $ npm -v 5.6.0
$ node -v > .nvmrc $ nvm install
$ npm -g install truffle + truffle@4.0.6 installed 1 package in 37.508s
$ truffle unbox BOX_NAME
$ mkdir Faucet $ cd Faucet Faucet $
Faucet $ truffle init
Faucet +---- contracts | `---- Migrations.sol +---- migrations | `---- 1_initial_migration.js +---- test +---- truffle-config.js `---- truffle.js
$ npm init
package name: (faucet)
version: (1.0.0)
description:
entry point: (truffle-config.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to Faucet/package.json:
{
"name": "faucet",
"version": "1.0.0",
"description": "",
"main": "truffle-config.js",
"directories": {
"test": "test"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this ok? (yes)
$ npm install dotenv truffle-wallet-provider ethereumjs-wallet
$ rm truffle.js
module.exports={networks:{localnode:{// Whatever network our local node connects tonetwork_id:"*",// Match any network IDhost:"localhost",port:8545,}}};
Faucet +---- contracts | +---- Faucet.sol | `---- Migrations.sol ...
$ truffle compile Compiling ./contracts/Faucet.sol... Compiling ./contracts/Migrations.sol... Writing artifacts to ./build/contracts
1varMigrations=artifacts.require("./Migrations.sol");2 3module.exports=function(deployer){4deployer.deploy(Migrations);5};
1varFaucet=artifacts.require("./Faucet.sol");2 3module.exports=function(deployer){4deployer.deploy(Faucet);5};
Faucet $ truffle migrate --network localnode
$ truffle migrate --network localnode Using network 'localnode'. Running migration: 1_initial_migration.js Deploying Migrations... ... 0xfa090db179d023d2abae543b4a21a1479e70ca7d35a469a5d1a98bfc6bd80fe8 Migrations: 0x8861c27715550bed8362c0345add158489df6db0 Saving successful migration to network... ... 0x985c4a32716826ddbe4eae284104bef8bc69e959899f62246a1b27c9dfcd6c03 Saving artifacts... Running migration: 2_deploy_contracts.js Deploying Faucet... ... 0xecdbeef77f0558edc689440e34b7bba0a3ba7a45e4b680b071b47c30a930e9d6 Faucet: 0xd01cd8e7bd29e4bff8c1693f59eee46137a9f300 Saving successful migration to network... ... 0x11f376bd7307edddfd40dc4a14c3f7cb84b6c921ac2465602060b67d08f9fd8a Saving artifacts...
$ truffle console --network localnode truffle(localnode)>
truffle(localnode)> Array Boolean Date Error EvalError Function Infinity JSON Math NaN Number Object RangeError ReferenceError RegExp String SyntaxError TypeError URIError decodeURI decodeURIComponent encodeURI encodeURIComponent eval isFinite isNaN parseFloat parseInt undefined ArrayBuffer Buffer DataView Faucet Float32Array Float64Array GLOBAL Int16Array Int32Array Int8Array Intl Map Migrations Promise Proxy Reflect Set StateManager Symbol Uint16Array Uint32Array Uint8Array Uint8ClampedArray WeakMap WeakSet WebAssembly XMLHttpRequest _ assert async_hooks buffer child_process clearImmediate clearInterval clearTimeout cluster console crypto dgram dns domain escape events fs global http http2 https module net os path perf_hooks process punycode querystring readline repl require root setImmediate setInterval setTimeout stream string_decoder tls tty unescape url util v8 vm web3 zlib __defineGetter__ __defineSetter__ __lookupGetter__ __lookupSetter__ __proto__ constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf
truffle(localnode)> web3.eth.accounts [ '0x9e713963a92c02317a681b9bb3065a8249de124f', '0xdb5dc1a13e3a55cf3b4587cd8d1e5fdeb6738145' ]
truffle(localnode)> web3.eth.getBalance(web3.eth.accounts[0]).toNumber() 191198572800000000 truffle(localnode)>
truffle(localnode)> Faucet.address '0xd01cd8e7bd29e4bff8c1693f59eee46137a9f300' truffle(localnode)> web3.eth.getBalance(Faucet.address).toNumber() 0 truffle(localnode)>
truffle(localnode)> web3.eth.sendTransaction({from:web3.eth.accounts[0],
to:Faucet.address, value:web3.toWei(0.5, 'ether')});
'0xf134c75b985dc0e0c27c2f0412251e0860eb530a5055e660f21e7483ab336808'
truffle(localnode)> web3.eth.getBalance(Faucet.address).toNumber() 500000000000000000
truffle(localnode)> Faucet.deployed().then(instance =>
{instance.withdraw(web3.toWei(0.1,
'ether'))}).then(console.log)
truffle(localnode)> web3.eth.getBalance(Faucet.address).toNumber()
400000000000000000
truffle(localnode)> Faucet.deployed().then(instance =>
{instance.withdraw(web3.toWei(1, 'ether'))})
StatusError: Transaction: 0xe147ae9e3610334...8612b92d3f9c
exited with an error (status 0).
Automatically deploy contracts and make them available in JS code.
Watch for changes and update contracts to redeploy if needed.
Manage and interact with different chains (e.g., testnet, local, mainnet).
Manage complex systems of interdependent contracts.
Store and retrieve data, including uploading and retrieving files hosted in IPFS.
Ease the process of deploying the full application to IPFS or Swarm.
Send and receive messages through Whisper.
$ npm -g install embark
$ mkdir sample-crowdsale $ cd sample-crowdsale $ npm install openzeppelin-solidity@1.9.0 $ mkdir contracts
pragma solidity0.4.23;import'openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol';contractSampleTokenisMintableToken{stringpublicname="SAMPLE TOKEN";stringpublicsymbol="SAM";uint8publicdecimals=18;}
pragma solidity0.4.23;import'./SampleToken.sol';import'openzeppelin-solidity/contracts/crowdsale/emission/MintedCrowdsale.sol';import'openzeppelin-solidity/contracts/crowdsale/\distribution/PostDeliveryCrowdsale.sol';contractSampleCrowdsaleisPostDeliveryCrowdsale,MintedCrowdsale{constructor(uint256_openingTime,uint256_closingTimeuint256_rate,address_wallet,MintableToken_token)publicCrowdsale(_rate,_wallet,_token)PostDeliveryCrowdsale(_openingTime,_closingTime){}}
constSampleCrowdsale=artifacts.require('./SampleCrowdsale.sol');constSampleToken=artifacts.require('./SampleToken.sol');module.exports=function(deployer,network,accounts){constopeningTime=web3.eth.getBlock('latest').timestamp+2;// 2s in futureconstclosingTime=openingTime+86400*20;// 20 daysconstrate=newweb3.BigNumber(1000);constwallet=accounts[1];returndeployer.then(()=>{returndeployer.deploy(SampleToken);}).then(()=>{returndeployer.deploy(SampleCrowdsale,openingTime,closingTime,rate,wallet,SampleToken.address);});};
Usage: helpeth [command] Commands: signMessage <message> Sign a message verifySig <hash> <sig> Verify signature verifySigParams <hash> <r> <s> <v> Verify signature parameters createTx <nonce> <to> <value> <data> Sign a transaction <gasLimit> <gasPrice> assembleTx <nonce> <to> <value> <data> Assemble a transaction from its <gasLimit> <gasPrice> <v> <r> <s> components parseTx <tx> Parse raw transaction keyGenerate [format] [icapdirect] Generate new key keyConvert Convert a key to V3 keystore format keyDetails Print key details bip32Details <path> Print key details for a given path addressDetails <address> Print details about an address unitConvert <value> <from> <to> Convert between Ethereum units Options: -p, --private Private key as a hex string [string] --password Password for the private key [string] --password-prompt Prompt for the private key password [boolean] -k, --keyfile Encoded key file [string] --show-private Show private key details [boolean] --mnemonic Mnemonic for HD key derivation [string] --version Show version number [boolean] --help Show help [boolean]
Dapp is the basic user-facing tool, for creating new DApps, running Solidity unit tests, debugging and deploying contracts, launching testnets, and more.
Seth is used for composing transactions, querying the blockchain, converting between data formats, performing remote calls, and similar everyday tasks.
Hevm is a Haskell EVM implementation with a nimble terminal-based Solidity debugger. It’s used to test and debug DApps.
evmdis is an EVM disassembler; it performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations.
| Framework | Test language(s) | Testing framework | Chain emulator | Website |
|---|---|---|---|---|
Truffle |
JavaScript/Solidity |
Mocha |
TestRPC/Ganache |
|
Embark |
JavaScript |
Mocha |
TestRPC/Ganache |
|
Dapp |
Solidity |
|
|
|
Populus |
Python |
|
Python chain emulator |
Truffle allows for unit tests to be written in JavaScript (Mocha-based) or Solidity. These tests are run against Ganache.
Embark integrates with Mocha to run unit tests written in JavaScript. The tests are in turn run against contracts deployed on TestRPC/Ganache. The Embark framework automatically deploys smart contracts, and will automatically redeploy the contracts when they are changed. It also keeps track of deployed contracts and deploys contracts only when truly needed. Embark includes a testing library to rapidly run and test your contracts in an EVM, with functions like assert.equal. The command embark test will run any test files under the directory test.
Dapp uses native Solidity code (a library called ds-test) and a Parity-built Rust library called ethrun to execute Ethereum bytecode and then assert correctness. The ds-test library provides assertion functions for validating correctness and events for logging data in the console.
The assertion functions include:
assert(bool condition) assertEq(address a, address b) assertEq(bytes32 a, bytes32 b) assertEq(int a, int b) assertEq(uint a, uint b) assertEq0(bytes a, bytes b) expectEventsExact(address target)
The logging commands will log information to the console, making them useful for debugging:
logs(bytes) log_bytes32(bytes32) log_named_bytes32(bytes32 key, bytes32 val) log_named_address(bytes32 key, address val) log_named_int(bytes32 key, int val) log_named_uint(bytes32 key, uint val) log_named_decimal_int(bytes32 key, int val, uint decimals) log_named_decimal_uint(bytes32 key, uint val, uint decimals)
Populus uses Python and its own chain emulator to run contracts written in Solidity. Unit tests are written in Python with the pytest library. Populus supports writing contracts specifically for testing. These contract filenames should match the glob pattern Test*.sol and be located anywhere under the project tests directory, tests.
eth.getTransactionReceipt(txhash);
eth.getCode(contractaddress)
eth.getPastLogs(options)
eth.getStorageAt(address, position)
$ npm install -g ganache-cli
$ ganache-cli \ --networkId=3 \ --port="8545" \ --verbose \ --gasLimit=8000000 \ --gasPrice=4000000000;
Check the --networkId and --port flag values match your configuration in truffle.js.
Check the --gasLimit flag value matches the latest mainnet gas limit (e.g., 8,000,000 gas) shown at https://ethstats.net to avoid encountering “out of gas” exceptions unnecessarily. Note that a --gasPrice of 4000000000 represents a gas price of 4 gwei.
You can optionally enter a --mnemonic flag value to restore a previous HD wallet and associated addresses.