├── js
├── .nvmrc
├── runtestrpc.sh
├── web3-testrpc.js
├── web3-test.js
├── package.json
├── tests
│ ├── tools.js
│ └── one-value-tests.js
├── genesis.json
├── express-example.js
├── update-contract-test.js
├── deploy-client-receipt.js
├── deploy-contract-test.js
├── deploy-contract-testrpc.js
└── watch-client-receipt.js
├── contracts
├── build
│ ├── Config.bin
│ ├── NameReg.bin
│ ├── interitance-example.sol:owned.abi
│ ├── interitance-example.sol:mortal.abi
│ ├── interitance-example.sol:Config.abi
│ ├── interitance-example.sol:named.abi
│ ├── interitance-example.sol:NameReg.abi
│ ├── owned.bin
│ ├── ClientReceipt.sol:ClientReceipt.abi
│ ├── OneValue.sol:OneValue.abi
│ ├── interitance-example.sol:PriceFeed.abi
│ ├── ClientReceipt.bin
│ ├── OneValue.bin
│ ├── CrowdFunding.sol:CrowdFunding.abi
│ ├── WithdrawalContract.sol:WithdrawalContract.abi
│ ├── lib-set.sol:Set.abi
│ ├── AccessRestriction.sol:AccessRestriction.abi
│ ├── mortal.bin
│ ├── StateMachine.sol:StateMachine.abi
│ ├── remote-purchase.sol:Purchase.abi
│ ├── Set.bin
│ ├── Ballot.sol:Ballot.abi
│ ├── SimpleAuction.sol:SimpleAuction.abi
│ ├── CrowdFunding.bin
│ ├── WithdrawalContract.bin
│ ├── BlindAuction.sol:BlindAuction.abi
│ ├── named.bin
│ ├── AccessRestriction.bin
│ ├── PriceFeed.bin
│ ├── StateMachine.bin
│ ├── SimpleAuction.bin
│ ├── Purchase.bin
│ ├── Ballot.bin
│ └── BlindAuction.bin
├── .soliumignore
├── build.sh
├── OneValue.sol
├── ClientReceipt.sol
├── .soliumrc.json
├── WithdrawalContract.sol
├── lib-set.sol
├── CrowdFunding.sol
├── StateMachine.sol
├── interitance-example.sol
├── AccessRestriction.sol
├── remote-purchase.sol
├── SimpleAuction.sol
├── Ballot.sol
└── BlindAuction.sol
├── dapp_example
├── myDapp
│ ├── .gitignore
│ ├── .meteor
│ │ ├── .gitignore
│ │ ├── release
│ │ ├── platforms
│ │ ├── .id
│ │ ├── .finished-upgraders
│ │ ├── packages
│ │ └── versions
│ ├── public
│ │ └── a.txt
│ ├── deploy.sh
│ ├── client
│ │ ├── main.less
│ │ ├── main.js
│ │ └── main.html
│ ├── lib
│ │ └── init.js
│ ├── server
│ │ └── main.js
│ └── package.json
└── myDapp2
│ ├── .gitignore
│ ├── .meteor
│ ├── .gitignore
│ ├── release
│ ├── platforms
│ ├── .id
│ ├── .finished-upgraders
│ ├── packages
│ └── versions
│ ├── deploy.sh
│ ├── client
│ ├── main.less
│ ├── main.html
│ └── main.js
│ ├── lib
│ └── init.js
│ ├── server
│ └── main.js
│ └── package.json
├── slides
├── install.sh
├── images
│ ├── mist.gif
│ ├── fdi-mist.png
│ ├── metamask.png
│ ├── fdi-metamask.png
│ ├── flightdelay-dapp.jpg
│ └── meteor-dashboard.png
├── README.md
├── package.json
├── build.sh
├── 0_Agenda_0906.md
├── 0_Agenda_1114.md
├── 0_Agenda.md
├── 0_Agenda_03232017.md
├── 1_Blockchain_Recap_0323.md
├── 0_Agenda_03172017.md
├── 7_References.md
├── 0_Agenda_03102017.md
├── css
│ └── style.css
├── 5_Solidity_Patterns.md
├── yarn.lock
├── 6_Solidity_Testing.md
├── 1_Blockchain_Basics.md
├── 4_Solidity_Security.md
├── 10_Web3_JavaScript.md
├── 9_Dapps_Development.md
├── 2_Ethereum_Development_Environment_and_Tools_03202017.md
├── 8_Insurance_Examples.md
└── 2_Ethereum_Development_Environment_and_Tools.md
├── qrcode.png
├── truffle_test
├── migrations
│ ├── 1_initial_migration.js
│ ├── 3_deploy_one_value_contract.js
│ └── 2_deploy_contracts.js
├── contracts
│ ├── ConvertLib.sol
│ ├── OneValue.sol
│ ├── Migrations.sol
│ └── MetaCoin.sol
├── truffle.js
├── test
│ ├── TestMetacoin.sol
│ └── metacoin.js
└── app
│ ├── stylesheets
│ └── app.css
│ ├── index.html
│ └── javascripts
│ └── app.js
├── .gitignore
├── README.MD
├── LECTURES.MD
└── FlightDelay
└── FlightDelay.sol
/js/.nvmrc:
--------------------------------------------------------------------------------
1 | 6.9.1
2 |
--------------------------------------------------------------------------------
/contracts/build/Config.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/contracts/build/NameReg.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/contracts/.soliumignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/dapp_example/myDapp/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/public/a.txt:
--------------------------------------------------------------------------------
1 | public file
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.4.2.7
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.4.2.7
2 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/slides/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | npm install markdown-to-slides -g
3 |
--------------------------------------------------------------------------------
/qrcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/qrcode.png
--------------------------------------------------------------------------------
/dapp_example/myDapp/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | meteor deploy ytdapp01.meteorapp.com
4 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | meteor deploy ytdapp02.meteorapp.com
4 |
--------------------------------------------------------------------------------
/contracts/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Build
4 | solc --bin --abi --gas -o ./build *.sol
5 |
--------------------------------------------------------------------------------
/js/runtestrpc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | node_modules/ethereumjs-testrpc/bin/testrpc -p 8600 -a 10
3 |
--------------------------------------------------------------------------------
/contracts/build/interitance-example.sol:owned.abi:
--------------------------------------------------------------------------------
1 | [{"inputs":[],"payable":false,"type":"constructor"}]
--------------------------------------------------------------------------------
/slides/images/mist.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/slides/images/mist.gif
--------------------------------------------------------------------------------
/slides/images/fdi-mist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/slides/images/fdi-mist.png
--------------------------------------------------------------------------------
/slides/images/metamask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/slides/images/metamask.png
--------------------------------------------------------------------------------
/slides/images/fdi-metamask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/slides/images/fdi-metamask.png
--------------------------------------------------------------------------------
/slides/README.md:
--------------------------------------------------------------------------------
1 | ## Build the slides
2 | 1. Install `markdown-to-slides`: run `install.sh`
3 | 2. Build slides: run `build.sh`
4 |
--------------------------------------------------------------------------------
/slides/images/flightdelay-dapp.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/slides/images/flightdelay-dapp.jpg
--------------------------------------------------------------------------------
/slides/images/meteor-dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/getamis/contract-training/HEAD/slides/images/meteor-dashboard.png
--------------------------------------------------------------------------------
/slides/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "global": "^4.3.1",
4 | "markdown-to-slides": "^1.0.5"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/client/main.less:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
2 | // libs
3 | @import '{ethereum:dapp-styles}/dapp-styles.less';
4 |
--------------------------------------------------------------------------------
/contracts/build/interitance-example.sol:mortal.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/dapp_example/myDapp2/client/main.less:
--------------------------------------------------------------------------------
1 | /* CSS declarations go here */
2 | // libs
3 | @import '{ethereum:dapp-styles}/dapp-styles.less';
4 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/lib/init.js:
--------------------------------------------------------------------------------
1 | if(typeof web3 === 'undefined')
2 | web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
3 |
4 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/lib/init.js:
--------------------------------------------------------------------------------
1 | if(typeof web3 === 'undefined')
2 | web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
3 |
4 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/server/main.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 |
3 | Meteor.startup(() => {
4 | // code to run on server at startup
5 | });
6 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/server/main.js:
--------------------------------------------------------------------------------
1 | import { Meteor } from 'meteor/meteor';
2 |
3 | Meteor.startup(() => {
4 | // code to run on server at startup
5 | });
6 |
--------------------------------------------------------------------------------
/slides/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | find . -name '*.md' -not -path "./node_modules/*" | xargs -I '{}' markdown-to-slides '{}' -o '{}'.html -s css/style.css -i
3 |
--------------------------------------------------------------------------------
/truffle_test/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/truffle_test/migrations/3_deploy_one_value_contract.js:
--------------------------------------------------------------------------------
1 | var OneValue = artifacts.require("./OneValue.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(OneValue);
5 | };
6 |
--------------------------------------------------------------------------------
/contracts/build/interitance-example.sol:Config.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"id","type":"uint256"}],"name":"lookup","outputs":[{"name":"adr","type":"address"}],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/contracts/build/interitance-example.sol:named.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"name","type":"bytes32"}],"payable":false,"type":"constructor"}]
--------------------------------------------------------------------------------
/truffle_test/contracts/ConvertLib.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.4;
2 |
3 | library ConvertLib{
4 | function convert(uint amount,uint conversionRate) returns (uint convertedAmount)
5 | {
6 | return amount * conversionRate;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myDapp",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run"
6 | },
7 | "dependencies": {
8 | "meteor-node-stubs": "~0.2.0",
9 | "babel-runtime": "6.18.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "myDapp",
3 | "private": true,
4 | "scripts": {
5 | "start": "meteor run"
6 | },
7 | "dependencies": {
8 | "meteor-node-stubs": "~0.2.0",
9 | "babel-runtime": "6.18.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/contracts/build/interitance-example.sol:NameReg.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"name","type":"bytes32"}],"name":"register","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"unregister","outputs":[],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/js/web3-testrpc.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var TestRPC = require("ethereumjs-testrpc");
3 | var web3 = new Web3(TestRPC.provider());
4 | web3.eth.getAccounts(function(e, accts){
5 | console.log("error:", e);
6 | console.log("accounts:", accts);
7 | process.exit(0);
8 | });
9 |
--------------------------------------------------------------------------------
/js/web3-test.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
3 |
4 | web3.eth.getBlock(48, function(error, result){
5 | if(!error)
6 | console.log(result)
7 | else
8 | console.error(error);
9 | });
10 |
--------------------------------------------------------------------------------
/contracts/build/owned.bin:
--------------------------------------------------------------------------------
1 | 60606040523415600b57fe5b5b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b603380605c6000396000f30060606040525bfe00a165627a7a723058205b82c5c0182c317ebd429c65630906900277e50ffbadf01cae0c8c3af36d8cf50029
--------------------------------------------------------------------------------
/truffle_test/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var ConvertLib = artifacts.require("./ConvertLib.sol");
2 | var MetaCoin = artifacts.require("./MetaCoin.sol");
3 |
4 | module.exports = function(deployer) {
5 | deployer.deploy(ConvertLib);
6 | deployer.link(ConvertLib, MetaCoin);
7 | deployer.deploy(MetaCoin);
8 | };
9 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | 1c1lvqbf0agoy1ex4vim
8 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | 1c1lvqbf0agoy1ex4vim
8 |
--------------------------------------------------------------------------------
/contracts/build/ClientReceipt.sol:ClientReceipt.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"deposit","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_id","type":"bytes32"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Deposit","type":"event"}]
--------------------------------------------------------------------------------
/contracts/build/OneValue.sol:OneValue.abi:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"payable":false,"type":"constructor"}]
--------------------------------------------------------------------------------
/contracts/build/interitance-example.sol:PriceFeed.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"newInfo","type":"uint256"}],"name":"updateInfo","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"r","type":"uint256"}],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/contracts/OneValue.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.4;
2 |
3 |
4 | contract OneValue {
5 | uint256 value;
6 |
7 | function OneValue(uint256 initValue) {
8 | value = initValue;
9 | }
10 |
11 | function setValue(uint256 v) {
12 | value = v;
13 | }
14 |
15 | function getValue() constant returns (uint256 result) {
16 | return value;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/truffle_test/contracts/OneValue.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.8;
2 |
3 | contract OneValue {
4 | uint256 value;
5 |
6 | function OneValue(uint256 initValue) {
7 | value = initValue;
8 | }
9 |
10 | function setValue(uint256 v) {
11 | value = v;
12 | }
13 |
14 | function getValue() constant returns (uint256 result){
15 | return value;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "contract-training",
3 | "version": "0.1.0",
4 | "dependencies": {
5 | "ethereumjs-testrpc": "^3.0.3",
6 | "express": "4.14.0",
7 | "mocha": "2.4.5",
8 | "truffle": "^2.1.1",
9 | "web3": "0.18.2"
10 | },
11 | "scripts": {
12 | "test": "find tests -name '*tests.js' -not -path './node_modules/*' | xargs ./node_modules/mocha/bin/_mocha -R spec"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/contracts/ClientReceipt.sol:
--------------------------------------------------------------------------------
1 | contract ClientReceipt {
2 | event Deposit(
3 | address indexed _from,
4 | bytes32 indexed _id,
5 | uint _value
6 | );
7 |
8 | function deposit(bytes32 _id) {
9 | // Any call to this function (even deeply nested) can
10 | // be detected from the JavaScript API by filtering
11 | // for `Deposit` to be called.
12 | Deposit(msg.sender, _id, msg.value);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/js/tests/tools.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | var fs = require('fs');
4 |
5 | var self = module.exports = {
6 | loadAbi: function(name) {
7 | var abi = JSON.parse(fs.readFileSync( __dirname + '/../../contracts/build/'+name+'.abi').toString());
8 | return abi;
9 | },
10 | loadBin: function(name) {
11 | var bin = fs.readFileSync( __dirname + '/../../contracts/build/'+name+'.bin').toString();
12 | return bin;
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/contracts/build/ClientReceipt.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b5b60de8061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b214faa514603a575bfe5b3415604157fe5b6059600480803560001916906020019091905050605b565b005b80600019163373ffffffffffffffffffffffffffffffffffffffff167f19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f346040518082815260200191505060405180910390a35b505600a165627a7a72305820528673a40eadb3be75f92326e0664ef276b182a65164702f0d7c104f291b9c680029
--------------------------------------------------------------------------------
/truffle_test/truffle.js:
--------------------------------------------------------------------------------
1 | var DefaultBuilder = require("truffle-default-builder");
2 |
3 | module.exports = {
4 | build: new DefaultBuilder({
5 | "index.html": "index.html",
6 | "app.js": [
7 | "javascripts/app.js"
8 | ],
9 | "app.css": [
10 | "stylesheets/app.css"
11 | ],
12 | "images/": "images/"
13 | }),
14 | networks: {
15 | development: {
16 | host: "localhost",
17 | port: 8547,
18 | network_id: "*" // Match any network id
19 | }
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/slides/0_Agenda_0906.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Ethereum Smart Contract
4 | ## Yu-Te Lin
5 |
6 | ---
7 |
8 | ## 以太坊開發環境及工具介紹
9 |
10 | - Ethereum and Smart contract
11 |
12 | - Wallet GUI: Mist
13 |
14 | - Command line tools: geth, solc
15 |
16 | - Contract editors: atom, sublime text, visual studio.
17 |
18 | - Libraries and Development tools: web3, testrpc, truffle.
19 |
20 | - Contract deployment
21 |
22 | ---
23 |
24 | ## 以太坊智能合約開發
25 |
26 | - 程式設計
27 |
28 | - 資訊安全
29 |
30 | - 設計模式
31 |
32 | - 測試
33 |
--------------------------------------------------------------------------------
/contracts/build/OneValue.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b604051602080610107833981016040528080519060200190919050505b806000819055505b505b60c6806100416000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632096525514604457806355241077146067575bfe5b3415604b57fe5b60516084565b6040518082815260200191505060405180910390f35b3415606e57fe5b60826004808035906020019091905050608f565b005b600060005490505b90565b806000819055505b505600a165627a7a72305820b3bec82e172f8481e07342d3b3a500a8fd2ef3ae60cdbcfec91dbd27feca90490029
--------------------------------------------------------------------------------
/contracts/build/CrowdFunding.sol:CrowdFunding.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"campaignID","type":"uint256"}],"name":"checkGoalReached","outputs":[{"name":"reached","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"campaignID","type":"uint256"}],"name":"contribute","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"beneficiary","type":"address"},{"name":"goal","type":"uint256"}],"name":"newCampaign","outputs":[{"name":"campaignID","type":"uint256"}],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 | 1.4.0-remove-old-dev-bundle-link
15 | 1.4.1-add-shell-server-package
16 |
--------------------------------------------------------------------------------
/contracts/build/WithdrawalContract.sol:WithdrawalContract.abi:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[],"name":"richest","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"mostSent","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"becomeRichest","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"inputs":[],"payable":true,"type":"constructor"}]
--------------------------------------------------------------------------------
/js/genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "nonce": "0x0000000000000042",
3 | "timestamp": "0x0",
4 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
5 | "extraData": "Any extra data 134ADFAD",
6 | "gasLimit": "0x47e7c4",
7 | "difficulty": "0x9c40",
8 | "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
9 | "coinbase": "0x3333333333333333333333333333333333333333",
10 | "alloc": {
11 | "0x60cafee22ae353ac9de07852a682558c9bb84e61": {
12 | "balance": "999999999999999999999999999999999"
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/contracts/build/lib-set.sol:Set.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"self","type":"Set.Data storage"},{"name":"value","type":"uint256"}],"name":"remove","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"self","type":"Set.Data storage"},{"name":"value","type":"uint256"}],"name":"contains","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"self","type":"Set.Data storage"},{"name":"value","type":"uint256"}],"name":"insert","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/contracts/.soliumrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "custom-rules-filename": null,
3 | "rules": {
4 | "imports-on-top": true,
5 | "variable-declarations": true,
6 | "array-declarations": true,
7 | "operator-whitespace": true,
8 | "lbrace": true,
9 | "mixedcase": true,
10 | "camelcase": true,
11 | "uppercase": true,
12 | "no-with": true,
13 | "no-empty-blocks": true,
14 | "no-unused-vars": true,
15 | "double-quotes": true,
16 | "blank-lines": true,
17 | "indentation": true,
18 | "whitespace": true,
19 | "deprecated-suicide": true,
20 | "pragma-on-top": true
21 | }
22 | }
--------------------------------------------------------------------------------
/truffle_test/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.4;
2 |
3 | contract Migrations {
4 | address public owner;
5 | uint public last_completed_migration;
6 |
7 | modifier restricted() {
8 | if (msg.sender == owner) _;
9 | }
10 |
11 | function Migrations() {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/contracts/build/AccessRestriction.sol:AccessRestriction.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"forceOwnerChange","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"disown","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"creationTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/dapp_example/myDapp2/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | myDapp
3 |
4 |
5 |
6 | OneValue Contract
7 |
8 | {{> blockInfo}}
9 |
10 |
11 |
12 | {{> oneValue}}
13 |
14 |
15 |
16 |
17 | Block height: {{currentBlock}}
18 |
19 |
20 |
21 | OneValue contract at {{oneValueAddress}}
22 | Current value: {{currentValue}}
23 | Set value:
24 | {{getMessage}}
25 |
26 |
--------------------------------------------------------------------------------
/contracts/build/mortal.bin:
--------------------------------------------------------------------------------
1 | 60606040525b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b610108806100576000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806341c0e1b514603a575bfe5b3415604157fe5b60476049565b005b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141560d957600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b5600a165627a7a72305820e2d013cfe53a7bda0ac5dc6589fba884f5511bac04be980303103c42dcb83aa30029
--------------------------------------------------------------------------------
/contracts/build/StateMachine.sol:StateMachine.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[],"name":"bid","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"reveal","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"h","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"stage","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"creationTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"g","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"i","outputs":[],"payable":false,"type":"function"}]
--------------------------------------------------------------------------------
/slides/0_Agenda_1114.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Ethereum Smart Contract
4 | ## Yu-Te Lin
5 |
6 | ---
7 |
8 | ## 以太坊開發環境及工具介紹
9 |
10 | - Ethereum and Smart contract
11 |
12 | - Wallet GUI: Mist
13 |
14 | - Command line tools: geth, solc
15 |
16 | - Contract editors: atom, sublime text, visual studio.
17 |
18 | - Libraries and Development tools: web3, testrpc, truffle.
19 |
20 | - Contract deployment
21 |
22 | ---
23 |
24 | ## 以太坊智能合約開發
25 |
26 | - 程式設計
27 |
28 | - 資訊安全
29 |
30 | - 設計模式
31 |
32 | - 測試
33 |
34 | ---
35 |
36 | ## Github
37 | - Github: https://github.com/amisamity/contract-training
38 |
39 | 
40 |
--------------------------------------------------------------------------------
/truffle_test/test/TestMetacoin.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.2;
2 |
3 | import "truffle/Assert.sol";
4 | import "truffle/DeployedAddresses.sol";
5 | import "../contracts/MetaCoin.sol";
6 |
7 | contract TestMetacoin {
8 |
9 | function testInitialBalanceUsingDeployedContract() {
10 | MetaCoin meta = MetaCoin(DeployedAddresses.MetaCoin());
11 |
12 | uint expected = 10000;
13 |
14 | Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially");
15 | }
16 |
17 | function testInitialBalanceWithNewMetaCoin() {
18 | MetaCoin meta = new MetaCoin();
19 |
20 | uint expected = 10000;
21 |
22 | Assert.equal(meta.getBalance(tx.origin), expected, "Owner should have 10000 MetaCoin initially");
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/slides/0_Agenda.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Ethereum Smart Contract
4 | ## Yu-Te Lin
5 |
6 | ---
7 |
8 | ## Blockchain Basics
9 |
10 | - Blockchain 1.0: Bitcoin, Altcoins
11 |
12 | - Blockchain 1.1: Colored coins, decoration protocols
13 |
14 | - Blockchain 2.0: Ethereum, Tendermint
15 |
16 | ---
17 |
18 | ## Ethereum Development Environment and Tools
19 |
20 | - Ethereum and Smart contract
21 |
22 | - Wallet GUI: Mist
23 |
24 | - Command line tools: geth, solc
25 |
26 | - Contract editors: atom, sublime text, visual studio.
27 |
28 | - Libraries and Development tools: web3, testrpc, truffle.
29 |
30 | - Contract deployment
31 |
32 | ---
33 |
34 | ## Smart Contract Coding
35 |
36 | - Basics
37 |
38 | - Security
39 |
40 | - Patterns
41 |
42 | - Testing
43 |
--------------------------------------------------------------------------------
/truffle_test/app/stylesheets/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin-left: 25%;
3 | margin-right: 25%;
4 | margin-top: 10%;
5 | font-family: "Open Sans", sans-serif;
6 | }
7 |
8 | label {
9 | display: inline-block;
10 | width: 100px;
11 | }
12 |
13 | input {
14 | width: 500px;
15 | padding: 5px;
16 | font-size: 16px;
17 | }
18 |
19 | button {
20 | font-size: 16px;
21 | padding: 5px;
22 | }
23 |
24 | h1, h2 {
25 | display: inline-block;
26 | vertical-align: middle;
27 | margin-top: 0px;
28 | margin-bottom: 10px;
29 | }
30 |
31 | h2 {
32 | color: #AAA;
33 | font-size: 32px;
34 | }
35 |
36 | h3 {
37 | font-weight: normal;
38 | color: #AAA;
39 | font-size: 24px;
40 | }
41 |
42 | .black {
43 | color: black;
44 | }
45 |
46 | #balance {
47 | color: black;
48 | }
49 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/client/main.js:
--------------------------------------------------------------------------------
1 | import { Template } from 'meteor/templating';
2 | import { ReactiveVar } from 'meteor/reactive-var';
3 |
4 | import './main.html';
5 |
6 | Template.hello.onCreated(function helloOnCreated() {
7 | // counter starts at 0
8 | this.counter = new ReactiveVar(0);
9 | });
10 |
11 | Template.hello.helpers({
12 | counter() {
13 | return Template.instance().counter.get();
14 | },
15 | });
16 |
17 | Template.hello.events({
18 | 'click button'(event, instance) {
19 | // increment the counter when button is clicked
20 | instance.counter.set(instance.counter.get() + 1);
21 | },
22 | });
23 |
24 | Template.blockInfo.onCreated(function blockInfoOnCreated(){
25 | EthBlocks.init();
26 | });
27 |
28 | Template.blockInfo.helpers({
29 | currentBlock(){
30 | return EthBlocks.latest.number;
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/js/express-example.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var app = express();
3 | var Web3 = require('web3');
4 | var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
5 | var abi = [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"type":"constructor"}];
6 | var OneValueContract = web3.eth.contract(abi);
7 | var contractAddress = '0x2c8d5011127c5c38cae75f4c63b19e71a644562f';
8 | var oneValue = OneValueContract.at(contractAddress);
9 |
10 | app.get('/', function (req, res) {
11 | res.send(
12 | 'OneValue Instance: ' + contractAddress + "\n" +
13 | 'Value: '+ oneValue.getValue() + "\n");
14 | });
15 |
16 | app.listen(3000)
17 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/client/main.html:
--------------------------------------------------------------------------------
1 |
2 | myDapp
3 |
4 |
5 |
6 | Welcome to Meteor!
7 |
8 | {{> blockInfo}}
9 |
10 | {{> hello}}
11 | {{> info}}
12 |
13 |
14 |
15 |
16 | You've pressed the button {{counter}} times.
17 |
18 |
19 |
20 | Learn Meteor!
21 |
27 |
28 |
29 |
30 | Block height: {{currentBlock}}
31 |
32 |
--------------------------------------------------------------------------------
/js/update-contract-test.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
3 | var abi = [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"type":"constructor"}];
4 | var OneValueContract = web3.eth.contract(abi);
5 | var contractAddress = '0xd34d02bd80b7ad234305e734bd229746e5fe204e';
6 | var oneValue = OneValueContract.at(contractAddress);
7 |
8 | var addr = web3.eth.accounts[0];
9 | web3.personal.unlockAccount(addr, 'test1234', function(e, r){
10 | oneValue.setValue.sendTransaction(1234, {from: addr}, function(error, txid){
11 | console.log("Error: ", e);
12 | console.log("Txid: ", txid);
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/slides/0_Agenda_03232017.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Ethereum Smart Contract
4 | ## Yu-Te Lin
5 |
6 | ---
7 | ## About me
8 | - VP of Engineering, Amis
9 | - Director of Engineering, MaiCoin
10 | - Manager, HTC
11 | - Co-founder, Everyday.me (Y-Combinator backed)
12 | - Engineer, Oracle/Dell (Wyse)
13 | - MS Stanford, BS NCCU
14 |
15 | ---
16 |
17 | ## 以太坊開發環境及工具介紹
18 | - Ethereum and Smart contract
19 | - Wallet GUI: Mist, MetaMask
20 | - Command line tools: geth, solc
21 | - Contract deployment
22 | ---
23 |
24 | ## 以太坊智能合約開發
25 | - 程式設計
26 | - 資訊安全
27 | - 設計模式
28 | - 測試
29 | ---
30 |
31 | ## Dapps 開發
32 | - Dapp 範例 - FlightDelay
33 | - Web3 JavaScript Ðapp API
34 | - 開發工具 - Meteor
35 |
36 | ---
37 |
38 | ## Github
39 | - Github: https://github.com/amisamity/contract-training
40 |
41 | 
42 |
--------------------------------------------------------------------------------
/slides/1_Blockchain_Recap_0323.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Blockchain FAQ
4 |
5 | ---
6 |
7 | ## 什麼是區塊鏈?
8 | - 可看成去中心化資料庫
9 | - 所有區塊鏈網路上節點共同維護一公開帳本(以比特幣為例)
10 | - 資料以一個個區塊方式連結,而串成一個區塊鏈
11 |
12 | ---
13 |
14 | ## 什麼是去中心化?
15 | - 相對於中心化,例如上市證券交易必須透過證交所
16 | - 任何節點都可以成為可靠的資料來源
17 |
18 | ---
19 |
20 | ## 什麼是共識演算法?
21 | - 產生區塊的方式
22 | - 比特幣和以太幣網路都是用工作量證明(Proof of Work/PoW)
23 |
24 | ---
25 |
26 | ## 什麼是挖礦,為什麼要挖礦?
27 | - 工作量證明中,必須算出一個nonce值用以產生合法的區塊,算出這個nonce來得到獎勵的過程就要做挖礦 (mining)
28 |
29 | ---
30 |
31 | ## 什麼是節點?
32 | - 利用 p2p 方式連上區塊鏈網路即成為節點
33 | - 在比特幣網路中可執行 `bitcoind` 程式
34 | - 在以太幣網路中可執行 `geth` 程式
35 |
36 | ---
37 |
38 | ## 什麼是公有鏈,私有鏈,Mainnet,Testnet?
39 | - 公有鏈是大家都可以連上的區塊鏈網路
40 | - Mainnet 等於是公有鏈上的正式環境,Testnet 等於是公有鏈上的測試環境
41 | - 私有鏈可以是跑在私有網路的區塊鏈網路,或是需要特定權限的節點才能加入的區塊鏈網路
42 |
43 | ---
44 |
45 | ## 什麼是 Ethereum Virtual Machine (EVM)?
46 | - EVM 是以太坊實現 Blockchain 2.0 的主要元件,它可以用來執行智能合約編譯後的Byte code,並確保不同電腦架構下的節點在相同的輸入下可以有相同的輸出
47 |
--------------------------------------------------------------------------------
/truffle_test/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MetaCoin - Default Truffle App
5 |
6 |
7 |
8 |
9 |
10 | MetaCoin
11 | Example Truffle Dapp
12 | You have META
13 |
14 |
15 | Send
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/slides/0_Agenda_03172017.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Ethereum API and Ðapp
4 | ## Yu-Te Lin
5 |
6 | ---
7 | ## About me
8 |
9 | - VP of Engineering, Amis
10 |
11 | - Director of Engineering, MaiCoin
12 |
13 | - Manager, HTC
14 |
15 | - Co-founder, Everyday.me (Y-Combinator backed)
16 |
17 | - Engineer, Oracle/Dell (Wyse)
18 |
19 | - MSCS Stanford, BSCS NCCU
20 |
21 | ---
22 |
23 | ## 以太坊開發環境及工具介紹
24 |
25 | - Ethereum and Smart contract
26 |
27 | - Wallet GUI: Mist
28 |
29 | - Command line tools: geth, solc
30 |
31 | - Contract editors: Atom, Sublime text, Visual Studio, Remix IDE
32 |
33 | - Libraries and Development tools: web3, testrpc, truffle
34 |
35 | - Contract deployment
36 |
37 | ---
38 |
39 | ## Ðapps 開發
40 |
41 | - Web3 JavaScript Ðapp API
42 |
43 | - 開發工具 - Meteor
44 |
45 | - 環境連結
46 |
47 | ---
48 |
49 | ## Github
50 | - Github: https://github.com/amisamity/contract-training
51 |
52 | 
53 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
18 | .grunt
19 |
20 | # node-waf configuration
21 | .lock-wscript
22 |
23 | # Compiled binary addons (http://nodejs.org/api/addons.html)
24 | build/Release
25 |
26 | # Dependency directory
27 | node_modules
28 |
29 | # Optional npm cache directory
30 | .npm
31 |
32 | # Optional REPL history
33 | .node_repl_history
34 |
35 | # bundler state
36 | .bundle
37 | **/vendor/bundle/
38 | **/vendor/ruby/
39 |
40 | # application
41 | services/config/service.json
42 |
43 | # JetBrains
44 | .idea
45 |
46 | # Node runtime stuff
47 | **/.node-xmlhttprequest*
48 |
49 | # NO vendor src
50 | #vendor/src/
51 |
52 | # Truffle build
53 | truffle_test/build
54 |
55 | # node_modules
56 | node_modules
57 |
--------------------------------------------------------------------------------
/contracts/build/remote-purchase.sol:Purchase.abi:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[],"name":"seller","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"abort","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"buyer","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"confirmReceived","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"state","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"confirmPurchase","outputs":[],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"payable":false,"type":"fallback"},{"anonymous":false,"inputs":[],"name":"aborted","type":"event"},{"anonymous":false,"inputs":[],"name":"purchaseConfirmed","type":"event"},{"anonymous":false,"inputs":[],"name":"itemReceived","type":"event"}]
--------------------------------------------------------------------------------
/truffle_test/contracts/MetaCoin.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.4;
2 |
3 | import "./ConvertLib.sol";
4 |
5 | // This is just a simple example of a coin-like contract.
6 | // It is not standards compatible and cannot be expected to talk to other
7 | // coin/token contracts. If you want to create a standards-compliant
8 | // token, see: https://github.com/ConsenSys/Tokens. Cheers!
9 |
10 | contract MetaCoin {
11 | mapping (address => uint) balances;
12 |
13 | event Transfer(address indexed _from, address indexed _to, uint256 _value);
14 |
15 | function MetaCoin() {
16 | balances[tx.origin] = 10000;
17 | }
18 |
19 | function sendCoin(address receiver, uint amount) returns(bool sufficient) {
20 | if (balances[msg.sender] < amount) return false;
21 | balances[msg.sender] -= amount;
22 | balances[receiver] += amount;
23 | Transfer(msg.sender, receiver, amount);
24 | return true;
25 | }
26 |
27 | function getBalanceInEth(address addr) returns(uint){
28 | return ConvertLib.convert(getBalance(addr),2);
29 | }
30 |
31 | function getBalance(address addr) returns(uint) {
32 | return balances[addr];
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/contracts/build/Set.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b5b61022f8061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063483b8a14146100515780636ce8e0811461008a578063831cb739146100c3575bfe5b61007060048080359060200190919080359060200190919050506100fc565b604051808215151515815260200191505060405180910390f35b6100a96004808035906020019091908035906020019091905050610169565b604051808215151515815260200191505060405180910390f35b6100e26004808035906020019091908035906020019091905050610197565b604051808215151515815260200191505060405180910390f35b600082600001600083815260200190815260200160002060009054906101000a900460ff1615156101305760009050610163565b600083600001600084815260200190815260200160002060006101000a81548160ff021916908315150217905550600190505b92915050565b600082600001600083815260200190815260200160002060009054906101000a900460ff1690505b92915050565b600082600001600083815260200190815260200160002060009054906101000a900460ff16156101ca57600090506101fd565b600183600001600084815260200190815260200160002060006101000a81548160ff021916908315150217905550600190505b929150505600a165627a7a7230582052a1e41ccda643bd44d932d28bfefdd399a92866343498c2cffe078140c09f910029
--------------------------------------------------------------------------------
/contracts/WithdrawalContract.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.0;
2 |
3 | contract WithdrawalContract {
4 | address public richest;
5 | uint public mostSent;
6 |
7 | mapping (address => uint) pendingWithdrawals;
8 |
9 | function WithdrawalContract() payable {
10 | richest = msg.sender;
11 | mostSent = msg.value;
12 | }
13 |
14 | function becomeRichest() payable returns (bool) {
15 | if (msg.value > mostSent) {
16 | pendingWithdrawals[richest] += msg.value;
17 | richest = msg.sender;
18 | mostSent = msg.value;
19 | return true;
20 | } else {
21 | return false;
22 | }
23 | }
24 |
25 | function withdraw() returns (bool) {
26 | uint amount = pendingWithdrawals[msg.sender];
27 | // Remember to zero the pending refund before
28 | // sending to prevent re-entrancy attacks
29 | pendingWithdrawals[msg.sender] = 0;
30 | if (msg.sender.send(amount)) {
31 | return true;
32 | } else {
33 | pendingWithdrawals[msg.sender] = amount;
34 | return false;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/contracts/lib-set.sol:
--------------------------------------------------------------------------------
1 | library Set {
2 | // We define a new struct datatype that will be used to
3 | // hold its data in the calling contract.
4 | struct Data { mapping(uint => bool) flags; }
5 |
6 | // Note that the first parameter is of type "storage
7 | // reference" and thus only its storage address and not
8 | // its contents is passed as part of the call. This is a
9 | // special feature of library functions. It is idiomatic
10 | // to call the first parameter 'self', if the function can
11 | // be seen as a method of that object.
12 | function insert(Data storage self, uint value)
13 | returns (bool)
14 | {
15 | if (self.flags[value])
16 | return false; // already there
17 | self.flags[value] = true;
18 | return true;
19 | }
20 |
21 | function remove(Data storage self, uint value)
22 | returns (bool)
23 | {
24 | if (!self.flags[value])
25 | return false; // not there
26 | self.flags[value] = false;
27 | return true;
28 | }
29 |
30 | function contains(Data storage self, uint value)
31 | returns (bool)
32 | {
33 | return self.flags[value];
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/contracts/build/Ballot.sol:Ballot.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[{"name":"proposal","type":"uint256"}],"name":"vote","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"proposals","outputs":[{"name":"name","type":"bytes32"},{"name":"voteCount","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"chairperson","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"}],"name":"delegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"winningProposal","outputs":[{"name":"winningProposal","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"voter","type":"address"}],"name":"giveRightToVote","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"voters","outputs":[{"name":"weight","type":"uint256"},{"name":"voted","type":"bool"},{"name":"delegate","type":"address"},{"name":"vote","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"proposalNames","type":"bytes32[]"}],"payable":false,"type":"constructor"}]
--------------------------------------------------------------------------------
/slides/7_References.md:
--------------------------------------------------------------------------------
1 | ## References:
2 | - Ethereum Frontier Guide https://www.gitbook.com/book/ethereum/frontier-guide/
3 | - Solidity http://solidity.readthedocs.io/en/latest/
4 | - Go-ethereum wiki: https://github.com/ethereum/go-ethereum/wiki
5 | - JavaScript console: https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console
6 | - ContractWallet https://github.com/ethereum/meteor-dapp-wallet/blob/develop/Wallet.sol
7 | - Sample contracts https://github.com/fivedogit/solidity-baby-steps/tree/master/contracts/
8 | - Sample ÐApps https://github.com/ethereum/dapp-bin
9 | - Vitalik Buterin. Ethereum: A Next-Generation Cryptocurrency and Decentralized Application Platform. https://bitcoinmagazine.com/articles/ethereum-next-generation-cryptocurrency-decentralized-application-platform-1390528211
10 | - Taylor Gerring. Blockchain 101 https://blockchainconsulting.expert/slides/blockchains101.pdf
11 | - Bitcoin wiki colored coin https://en.bitcoin.it/wiki/Colored_Coins
12 | - Bitcoin script https://en.bitcoin.it/wiki/Script
13 | - Ethereum white paper: https://github.com/ethereum/wiki/wiki/White-Paper
14 | - Vitalik Buterin. Thoughts on UTXOs https://medium.com/@ConsenSys/thoughts-on-utxo-by-vitalik-buterin-2bb782c67e53#.99hm4kf6x
15 |
--------------------------------------------------------------------------------
/slides/0_Agenda_03102017.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Smart Contract Bootcamp
4 | ## Yu-Te Lin
5 |
6 | ---
7 | ## About me
8 | - VP of Engineering, __Amis__
9 |
10 | - Director of Engineering, __MaiCoin__
11 |
12 | - Manager, __HTC__
13 |
14 | - Co-founder, __Everyday.me__ (Y-Combinator backed)
15 |
16 | - Engineer, __Oracle__/__Dell__ (__Wyse__)
17 |
18 | - MSCS __Stanford__, BSCS __NCCU__
19 |
20 | ---
21 |
22 | ## 以太坊開發環境及工具介紹
23 |
24 | - Ethereum and Smart contract
25 |
26 | - Wallet GUI: Mist
27 |
28 | - Command line tools: geth, solc
29 |
30 | - Contract editors: atom, sublime text, visual studio.
31 |
32 | - Libraries and Development tools: web3, testrpc, truffle.
33 |
34 | - Contract deployment
35 |
36 | ---
37 |
38 | ## 以太坊智能合約開發
39 |
40 | - 程式設計
41 |
42 | - 資訊安全
43 |
44 | - 設計模式
45 |
46 | - 測試
47 |
48 | ---
49 |
50 | ## 保險智能合約範例
51 |
52 | - FlightDelay 介紹
53 |
54 | - FlightDelay 操作 - MetaMask / Mist
55 |
56 | - FlightDelay 程式碼導讀
57 |
58 | ---
59 |
60 | ## Dapps 開發
61 |
62 | - Web3 JavaScript Ðapp API
63 |
64 | - 開發工具 - Meteor
65 |
66 | - 環境連結
67 |
68 | ---
69 |
70 | ## Github
71 | - Github: https://github.com/amisamity/contract-training
72 |
73 | 
74 |
--------------------------------------------------------------------------------
/contracts/build/SimpleAuction.sol:SimpleAuction.abi:
--------------------------------------------------------------------------------
1 | [{"constant":false,"inputs":[],"name":"bid","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"auctionEnd","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"beneficiary","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"auctionStart","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"highestBidder","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"biddingTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"highestBid","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"_biddingTime","type":"uint256"},{"name":"_beneficiary","type":"address"}],"payable":false,"type":"constructor"},{"payable":false,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"bidder","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"HighestBidIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"winner","type":"address"},{"indexed":false,"name":"amount","type":"uint256"}],"name":"AuctionEnded","type":"event"}]
--------------------------------------------------------------------------------
/README.MD:
--------------------------------------------------------------------------------
1 | # Contract Training
2 | Repo for smart contract (solidity) training.
3 |
4 | ## Link
5 | 
6 |
7 | ## Slides
8 | - [0. Agenda](https://amisamity.github.io/contract-training/slides/0_Agenda.md.html)
9 | - [1. Blockchain Basics](https://amisamity.github.io/contract-training/slides/1_Blockchain_Basics.md.html)
10 | - [2. Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools.md.html)
11 | - [3. Smart Contract and Solidity](https://amisamity.github.io/contract-training/slides/3_Smart_Contract_Solidity_Quick_Start.md.html)
12 | - [4. Solidity Security](https://amisamity.github.io/contract-training/slides/4_Solidity_Security.md.html)
13 | - [5. Solidity Patterns](https://amisamity.github.io/contract-training/slides/5_Solidity_Patterns.md.html)
14 | - [6. Solidity Testing](https://amisamity.github.io/contract-training/slides/6_Solidity_Testing.md.html)
15 | - [7. Ðapps Development](https://amisamity.github.io/contract-training/slides/9_Dapps_Development.md.html)
16 | - [8. Insurance Example](https://amisamity.github.io/contract-training/slides/8_Insurance_Examples.md.html)
17 | - [9. Web3 JavaScript Ðapp API](https://amisamity.github.io/contract-training/slides/10_Web3_JavaScript.md.html)
18 | - [10. References](https://amisamity.github.io/contract-training/slides/7_References.md.html)
19 |
20 | ## 課程投影片
21 | - [課程投影片](LECTURES.MD)
22 |
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.0.4 # Packages every Meteor app needs to have
8 | mobile-experience@1.0.4 # Packages for a great mobile UX
9 | mongo@1.1.14 # The database Meteor supports right now
10 | blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
11 | reactive-var@1.0.11 # Reactive variable for tracker
12 | jquery@1.11.10 # Helpful client-side library
13 | tracker@1.1.1 # Meteor's client-side reactive programming library
14 |
15 | standard-minifier-css@1.3.2 # CSS minifier run for production mode
16 | standard-minifier-js@1.2.1 # JS minifier run for production mode
17 | es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
18 | ecmascript@0.6.1 # Enable ECMAScript2015+ syntax in app code
19 | shell-server@0.2.1 # Server-side component of the `meteor shell` command
20 |
21 | autopublish@1.0.7 # Publish all data to the clients (for prototyping)
22 | insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
23 | ethereum:web3
24 | ethereum:dapp-styles
25 | ethereum:tools
26 | ethereum:elements
27 | ethereum:accounts
28 | ethereum:blocks
29 | frozeman:template-var
30 | frozeman:persistent-minimongo2
31 | less
32 |
--------------------------------------------------------------------------------
/contracts/CrowdFunding.sol:
--------------------------------------------------------------------------------
1 | contract CrowdFunding {
2 | // Defines a new type with two fields.
3 | struct Funder {
4 | address addr;
5 | uint amount;
6 | }
7 |
8 | struct Campaign {
9 | address beneficiary;
10 | uint fundingGoal;
11 | uint numFunders;
12 | uint amount;
13 | mapping (uint => Funder) funders;
14 | }
15 |
16 | uint numCampaigns;
17 | mapping (uint => Campaign) campaigns;
18 |
19 | function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
20 | campaignID = numCampaigns++; // campaignID is return variable
21 | // Creates new struct and saves in storage. We leave out the mapping type.
22 | campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
23 | }
24 |
25 | function contribute(uint campaignID) {
26 | Campaign c = campaigns[campaignID];
27 | // Creates a new temporary memory struct, initialised with the given values
28 | // and copies it over to storage.
29 | // Note that you can also use Funder(msg.sender, msg.value) to initialise.
30 | c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
31 | c.amount += msg.value;
32 | }
33 |
34 | function checkGoalReached(uint campaignID) returns (bool reached) {
35 | Campaign c = campaigns[campaignID];
36 | if (c.amount < c.fundingGoal)
37 | return false;
38 | if (!c.beneficiary.send(c.amount))
39 | throw;
40 | c.amount = 0;
41 | return true;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base@1.0.4 # Packages every Meteor app needs to have
8 | mobile-experience@1.0.4 # Packages for a great mobile UX
9 | mongo@1.1.14 # The database Meteor supports right now
10 | blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
11 | reactive-var@1.0.11 # Reactive variable for tracker
12 | jquery@1.11.10 # Helpful client-side library
13 | tracker@1.1.1 # Meteor's client-side reactive programming library
14 |
15 | standard-minifier-css@1.3.2 # CSS minifier run for production mode
16 | standard-minifier-js@1.2.1 # JS minifier run for production mode
17 | es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
18 | ecmascript@0.6.1 # Enable ECMAScript2015+ syntax in app code
19 | shell-server@0.2.1 # Server-side component of the `meteor shell` command
20 |
21 | autopublish@1.0.7 # Publish all data to the clients (for prototyping)
22 | insecure@1.0.7 # Allow all DB writes from clients (for prototyping)
23 | ethereum:web3
24 | ethereum:dapp-styles
25 | ethereum:tools
26 | ethereum:elements
27 | ethereum:accounts
28 | ethereum:blocks
29 | frozeman:template-var
30 | frozeman:persistent-minimongo2
31 | less
32 | erasaur:meteor-lodash
33 |
--------------------------------------------------------------------------------
/js/deploy-client-receipt.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var TestRPC = require("ethereumjs-testrpc");
3 | // var web3 = new Web3(TestRPC.provider());
4 | var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
5 |
6 | var abi = [{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"deposit","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_id","type":"bytes32"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Deposit","type":"event"}];
7 | var evmCode = "0x6060604052341561000c57fe5b5b60de8061001b6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b214faa514603a575bfe5b3415604157fe5b6059600480803560001916906020019091905050605b565b005b80600019163373ffffffffffffffffffffffffffffffffffffffff167f19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f346040518082815260200191505060405180910390a35b505600a165627a7a72305820528673a40eadb3be75f92326e0664ef276b182a65164702f0d7c104f291b9c680029";
8 |
9 | var ClientReceiptContract = web3.eth.contract(abi);
10 | var callback = function(e, contract){
11 | if(e == null) {
12 | console.log("Contract transaction: TransactionHash: " + contract.transactionHash);
13 | if(typeof contract.address !== 'undefined'){
14 | console.log("Contract mined! Address: " + contract.address);
15 | }
16 | } else {
17 | console.log(e);
18 | }
19 | };
20 | var addr = web3.eth.accounts[0];
21 | web3.personal.unlockAccount(addr, 'test1234', function(e, r){
22 | if(e != null){
23 | console.log("Error:", e);
24 | }else {
25 | var oneValue = ClientReceiptContract.new({from:addr, data: evmCode, gas: 200000}, callback);
26 | }
27 | });
28 |
--------------------------------------------------------------------------------
/contracts/build/CrowdFunding.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b5b6103808061001c6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680635b2329d414610051578063c1cbbca714610089578063f7572cf3146100a9575bfe5b341561005957fe5b61006f60048080359060200190919050506100fc565b604051808215151515815260200191505060405180910390f35b341561009157fe5b6100a760048080359060200190919050506101ae565b005b34156100b157fe5b6100e6600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610283565b6040518082815260200191505060405180910390f35b6000600060016000848152602001908152602001600020905080600101548160030154101561012e57600091506101a8565b8060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc82600301549081150290604051809050600060405180830381858888f19350505050151561019957610000565b60008160030181905550600191505b50919050565b60006001600083815260200190815260200160002090506040604051908101604052803373ffffffffffffffffffffffffffffffffffffffff1681526020013481525081600401600083600201600081548092919060010191905055815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050503481600301600082825401925050819055505b5050565b6000600060008154809291906001019190505590506080604051908101604052808473ffffffffffffffffffffffffffffffffffffffff1681526020018381526020016000815260200160008152506001600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015560408201518160020155606082015181600301559050505b929150505600a165627a7a723058201e64ca853a8799b9fefd264986797447d85fc0b9c9b57ee7be1b94e19d16783b0029
--------------------------------------------------------------------------------
/js/deploy-contract-test.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var TestRPC = require("ethereumjs-testrpc");
3 | // var web3 = new Web3(TestRPC.provider());
4 | var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
5 |
6 | var abi = [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"type":"constructor"}]
7 | var evmCode = "0x606060405260405160208060cf833981016040528080519060200190919050505b806000600050819055505b5060978060386000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063209652551460415780635524107714606257603f565b005b604c60048050506078565b6040518082815260200191505060405180910390f35b607660048080359060200190919050506089565b005b600060006000505490506086565b90565b806000600050819055505b5056";
8 |
9 | var OneValueContract = web3.eth.contract(abi);
10 | var callback = function(e, contract){
11 | if(e == null) {
12 | console.log("Contract transaction: TransactionHash: " + contract.transactionHash);
13 | if(typeof contract.address !== 'undefined'){
14 | console.log("Contract mined! Address: " + contract.address);
15 | var oneValueInst = OneValueContract.at(contract.address);
16 | console.log("Value:", parseInt(oneValueInst.getValue()));
17 | }
18 | } else {
19 | console.log(e);
20 | }
21 | };
22 | var initValue = 123;
23 | var addr = web3.eth.accounts[0];
24 | web3.personal.unlockAccount(addr, 'test1234', function(e, r){
25 | if(e != null){
26 | console.log("Error:", e);
27 | }else {
28 | var oneValue = OneValueContract.new(initValue, {from:addr, data: evmCode, gas: 200000}, callback);
29 | }
30 | });
31 |
--------------------------------------------------------------------------------
/truffle_test/app/javascripts/app.js:
--------------------------------------------------------------------------------
1 | var accounts;
2 | var account;
3 | var balance;
4 |
5 | function setStatus(message) {
6 | var status = document.getElementById("status");
7 | status.innerHTML = message;
8 | };
9 |
10 | function refreshBalance() {
11 | return MetaCoin.deployed().then(function(meta) {
12 | return meta.getBalance.call(account);
13 | }).then(function(outCoinBalance) {
14 | var metaCoinBalance = outCoinBalance.toNumber();
15 | var balance_element = document.getElementById("balance");
16 | balance_element.innerHTML = metaCoinBalance.valueOf();
17 | });
18 | };
19 |
20 | function sendCoin() {
21 | var meta;
22 | var amount = parseInt(document.getElementById("amount").value);
23 | var receiver = document.getElementById("receiver").value;
24 |
25 | return MetaCoin.deployed().then(function(instance) {
26 | meta = instance;
27 | setStatus("Initiating transaction... (please wait)");
28 | return meta.sendCoin(receiver, amount, {from: account});
29 | }).then(function(tx) {
30 | console.log(tx, tx.tx);
31 | setStatus("Transaction complete! txid: " + tx.tx);
32 | return refreshBalance();
33 | }).catch(function(e){
34 | console.log(e);
35 | setStatus("Error sending coin; see log.");
36 | });
37 | };
38 |
39 | window.onload = function() {
40 | web3.eth.getAccounts(function(err, accs) {
41 | if (err != null) {
42 | alert("There was an error fetching your accounts.");
43 | return;
44 | }
45 |
46 | if (accs.length == 0) {
47 | alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
48 | return;
49 | }
50 |
51 | accounts = accs;
52 | account = accounts[0];
53 |
54 | refreshBalance();
55 | });
56 | }
57 |
--------------------------------------------------------------------------------
/js/deploy-contract-testrpc.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var TestRPC = require("ethereumjs-testrpc");
3 | var web3 = new Web3(TestRPC.provider());
4 | // var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8547"));
5 |
6 | var abi = [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"type":"constructor"}]
7 | var evmCode = "0x606060405260405160208060cf833981016040528080519060200190919050505b806000600050819055505b5060978060386000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063209652551460415780635524107714606257603f565b005b604c60048050506078565b6040518082815260200191505060405180910390f35b607660048080359060200190919050506089565b005b600060006000505490506086565b90565b806000600050819055505b5056";
8 |
9 | var OneValueContract = web3.eth.contract(abi);
10 | var callback = function(e, contract){
11 | if(e == null) {
12 | console.log("Contract transaction: TransactionHash: " + contract.transactionHash);
13 | if(typeof contract.address !== 'undefined'){
14 | console.log("Contract mined! Address: " + contract.address);
15 | var oneValueInst = OneValueContract.at(contract.address);
16 | oneValueInst.getValue(function(e, r){
17 | console.log("Value:", parseInt(r));
18 | process.exit(0);
19 | });
20 | }
21 | } else {
22 | console.log(e);
23 | }
24 | };
25 | var initValue = 123;
26 | web3.eth.getAccounts(function(e, accts){
27 | var addr = accts[0];
28 | //Unlock account
29 | var oneValue = OneValueContract.new(initValue, {from:addr, data: evmCode, gas: 200000}, callback);
30 | });
31 |
--------------------------------------------------------------------------------
/js/watch-client-receipt.js:
--------------------------------------------------------------------------------
1 | var Web3 = require('web3');
2 | var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
3 | var abi = [{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"deposit","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_id","type":"bytes32"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Deposit","type":"event"}];
4 | var ClientReceipt = web3.eth.contract(abi);
5 | var clientReceipt = ClientReceipt.at("0x32cb389a408cb79ab1e2d23bf1a454f4420f80b2");
6 |
7 | var event = clientReceipt.Deposit();
8 |
9 | var eventPrint = function(result){
10 | if(result.event == 'Deposit') {
11 | console.log("Deposit " + result.args._value +
12 | " from " + result.args._from +
13 | " id " + result.args._id);
14 | }
15 | }
16 |
17 | // watch for changes
18 | event.watch(function(error, result){
19 | // result will contain various information
20 | // including the argumets given to the Deposit
21 | // call.
22 | console.log("Received event from all filter");
23 | if (!error) {
24 | eventPrint(result);
25 | }
26 | });
27 |
28 | // Or pass a callback to start watching immediately
29 | var event = clientReceipt.Deposit(function(error, result) {
30 | console.log("Received event from 'Deposit' filter");
31 | if (!error) {
32 | eventPrint(result);
33 | }
34 | process.exit(0);
35 | });
36 |
37 | //Create transaction
38 | var addr = web3.eth.accounts[0];
39 | web3.personal.unlockAccount(addr, 'test1234', function(e, r){
40 | if(e != null){
41 | console.log("Error:", e);
42 | }else {
43 | var txid = clientReceipt.deposit.sendTransaction(123, {from:addr, gas: 50000});
44 | console.log("txid:", txid);
45 | }
46 | });
47 |
--------------------------------------------------------------------------------
/contracts/build/WithdrawalContract.bin:
--------------------------------------------------------------------------------
1 | 60606040525b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550346001819055505b5b6103748061005e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806302e26c381461005c5780633ccfd60b146100ae5780636886bf1c146100d857806369934ee7146100fe575bfe5b341561006457fe5b61006c610120565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100b657fe5b6100be610146565b604051808215151515815260200191505060405180910390f35b34156100e057fe5b6100e8610269565b6040518082815260200191505060405180910390f35b61010661026f565b604051808215151515815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050156102175760019150610265565b80600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555060009150610265565b5b5090565b60015481565b600060015434111561033b573460026000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555033600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503460018190555060019050610345565b60009050610345565b5b905600a165627a7a72305820deddf4f89657e133f48fe90426f404ad49a1c653421df7c7c407c5cb3f0592f90029
--------------------------------------------------------------------------------
/js/tests/one-value-tests.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | describe('OneValueContract', function(){
4 | var assert = require('assert');
5 | var Web3 = require('web3');
6 | var web3 = new Web3();
7 | var TestRPC = require("ethereumjs-testrpc");
8 | var primaryAddress;
9 | var oneValue;
10 | var initValue = 123;
11 | var gas = 200000;
12 | web3.setProvider(TestRPC.provider());
13 | this.timeout(60000); //1 minute
14 |
15 | // 1. Deploy OneValueContract
16 | before(function(done) {
17 | var tool = require('./tools');
18 | var abi = tool.loadAbi('OneValue');
19 | var bin = tool.loadBin('OneValue');
20 | var OneValueContract = web3.eth.contract(abi);
21 | //2. Get accounts
22 | web3.eth.getAccounts(function(error, result){
23 | //3. Deploy
24 | primaryAddress = result[0]; //Blockchain Admin
25 | oneValue = OneValueContract.new(initValue, {from:primaryAddress, data: bin, gas: gas}, function(error, contract){
26 | assert.equal(error, null);
27 | if(error == null && contract.address != null){
28 | //Mined
29 | done();
30 | }
31 | });
32 | });
33 | });
34 |
35 | it("initValue should be 123", function(done){
36 | oneValue.getValue(function(error, result){
37 | assert.equal(error, null);
38 | assert.equal(initValue, result);
39 | done();
40 | });
41 | });
42 |
43 | it("setValue should store value", function(done){
44 | var newValue = 456;
45 | oneValue.setValue.sendTransaction(456, {from:primaryAddress, gas: gas}, function(error, txid){
46 | oneValue.getValue(function(error, result){
47 | assert.equal(error, null);
48 | assert.equal(newValue, result);
49 | done();
50 | });
51 | });
52 | });
53 | });
54 |
--------------------------------------------------------------------------------
/contracts/build/BlindAuction.sol:BlindAuction.abi:
--------------------------------------------------------------------------------
1 | [{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"bids","outputs":[{"name":"blindedBid","type":"bytes32"},{"name":"deposit","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"ended","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"auctionEnd","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"beneficiary","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"withdraw","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"biddingEnd","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"auctionStart","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_values","type":"uint256[]"},{"name":"_fake","type":"bool[]"},{"name":"_secret","type":"bytes32[]"}],"name":"reveal","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"highestBidder","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_blindedBid","type":"bytes32"}],"name":"bid","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"revealEnd","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"highestBid","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"_biddingTime","type":"uint256"},{"name":"_revealTime","type":"uint256"},{"name":"_beneficiary","type":"address"}],"payable":false,"type":"constructor"},{"payable":false,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"winner","type":"address"},{"indexed":false,"name":"highestBid","type":"uint256"}],"name":"AuctionEnded","type":"event"}]
--------------------------------------------------------------------------------
/contracts/build/named.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b60405160208061042d833981016040528080519060200190919050505b60005b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b73d5f9d8d94886e70b06e474c3fb14fd43e2f2397090508073ffffffffffffffffffffffffffffffffffffffff16630a874df660016000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15156100fa57fe5b60325a03f1151561010757fe5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff1663e1fa8e84836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050600060405180830381600087803b151561018357fe5b60325a03f1151561019057fe5b5050505b50505b610287806101a66000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806341c0e1b51461003b575bfe5b341561004357fe5b61004b61004d565b005b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156101c35773d5f9d8d94886e70b06e474c3fb14fd43e2f2397090508073ffffffffffffffffffffffffffffffffffffffff16630a874df660016000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b151561013157fe5b60325a03f1151561013e57fe5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff1663e79a198f6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050600060405180830381600087803b15156101aa57fe5b60325a03f115156101b757fe5b5050506101c26101c7565b5b5b50565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561025857600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b5600a165627a7a72305820bd022a289f0a2699dfa1127fdfccf8c8d3a5c253b44410bd6c30b3097963abae0029
--------------------------------------------------------------------------------
/dapp_example/myDapp/.meteor/versions:
--------------------------------------------------------------------------------
1 | 3stack:bignumber@2.0.0
2 | alexvandesande:identicon@2.0.2
3 | allow-deny@1.0.5
4 | amplify@1.0.0
5 | autopublish@1.0.7
6 | autoupdate@1.2.11
7 | babel-compiler@6.14.1
8 | babel-runtime@1.0.1
9 | base64@1.0.10
10 | binary-heap@1.0.10
11 | blaze@2.3.0
12 | blaze-html-templates@1.1.0
13 | blaze-tools@1.0.10
14 | boilerplate-generator@1.0.11
15 | caching-compiler@1.1.9
16 | caching-html-compiler@1.1.0
17 | callback-hook@1.0.10
18 | check@1.2.4
19 | ddp@1.2.5
20 | ddp-client@1.2.9
21 | ddp-common@1.2.8
22 | ddp-server@1.2.10
23 | deps@1.0.12
24 | diff-sequence@1.0.7
25 | ecmascript@0.6.3
26 | ecmascript-runtime@0.3.15
27 | ejson@1.0.13
28 | es5-shim@4.6.15
29 | ethereum:accounts@0.4.0
30 | ethereum:blocks@0.3.2
31 | ethereum:dapp-styles@0.5.8
32 | ethereum:elements@0.7.11
33 | ethereum:tools@0.6.0
34 | ethereum:web3@0.18.3
35 | fastclick@1.0.13
36 | frozeman:animation-helper@0.2.6
37 | frozeman:persistent-minimongo@0.1.8
38 | frozeman:persistent-minimongo2@0.3.4
39 | frozeman:storage@0.1.9
40 | frozeman:template-var@1.2.3
41 | geojson-utils@1.0.10
42 | hot-code-push@1.0.4
43 | html-tools@1.0.11
44 | htmljs@1.0.11
45 | http@1.1.8
46 | id-map@1.0.9
47 | insecure@1.0.7
48 | jquery@1.11.10
49 | launch-screen@1.0.12
50 | less@2.5.7
51 | livedata@1.0.18
52 | localstorage@1.0.12
53 | logging@1.1.17
54 | meteor@1.6.1
55 | meteor-base@1.0.4
56 | minifier-css@1.2.16
57 | minifier-js@1.2.17
58 | minimongo@1.0.20
59 | mobile-experience@1.0.4
60 | mobile-status-bar@1.0.14
61 | modules@0.7.9
62 | modules-runtime@0.7.9
63 | mongo@1.1.15
64 | mongo-id@1.0.6
65 | npm-mongo@2.2.16_1
66 | observe-sequence@1.0.15
67 | ordered-dict@1.0.9
68 | promise@0.8.8
69 | random@1.0.10
70 | reactive-var@1.0.11
71 | reload@1.1.11
72 | retry@1.0.9
73 | routepolicy@1.0.12
74 | shell-server@0.2.2
75 | spacebars@1.0.13
76 | spacebars-compiler@1.1.0
77 | standard-minifier-css@1.3.3
78 | standard-minifier-js@1.2.2
79 | standard-minifiers@1.0.6
80 | templating@1.3.0
81 | templating-compiler@1.3.0
82 | templating-runtime@1.3.0
83 | templating-tools@1.1.0
84 | tracker@1.1.2
85 | ui@1.0.12
86 | underscore@1.0.10
87 | url@1.0.11
88 | webapp@1.3.13
89 | webapp-hashing@1.0.9
90 |
--------------------------------------------------------------------------------
/contracts/build/AccessRestriction.bin:
--------------------------------------------------------------------------------
1 | 606060405233600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600155341561005157fe5b5b6103e2806100616000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630cb0c7f0146100675780631e9bf0da1461009d5780638da5cb5b146100af578063a6f9dae114610101578063d8270dce14610137575bfe5b341561006f57fe5b61009b600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061015d565b005b34156100a557fe5b6100ad610248565b005b34156100b757fe5b6100bf6102e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561010957fe5b610135600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190505061030c565b005b341561013f57fe5b6101476103b0565b6040518082815260200191505060405180910390f35b680ad78ebc5ac62000008034101561017457610000565b81600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060016000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161614156101fe576101ff565b5b80341115610243573373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051809050600060405180830381858888f19350505050505b5b5050565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156102a557610000565b62375f0060015401804210156102ba57610000565b600060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690555b5b505b50565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561036957610000565b81600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b5b5050565b600154815600a165627a7a7230582000e5323c38ec3a336c215628d2f399824dbe2c96e892d68175558701d1b35d700029
--------------------------------------------------------------------------------
/dapp_example/myDapp2/.meteor/versions:
--------------------------------------------------------------------------------
1 | 3stack:bignumber@2.0.0
2 | alexvandesande:identicon@2.0.2
3 | allow-deny@1.0.5
4 | amplify@1.0.0
5 | autopublish@1.0.7
6 | autoupdate@1.2.11
7 | babel-compiler@6.14.1
8 | babel-runtime@1.0.1
9 | base64@1.0.10
10 | binary-heap@1.0.10
11 | blaze@2.3.0
12 | blaze-html-templates@1.1.0
13 | blaze-tools@1.0.10
14 | boilerplate-generator@1.0.11
15 | caching-compiler@1.1.9
16 | caching-html-compiler@1.1.0
17 | callback-hook@1.0.10
18 | check@1.2.4
19 | ddp@1.2.5
20 | ddp-client@1.2.9
21 | ddp-common@1.2.8
22 | ddp-server@1.2.10
23 | deps@1.0.12
24 | diff-sequence@1.0.7
25 | ecmascript@0.6.3
26 | ecmascript-runtime@0.3.15
27 | ejson@1.0.13
28 | erasaur:meteor-lodash@4.0.0
29 | es5-shim@4.6.15
30 | ethereum:accounts@0.4.0
31 | ethereum:blocks@0.3.2
32 | ethereum:dapp-styles@0.5.8
33 | ethereum:elements@0.7.11
34 | ethereum:tools@0.6.0
35 | ethereum:web3@0.18.3
36 | fastclick@1.0.13
37 | frozeman:animation-helper@0.2.6
38 | frozeman:persistent-minimongo@0.1.8
39 | frozeman:persistent-minimongo2@0.3.4
40 | frozeman:storage@0.1.9
41 | frozeman:template-var@1.2.3
42 | geojson-utils@1.0.10
43 | hot-code-push@1.0.4
44 | html-tools@1.0.11
45 | htmljs@1.0.11
46 | http@1.1.8
47 | id-map@1.0.9
48 | insecure@1.0.7
49 | jquery@1.11.10
50 | launch-screen@1.0.12
51 | less@2.5.7
52 | livedata@1.0.18
53 | localstorage@1.0.12
54 | logging@1.1.17
55 | meteor@1.6.1
56 | meteor-base@1.0.4
57 | minifier-css@1.2.16
58 | minifier-js@1.2.17
59 | minimongo@1.0.20
60 | mobile-experience@1.0.4
61 | mobile-status-bar@1.0.14
62 | modules@0.7.9
63 | modules-runtime@0.7.9
64 | mongo@1.1.15
65 | mongo-id@1.0.6
66 | npm-mongo@2.2.16_1
67 | observe-sequence@1.0.15
68 | ordered-dict@1.0.9
69 | promise@0.8.8
70 | random@1.0.10
71 | reactive-var@1.0.11
72 | reload@1.1.11
73 | retry@1.0.9
74 | routepolicy@1.0.12
75 | shell-server@0.2.2
76 | spacebars@1.0.13
77 | spacebars-compiler@1.1.0
78 | standard-minifier-css@1.3.3
79 | standard-minifier-js@1.2.2
80 | standard-minifiers@1.0.6
81 | templating@1.3.0
82 | templating-compiler@1.3.0
83 | templating-runtime@1.3.0
84 | templating-tools@1.1.0
85 | tracker@1.1.2
86 | ui@1.0.12
87 | underscore@1.0.10
88 | url@1.0.11
89 | webapp@1.3.13
90 | webapp-hashing@1.0.9
91 |
--------------------------------------------------------------------------------
/contracts/StateMachine.sol:
--------------------------------------------------------------------------------
1 | contract StateMachine {
2 | enum Stages {
3 | AcceptingBlindedBids,
4 | RevealBids,
5 | AnotherStage,
6 | AreWeDoneYet,
7 | Finished
8 | }
9 |
10 | // This is the current stage.
11 | Stages public stage = Stages.AcceptingBlindedBids;
12 |
13 | uint public creationTime = now;
14 |
15 | modifier atStage(Stages _stage) {
16 | if (stage != _stage) throw;
17 | _;
18 | }
19 |
20 | function nextStage() internal {
21 | stage = Stages(uint(stage) + 1);
22 | }
23 |
24 | // Perform timed transitions. Be sure to mention
25 | // this modifier first, otherwise the guards
26 | // will not take the new stage into account.
27 | modifier timedTransitions() {
28 | if (stage == Stages.AcceptingBlindedBids &&
29 | now >= creationTime + 10 days)
30 | nextStage();
31 | if (stage == Stages.RevealBids &&
32 | now >= creationTime + 12 days)
33 | nextStage();
34 | // The other stages transition by transaction
35 | _;
36 | }
37 |
38 | // Order of the modifiers matters here!
39 | function bid()
40 | timedTransitions
41 | atStage(Stages.AcceptingBlindedBids) {
42 | // We will not implement that here
43 | }
44 |
45 | function reveal()
46 | timedTransitions
47 | atStage(Stages.RevealBids) {
48 | }
49 |
50 | // This modifier goes to the next stage
51 | // after the function is done.
52 | // If you use `return` in the function,
53 | // `nextStage` will not be called
54 | // automatically.
55 | modifier transitionNext() {
56 | _;
57 | nextStage();
58 | }
59 |
60 | function g()
61 | timedTransitions
62 | atStage(Stages.AnotherStage)
63 | transitionNext {
64 | // If you want to use `return` here,
65 | // you have to call `nextStage()` manually.
66 | }
67 |
68 | function h()
69 | timedTransitions
70 | atStage(Stages.AreWeDoneYet)
71 | transitionNext {
72 | }
73 |
74 | function i()
75 | timedTransitions
76 | atStage(Stages.Finished) {
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/slides/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
3 | }
4 |
5 | h1, h2, h3 {
6 | font-weight: 500;
7 | margin-bottom: 0;
8 | color: #dadada;
9 | }
10 |
11 | .remark-slide-content h1 {
12 | font-size: 3.2em;
13 | }
14 |
15 | .remark-slide-content h2 {
16 | font-size: 2.2em;
17 | }
18 |
19 | .remark-slide-content h3 {
20 | font-size: 1.8em;
21 | }
22 |
23 | .remark-slide-content {
24 | background: #272822;
25 | color: #f3f3f3;
26 | }
27 |
28 | .remark-slide-content li {
29 | font-size: 1.4em;
30 | margin: 14px 0;
31 | }
32 |
33 | .remark-slide-content li li{
34 | font-size: 1em;
35 | }
36 |
37 | .footnote {
38 | position: absolute;
39 | bottom: 3em;
40 | }
41 |
42 | li p {
43 | line-height: 1.25em;
44 | }
45 |
46 | .red {
47 | color: #fa0000;
48 | }
49 |
50 | .large {
51 | font-size: 2em;
52 | }
53 |
54 | a, a>code {
55 | color: rgb(249, 38, 114);
56 | text-decoration: none;
57 | }
58 |
59 | code {
60 | background: none repeat scroll 0 0 #272822;
61 | border: 1px solid #DEDEDE;
62 | border-radius: 3px;
63 | padding: 0 0.2em;
64 | }
65 |
66 | .remark-code, .remark-inline-code {
67 | font-family: "Bitstream Vera Sans Mono", "Courier", monospace;
68 | }
69 |
70 | .remark-code-line-highlighted {
71 | background-color: #373832;
72 | }
73 |
74 | .pull-left {
75 | float: left;
76 | width: 47%;
77 | }
78 |
79 | .pull-right {
80 | float: right;
81 | width: 47%;
82 | }
83 |
84 | .pull-right~p {
85 | clear: both;
86 | }
87 |
88 | #slideshow .slide .content code {
89 | font-size: 0.8em;
90 | }
91 |
92 | #slideshow .slide .content pre code {
93 | font-size: 0.9em;
94 | padding: 15px;
95 | }
96 |
97 | .main-title, .title {
98 | background: #272822;
99 | color: #777872;
100 | text-shadow: 0 0 20px #333;
101 | }
102 |
103 | .title h1, .title h2, .main-title h1, .main-title h2 {
104 | color: #f3f3f3;
105 | line-height: 0.8em;
106 | }
107 |
108 | .code{
109 |
110 | }
111 |
112 | /* Custom */
113 |
114 | .remark-code {
115 | display: block;
116 | padding: 0.5em;
117 | }
118 |
--------------------------------------------------------------------------------
/contracts/interitance-example.sol:
--------------------------------------------------------------------------------
1 | contract owned {
2 | function owned() { owner = msg.sender; }
3 | address owner;
4 | }
5 |
6 |
7 | // Use "is" to derive from another contract. Derived
8 | // contracts can access all non-private members including
9 | // internal functions and state variables. These cannot be
10 | // accessed externally via `this`, though.
11 | contract mortal is owned {
12 | function kill() {
13 | if (msg.sender == owner) selfdestruct(owner);
14 | }
15 | }
16 |
17 |
18 | // These abstract contracts are only provided to make the
19 | // interface known to the compiler. Note the function
20 | // without body. If a contract does not implement all
21 | // functions it can only be used as an interface.
22 | contract Config {
23 | function lookup(uint id) returns (address adr);
24 | }
25 |
26 |
27 | contract NameReg {
28 | function register(bytes32 name);
29 | function unregister();
30 | }
31 |
32 |
33 | // Multiple inheritance is possible. Note that "owned" is
34 | // also a base class of "mortal", yet there is only a single
35 | // instance of "owned" (as for virtual inheritance in C++).
36 | contract named is owned, mortal {
37 | function named(bytes32 name) {
38 | Config config = Config(0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970);
39 | NameReg(config.lookup(1)).register(name);
40 | }
41 |
42 | // Functions can be overridden, both local and
43 | // message-based function calls take these overrides
44 | // into account.
45 | function kill() {
46 | if (msg.sender == owner) {
47 | Config config = Config(0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970);
48 | NameReg(config.lookup(1)).unregister();
49 | // It is still possible to call a specific
50 | // overridden function.
51 | mortal.kill();
52 | }
53 | }
54 | }
55 |
56 |
57 | // If a constructor takes an argument, it needs to be
58 | // provided in the header (or modifier-invocation-style at
59 | // the constructor of the derived contract (see below)).
60 | contract PriceFeed is owned, mortal, named("GoldFeed") {
61 | function updateInfo(uint newInfo) {
62 | if (msg.sender == owner) info = newInfo;
63 | }
64 |
65 | function get() constant returns(uint r) { return info; }
66 |
67 | uint info;
68 | }
69 |
--------------------------------------------------------------------------------
/slides/5_Solidity_Patterns.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 | # Solidity - Patterns
3 |
4 | ---
5 | ## Withdrawal from contracts
6 | withdraw-contract.sol
7 |
8 | Let users withdraw themselves (rather than sending fund directly)
9 |
10 | ```Javascript
11 | contract WithdrawalContract {
12 | ...
13 |
14 | function withdraw() returns (bool) {
15 | uint amount = pendingWithdrawals[msg.sender];
16 | // Remember to zero the pending refund before
17 | // sending to prevent re-entrancy attacks
18 | pendingWithdrawals[msg.sender] = 0;
19 | if (msg.sender.send(amount)) {
20 | return true;
21 | }
22 | else {
23 | pendingWithdrawals[msg.sender] = amount;
24 | return false;
25 | }
26 | }
27 | }
28 | ```
29 |
30 | ---
31 | ## Restricting access
32 | You can make it a bit harder by using encryption, but if your contract is supposed to read the data, so will everyone else.
33 |
34 | access-restriction.sol
35 |
36 | ---
37 | ## State machine
38 | state-machine.sol
39 |
40 | ```Javascript
41 | contract StateMachine {
42 | enum Stages {
43 | AcceptingBlindedBids,
44 | RevealBids,
45 | AnotherStage,
46 | AreWeDoneYet,
47 | Finished
48 | }
49 |
50 | Stages public stage = Stages.AcceptingBlindedBids;
51 |
52 | modifier atStage(Stages _stage) {
53 | if (stage != _stage) throw;
54 | _;
55 | }
56 |
57 | function bid() atStage(Stages.AcceptingBlindedBids) {
58 | //To implement
59 | }
60 |
61 | function reveal() atStage(Stages.RevealBids) {
62 | //To implement
63 | }
64 | }
65 | ```
66 |
67 | ---
68 | ## Checks-Effects-Interactions pattern
69 |
70 | ```Javascript
71 | function auctionEnd() {
72 | // 1. checking conditions
73 | // 2. performing actions (potentially changing conditions)
74 | // 3. interacting with other contracts
75 |
76 | // 1. Conditions
77 | if (now <= auctionStart + biddingTime)
78 | throw; // auction did not yet end
79 | if (ended)
80 | throw; // this function has already been called
81 |
82 | // 2. Effects
83 | ended = true;
84 | AuctionEnded(highestBidder, highestBid);
85 |
86 | // 3. Interaction
87 | if (!beneficiary.send(highestBid))
88 | throw;
89 | }
90 | ```
91 |
--------------------------------------------------------------------------------
/dapp_example/myDapp2/client/main.js:
--------------------------------------------------------------------------------
1 | import { Template } from 'meteor/templating';
2 | import { ReactiveVar } from 'meteor/reactive-var';
3 | _ = lodash;
4 |
5 | import './main.html';
6 |
7 | // Template - blockInfo
8 | Template.blockInfo.onCreated(function blockInfoOnCreated(){
9 | EthBlocks.init();
10 | });
11 |
12 | Template.blockInfo.helpers({
13 | currentBlock(){
14 | return EthBlocks.latest.number;
15 | },
16 | });
17 |
18 | // Template - OneValue
19 | Template.oneValue.onCreated(function oneValueOnCreated(){
20 | var abi = [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"type":"constructor"}];;
21 | var OneValueContract = web3.eth.contract(abi);
22 | this.contractAddress = '0xe07438274839E9793baEAaa757F695CfED4A9e26';
23 | var oneValue = this.oneValue = OneValueContract.at(this.contractAddress);
24 | var currentValue = this.currentValue = new ReactiveVar(0);
25 | var message = this.message = new ReactiveVar("");
26 | setInterval(function(){
27 | oneValue.getValue(function(err, res){
28 | if(!_.isEqual(res.toNumber(), currentValue.get())){
29 | currentValue.set(res.toNumber());
30 | message.set("Update value to: " + res.toNumber());
31 | }
32 | });
33 | }, 1000);
34 |
35 | });
36 |
37 | Template.oneValue.helpers({
38 | oneValueAddress(){
39 | return Template.instance().contractAddress;
40 | },
41 | currentValue(){
42 | return Template.instance().currentValue.get();
43 | },
44 | getMessage(){
45 | return Template.instance().message.get();
46 | }
47 | });
48 |
49 | Template.oneValue.events({
50 | 'click button'(event, instance) {
51 | // increment the counter when button is clicked
52 | //instance.counter.set(instance.counter.get() + 1);
53 | var newValue = $('#new-value').val();
54 | var oneValue = Template.instance().oneValue;
55 | var message = Template.instance().message;
56 | oneValue.setValue.sendTransaction(_.toNumber(newValue), function(err, res){
57 | message.set("Transaction hash: " + res);
58 | });
59 | },
60 | });
61 |
--------------------------------------------------------------------------------
/contracts/AccessRestriction.sol:
--------------------------------------------------------------------------------
1 | contract AccessRestriction {
2 | // These will be assigned at the construction
3 | // phase, where `msg.sender` is the account
4 | // creating this contract.
5 | address public owner = msg.sender;
6 | uint public creationTime = now;
7 |
8 | // Modifiers can be used to change
9 | // the body of a function.
10 | // If this modifier is used, it will
11 | // prepend a check that only passes
12 | // if the function is called from
13 | // a certain address.
14 | modifier onlyBy(address _account)
15 | {
16 | if (msg.sender != _account)
17 | throw;
18 | // Do not forget the "_"! It will
19 | // be replaced by the actual function
20 | // body when the modifier is invoked.
21 | _;
22 | }
23 |
24 | /// Make `_newOwner` the new owner of this
25 | /// contract.
26 | function changeOwner(address _newOwner)
27 | onlyBy(owner)
28 | {
29 | owner = _newOwner;
30 | }
31 |
32 | modifier onlyAfter(uint _time) {
33 | if (now < _time) throw;
34 | _;
35 | }
36 |
37 | /// Erase ownership information.
38 | /// May only be called 6 weeks after
39 | /// the contract has been created.
40 | function disown()
41 | onlyBy(owner)
42 | onlyAfter(creationTime + 6 weeks)
43 | {
44 | delete owner;
45 | }
46 |
47 | // This modifier requires a certain
48 | // fee being associated with a function call.
49 | // If the caller sent too much, he or she is
50 | // refunded, but only after the function body.
51 | // This is dangerous, because if the function
52 | // uses `return` explicitly, this will not be
53 | // done! This behavior will be fixed in Version 0.4.0.
54 | modifier costs(uint _amount) {
55 | if (msg.value < _amount)
56 | throw;
57 | _;
58 | if (msg.value > _amount)
59 | msg.sender.send(msg.value - _amount);
60 | }
61 |
62 | function forceOwnerChange(address _newOwner)
63 | costs(200 ether)
64 | {
65 | owner = _newOwner;
66 | // just some example condition
67 | if (uint(owner) & 0 == 1)
68 | // in this case, overpaid fees will not
69 | // be refunded
70 | return;
71 | // otherwise, refund overpaid fees
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/contracts/remote-purchase.sol:
--------------------------------------------------------------------------------
1 | contract Purchase {
2 | uint public value;
3 | address public seller;
4 | address public buyer;
5 | enum State { Created, Locked, Inactive }
6 | State public state;
7 |
8 | function Purchase() {
9 | seller = msg.sender;
10 | value = msg.value / 2;
11 | if (2 * value != msg.value) throw;
12 | }
13 |
14 | modifier require(bool _condition) {
15 | if (!_condition) throw;
16 | _;
17 | }
18 |
19 | modifier onlyBuyer() {
20 | if (msg.sender != buyer) throw;
21 | _;
22 | }
23 |
24 | modifier onlySeller() {
25 | if (msg.sender != seller) throw;
26 | _;
27 | }
28 |
29 | modifier inState(State _state) {
30 | if (state != _state) throw;
31 | _;
32 | }
33 |
34 | event aborted();
35 | event purchaseConfirmed();
36 | event itemReceived();
37 |
38 | /// Abort the purchase and reclaim the ether.
39 | /// Can only be called by the seller before
40 | /// the contract is locked.
41 | function abort()
42 | onlySeller
43 | inState(State.Created)
44 | {
45 | aborted();
46 | state = State.Inactive;
47 | if (!seller.send(this.balance))
48 | throw;
49 | }
50 |
51 | /// Confirm the purchase as buyer.
52 | /// Transaction has to include `2 * value` ether.
53 | /// The ether will be locked until confirmReceived
54 | /// is called.
55 | function confirmPurchase()
56 | inState(State.Created)
57 | require(msg.value == 2 * value)
58 | {
59 | purchaseConfirmed();
60 | buyer = msg.sender;
61 | state = State.Locked;
62 | }
63 |
64 | /// Confirm that you (the buyer) received the item.
65 | /// This will release the locked ether.
66 | function confirmReceived()
67 | onlyBuyer
68 | inState(State.Locked)
69 | {
70 | itemReceived();
71 | // It is important to change the state first because
72 | // otherwise, the contracts called using `send` below
73 | // can call in again here.
74 | state = State.Inactive;
75 | // This actually allows both the buyer and the seller to
76 | // block the refund.
77 | if (!buyer.send(value) || !seller.send(this.balance))
78 | throw;
79 | }
80 |
81 | function() {
82 | throw;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/contracts/build/PriceFeed.bin:
--------------------------------------------------------------------------------
1 | 60606040527f476f6c64466565640000000000000000000000000000000000000000000000005b60005b33600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b73d5f9d8d94886e70b06e474c3fb14fd43e2f2397090508073ffffffffffffffffffffffffffffffffffffffff16630a874df660016000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15156100f757fe5b60325a03f1151561010457fe5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff1663e1fa8e84836040518263ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401808260001916600019168152602001915050600060405180830381600087803b151561018057fe5b60325a03f1151561018d57fe5b5050505b50505b610350806101a36000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063316db7f21461005157806341c0e1b5146100715780636d4ce63c14610083575bfe5b341561005957fe5b61006f60048080359060200190919050506100a9565b005b341561007957fe5b61008161010b565b005b341561008b57fe5b610093610285565b6040518082815260200191505060405180910390f35b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561010757806001819055505b5b50565b6000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614156102815773d5f9d8d94886e70b06e474c3fb14fd43e2f2397090508073ffffffffffffffffffffffffffffffffffffffff16630a874df660016000604051602001526040518263ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040180828152602001915050602060405180830381600087803b15156101ef57fe5b60325a03f115156101fc57fe5b5050506040518051905073ffffffffffffffffffffffffffffffffffffffff1663e79a198f6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401809050600060405180830381600087803b151561026857fe5b60325a03f1151561027557fe5b505050610280610290565b5b5b50565b600060015490505b90565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561032157600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b5b5600a165627a7a7230582011b740302371ef0e89ab0bb4a03558ac0954ff017c635c348ca26bcc721615370029
--------------------------------------------------------------------------------
/slides/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | dom-walk@^0.1.0:
6 | version "0.1.1"
7 | resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
8 |
9 | global@^4.3.1:
10 | version "4.3.1"
11 | resolved "https://registry.yarnpkg.com/global/-/global-4.3.1.tgz#5f757908c7cbabce54f386ae440e11e26b7916df"
12 | dependencies:
13 | min-document "^2.19.0"
14 | process "~0.5.1"
15 |
16 | markdown-to-slides@^1.0.5:
17 | version "1.0.5"
18 | resolved "https://registry.yarnpkg.com/markdown-to-slides/-/markdown-to-slides-1.0.5.tgz#6699bd31a1cf5189ab8e04c2f4dcd83c1ef185f0"
19 | dependencies:
20 | marked "^0.3.2"
21 | marked-to-md "1.0.x"
22 | mustache "2.1.x"
23 | optimist "~0.3.4"
24 | remark "git://github.com/gnab/remark.git#v0.13.0"
25 |
26 | marked-to-md@1.0.x:
27 | version "1.0.1"
28 | resolved "https://registry.yarnpkg.com/marked-to-md/-/marked-to-md-1.0.1.tgz#864cacb02f3f0a92510c53a8d5fa1e14acd09a5f"
29 |
30 | marked@0.3.1:
31 | version "0.3.1"
32 | resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.1.tgz#156a3b803cc54c59290e60354b83baaa7d66c074"
33 |
34 | marked@^0.3.2:
35 | version "0.3.6"
36 | resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7"
37 |
38 | min-document@^2.19.0:
39 | version "2.19.0"
40 | resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
41 | dependencies:
42 | dom-walk "^0.1.0"
43 |
44 | mustache@2.1.x:
45 | version "2.1.3"
46 | resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.1.3.tgz#25b90b4204a454c898e8bb2e38d26de223abbd56"
47 |
48 | optimist@~0.3.4:
49 | version "0.3.7"
50 | resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9"
51 | dependencies:
52 | wordwrap "~0.0.2"
53 |
54 | process@~0.5.1:
55 | version "0.5.2"
56 | resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
57 |
58 | "remark@git://github.com/gnab/remark.git#v0.13.0":
59 | version "0.13.0"
60 | resolved "git://github.com/gnab/remark.git#a6fdde973b965c1e1a5e6d93645096f71f96a05b"
61 | dependencies:
62 | marked "0.3.1"
63 |
64 | wordwrap@~0.0.2:
65 | version "0.0.3"
66 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
67 |
--------------------------------------------------------------------------------
/slides/6_Solidity_Testing.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Solidity testing
4 |
5 | ---
6 |
7 | ## Tools:
8 |
9 | - Testrpc: https://github.com/ethereumjs/testrpc
10 | ```bash
11 | testrpc -p 8600 -a 10
12 | ```
13 |
14 | - Mocha: https://mochajs.org/
15 |
16 | ---
17 | ## Mocha
18 | Mocha is a feature-rich JavaScript test framework running on Node.js and in the browser, making asynchronous testing simple and fun. Mocha tests run serially, allowing for flexible and accurate reporting, while mapping uncaught exceptions to the correct test cases. Hosted on GitHub.
19 |
20 | ---
21 | ## Test case example
22 | one-value-tests.js
23 |
24 | ```JavaScript
25 | describe('OneValueContract', function(){
26 | // 1. Deploy OneValueContract
27 | before(function(done) {
28 | web3.eth.getAccounts(function(error, result){
29 | //3. Deploy
30 | primaryAddress = result[0]; //Blockchain Admin
31 | oneValue = OneValueContract.new(initValue, {from:primaryAddress, data: bin}, function(error, contract){
32 | if(error == null && contract.address != null){
33 | //Mined
34 | done();
35 | }
36 | });
37 | });
38 | });
39 |
40 | it("initValue should be 123", function(done){
41 | oneValue.getValue(function(error, result){
42 | assert.equal(initValue, result);
43 | done();
44 | });
45 | });
46 | });
47 |
48 | ```
49 |
50 | ---
51 | ## Run tests
52 | Add test script in package.json
53 | ```Javascript
54 | {
55 | "dependencies": {
56 | "mocha": "2.4.5"
57 | },
58 | "scripts": {
59 | "test": "find tests -name '*tests.js' -not -path './node_modules/*' | xargs ./node_modules/mocha/bin/_mocha -R spec"
60 | }
61 | }
62 | ```
63 |
64 | Run: `npm test`
65 |
66 | ---
67 | ## Test with truffle
68 | https://truffle.readthedocs.io/en/latest/getting_started/testing/
69 |
70 | ```Javascript
71 | contract('MetaCoin', function(accounts) {
72 | it("should put 10000 MetaCoin in the first account", function() {
73 | // Get a reference to the deployed MetaCoin contract, as a JS object.
74 | var meta = MetaCoin.deployed();
75 |
76 | // Get the MetaCoin balance of the first account and assert that it's 10000.
77 | return meta.getBalance.call(accounts[0]).then(function(balance) {
78 | assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account");
79 | });
80 | });
81 | });
82 | ```
83 |
84 | Run: `truffle test`
85 |
--------------------------------------------------------------------------------
/truffle_test/test/metacoin.js:
--------------------------------------------------------------------------------
1 | var MetaCoin = artifacts.require("./MetaCoin.sol");
2 |
3 | contract('MetaCoin', function(accounts) {
4 | it("should put 10000 MetaCoin in the first account", function() {
5 | return MetaCoin.deployed().then(function(instance) {
6 | return instance.getBalance.call(accounts[0]);
7 | }).then(function(balance) {
8 | assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account");
9 | });
10 | });
11 | it("should call a function that depends on a linked library", function() {
12 | var meta;
13 | var metaCoinBalance;
14 | var metaCoinEthBalance;
15 |
16 | return MetaCoin.deployed().then(function(instance) {
17 | meta = instance;
18 | return meta.getBalance.call(accounts[0]);
19 | }).then(function(outCoinBalance) {
20 | metaCoinBalance = outCoinBalance.toNumber();
21 | return meta.getBalanceInEth.call(accounts[0]);
22 | }).then(function(outCoinBalanceEth) {
23 | metaCoinEthBalance = outCoinBalanceEth.toNumber();
24 | }).then(function() {
25 | assert.equal(metaCoinEthBalance, 2 * metaCoinBalance, "Library function returned unexpected function, linkage may be broken");
26 | });
27 | });
28 | it("should send coin correctly", function() {
29 | var meta;
30 |
31 | // Get initial balances of first and second account.
32 | var account_one = accounts[0];
33 | var account_two = accounts[1];
34 |
35 | var account_one_starting_balance;
36 | var account_two_starting_balance;
37 | var account_one_ending_balance;
38 | var account_two_ending_balance;
39 |
40 | var amount = 10;
41 |
42 | return MetaCoin.deployed().then(function(instance) {
43 | meta = instance;
44 | return meta.getBalance.call(account_one);
45 | }).then(function(balance) {
46 | account_one_starting_balance = balance.toNumber();
47 | return meta.getBalance.call(account_two);
48 | }).then(function(balance) {
49 | account_two_starting_balance = balance.toNumber();
50 | return meta.sendCoin(account_two, amount, {from: account_one});
51 | }).then(function() {
52 | return meta.getBalance.call(account_one);
53 | }).then(function(balance) {
54 | account_one_ending_balance = balance.toNumber();
55 | return meta.getBalance.call(account_two);
56 | }).then(function(balance) {
57 | account_two_ending_balance = balance.toNumber();
58 |
59 | assert.equal(account_one_ending_balance, account_one_starting_balance - amount, "Amount wasn't correctly taken from the sender");
60 | assert.equal(account_two_ending_balance, account_two_starting_balance + amount, "Amount wasn't correctly sent to the receiver");
61 | });
62 | });
63 | });
64 |
--------------------------------------------------------------------------------
/slides/1_Blockchain_Basics.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Blockchain Basics
4 |
5 | ---
6 |
7 | ## Blockchain 1.0 - Bitcoin and Alt coins (Dogecoin, Litecoin, etc)
8 | - P2P payment system
9 |
10 | - Blockchain
11 |
12 | - Immutable: create and read. no update and delete.
13 |
14 | - Non-repudiable: digital signatures, sign & verify
15 |
16 | - Fault-tolerant: censorship resistant, partially-connected mesh resilience
17 |
18 | ---
19 |
20 | ## Blockchain 1.1 - Colored Coins, Decoration protocols
21 | - Colored coins – leverage additional 40 bytes scripting size in Bitcoin
22 |
23 | - Mastercoin, Bitshares and Counterparty
24 |
25 | - financial derivatives
26 |
27 | - savings wallets
28 |
29 | - decentralized exchange
30 |
31 | ---
32 | ## Blockchain 2.0 - Ethereum, Tendermint
33 | - General purpose blockchain
34 |
35 | - Ethereum: TCP/IP = Bitcoin: SMTP
36 |
37 | ---
38 | ## Ethereum
39 | - Turing-complete
40 |
41 | - Universal scripting language
42 |
43 | - Mining algorithm - specialized hardware resistant. (Dagger)
44 |
45 | - Fee system
46 |
47 | - GHOST (fast block confirmation time, 3 ~ 30 sec)
48 |
49 | ---
50 | ## Ethereum Virtual Machine vs. Bitcoin Scripting
51 | | Ethereum | Bitcoin |
52 | | -- | -- |
53 | | Turing-completeness | Turing-incomplete - no loop |
54 | | State-awareness | Lack of state - single stage |
55 | | Value-awareness | Value-blindness - all or nothing |
56 | | Blockchain-awareness | Blockchain-blindness - no blockchain reference |
57 |
58 | ---
59 | ## Accounts vs UTXO
60 | - Accounts
61 |
62 | - Large space savings
63 |
64 | - Greater fungibility
65 |
66 | - Simplicity
67 |
68 | - Constant light client reference
69 |
70 | - UTXO
71 |
72 | - Higher degree of privacy
73 |
74 | - Potential scalability paradigms
75 |
76 | ---
77 | ## Why not UTXO - State
78 | - UTXOs are unnecessarily complicated
79 |
80 | - UTXOs are stateless, and so are not well-suited to dapps
81 |
82 | ---
83 | ## Bitcoin Script: pay-to-pubkey-hash
84 | | Stack | Script | Description |
85 | | -- | -- | -- |
86 | | Empty. | ` OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG` |scriptSig and scriptPubKey are combined. |
87 | | ` ` | `OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG` | Constants are added to the stack. |
88 | | ` ` | `OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG`|Top stack item is duplicated. |
89 | | ` ` | ` OP_EQUALVERIFY OP_CHECKSIG` | Top stack item is hashed. |
90 | | ` ` | `OP_EQUALVERIFY OP_CHECKSIG` | Constant added. |
91 | | ` ` | `OP_CHECKSIG` |Equality is checked between the top two stack items. |
92 | | `true` | Empty. | Signature is checked for top two stack items.|
93 |
94 | ---
95 | ## Ethereum Virtual Machine v.s. Bitcoin Scripting (2)
96 | - Bitcoin script is primarily about expressing ownership conditions.
97 |
98 | - Ethereum script is more suited to describing business logic (though it can express ownership conditions too)
99 |
--------------------------------------------------------------------------------
/contracts/build/StateMachine.bin:
--------------------------------------------------------------------------------
1 | 60606040526000600060006101000a81548160ff0219169083600481111561002357fe5b021790555042600155341561003457fe5b5b6105e7806100446000396000f30060606040523615610081576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631998aeef14610083578063a475b5dd14610095578063b8c9d365146100a7578063c040e6b8146100b9578063d8270dce146100ed578063e2179b8e14610113578063e5aa3d5814610125575bfe5b341561008b57fe5b610093610137565b005b341561009d57fe5b6100a5610206565b005b34156100af57fe5b6100b76102d5565b005b34156100c157fe5b6100c96103ad565b604051808260048111156100d957fe5b60ff16815260200191505060405180910390f35b34156100f557fe5b6100fd6103c0565b6040518082815260200191505060405180910390f35b341561011b57fe5b6101236103c6565b005b341561012d57fe5b61013561049e565b005b6000600481111561014457fe5b600060009054906101000a900460ff16600481111561015f57fe5b1480156101735750620d2f00600154014210155b156101815761018061056d565b5b6001600481111561018e57fe5b600060009054906101000a900460ff1660048111156101a957fe5b1480156101bd5750620fd200600154014210155b156101cb576101ca61056d565b5b60008060048111156101d957fe5b600060009054906101000a900460ff1660048111156101f457fe5b14151561020057610000565b5b5b505b565b6000600481111561021357fe5b600060009054906101000a900460ff16600481111561022e57fe5b1480156102425750620d2f00600154014210155b156102505761024f61056d565b5b6001600481111561025d57fe5b600060009054906101000a900460ff16600481111561027857fe5b14801561028c5750620fd200600154014210155b1561029a5761029961056d565b5b60018060048111156102a857fe5b600060009054906101000a900460ff1660048111156102c357fe5b1415156102cf57610000565b5b5b505b565b600060048111156102e257fe5b600060009054906101000a900460ff1660048111156102fd57fe5b1480156103115750620d2f00600154014210155b1561031f5761031e61056d565b5b6001600481111561032c57fe5b600060009054906101000a900460ff16600481111561034757fe5b14801561035b5750620fd200600154014210155b156103695761036861056d565b5b600380600481111561037757fe5b600060009054906101000a900460ff16600481111561039257fe5b14151561039e57610000565b5b6103a761056d565b5b5b505b565b600060009054906101000a900460ff1681565b60015481565b600060048111156103d357fe5b600060009054906101000a900460ff1660048111156103ee57fe5b1480156104025750620d2f00600154014210155b156104105761040f61056d565b5b6001600481111561041d57fe5b600060009054906101000a900460ff16600481111561043857fe5b14801561044c5750620fd200600154014210155b1561045a5761045961056d565b5b600280600481111561046857fe5b600060009054906101000a900460ff16600481111561048357fe5b14151561048f57610000565b5b61049861056d565b5b5b505b565b600060048111156104ab57fe5b600060009054906101000a900460ff1660048111156104c657fe5b1480156104da5750620d2f00600154014210155b156104e8576104e761056d565b5b600160048111156104f557fe5b600060009054906101000a900460ff16600481111561051057fe5b1480156105245750620fd200600154014210155b156105325761053161056d565b5b600480600481111561054057fe5b600060009054906101000a900460ff16600481111561055b57fe5b14151561056757610000565b5b5b505b565b6001600060009054906101000a900460ff16600481111561058a57fe5b01600481111561059657fe5b600060006101000a81548160ff021916908360048111156105b357fe5b02179055505b5600a165627a7a723058200f1afd541c5e6b4fea80f12bd340858c4cedfa92dc803d126ead9f3c9ec6ff590029
--------------------------------------------------------------------------------
/contracts/build/SimpleAuction.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b6040516040806106aa833981016040528080519060200190919080519060200190919050505b80600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600181905550816002819055505b50505b610616806100946000396000f3006060604052361561008c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631998aeef146100a15780632a24f46c146100b357806338af3eed146100c55780633ccfd60b146101175780634f245ef71461012957806391f901571461014f578063d074a38d146101a1578063d57bde79146101c7575b341561009457fe5b61009f5b610000565b565b005b34156100a957fe5b6100b16101ed565b005b34156100bb57fe5b6100c361037a565b005b34156100cd57fe5b6100d56104bc565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561011f57fe5b6101276104e2565b005b341561013157fe5b6101396105b2565b6040518082815260200191505060405180910390f35b341561015757fe5b61015f6105b8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101a957fe5b6101b16105de565b6040518082815260200191505060405180910390f35b34156101cf57fe5b6101d76105e4565b6040518082815260200191505060405180910390f35b6002546001540142111561020057610000565b6004543411151561021057610000565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156102c45760045460056000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b33600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550346004819055507ff4757a49b326036464bec6fe419a4ae38c8a02ce3e68bf0809674f6aab8ad3003334604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a15b565b600254600154014211151561038e57610000565b600660009054906101000a900460ff16156103a857610000565b6001600660006101000a81548160ff0219169083151502179055507fdaec4582d5d9595688c8c98545fdd1c696d41c6aeaeb636737e84ed2f5c00eda600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600454604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a1600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6004549081150290604051809050600060405180830381858888f1935050505015156104b957610000565b5b565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f1935050505015156105ae57610000565b5b50565b60015481565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60025481565b600454815600a165627a7a72305820e1260d03188896b26a39fa796a88cc438744c944427a6c185390e2243b424e750029
--------------------------------------------------------------------------------
/contracts/build/Purchase.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b5b33600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060023481151561005a57fe5b046000819055503460005460020214151561007457610000565b5b5b61066f806100856000396000f30060606040523615610081576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806308551a531461009657806335a063b4146100e85780633fa4f245146100fa5780637150d8ae1461012057806373fac6f014610172578063c19d93fb14610184578063d6960697146101b8575b341561008957fe5b6100945b610000565b565b005b341561009e57fe5b6100a66101ca565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100f057fe5b6100f86101f0565b005b341561010257fe5b61010a610356565b6040518082815260200191505060405180910390f35b341561012857fe5b61013061035c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561017a57fe5b610182610382565b005b341561018c57fe5b61019461054c565b604051808260028111156101a457fe5b60ff16815260200191505060405180910390f35b34156101c057fe5b6101c861055f565b005b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561024c57610000565b600080600281111561025a57fe5b600260149054906101000a900460ff16600281111561027557fe5b14151561028157610000565b7f80b62b7017bb13cf105e22749ee2a06a417ffba8c7f57b665057e0f3c2e925d960405180905060405180910390a16002600260146101000a81548160ff021916908360028111156102cf57fe5b0217905550600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050151561035057610000565b5b5b505b565b60005481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156103de57610000565b60018060028111156103ec57fe5b600260149054906101000a900460ff16600281111561040757fe5b14151561041357610000565b7f64ea507aa320f07ae13c28b5e9bf6b4833ab544315f5f2aa67308e21c252d47d60405180905060405180910390a16002600260146101000a81548160ff0219169083600281111561046157fe5b0217905550600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc6000549081150290604051809050600060405180830381858888f19350505050158061053c5750600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050155b1561054657610000565b5b5b505b565b600260149054906101000a900460ff1681565b600080600281111561056d57fe5b600260149054906101000a900460ff16600281111561058857fe5b14151561059457610000565b60005460020234148015156105a857610000565b7f764326667cab2f2f13cad5f7b7665c704653bd1acc250dcb7b422bce726896b460405180905060405180910390a133600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600260146101000a81548160ff0219169083600281111561063757fe5b02179055505b5b505b505600a165627a7a72305820bbd82f72fd90ed3d00e57f28362b391ff6241d37eb8322801d75c4fad70ea3de0029
--------------------------------------------------------------------------------
/LECTURES.MD:
--------------------------------------------------------------------------------
1 |
2 | ## 政大 (03/23/2017)
3 | - [0. Agenda](https://amisamity.github.io/contract-training/slides/0_Agenda_03232017.md.html)
4 | - [1. Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools_03202017.md.html)
5 | - [2. Smart Contract and Solidity](https://amisamity.github.io/contract-training/slides/3_Smart_Contract_Solidity_Quick_Start_03232017.md.html)
6 | - [3. Ðapp Example - FlightDelay](https://amisamity.github.io/contract-training/slides/8_Insurance_Examples.md.html)
7 | - [4. Web3 JavaScript Ðapp API](https://amisamity.github.io/contract-training/slides/10_Web3_JavaScript.md.html)
8 | - [5. Ðapps Development](https://amisamity.github.io/contract-training/slides/9_Dapps_Development.md.html)
9 | - [6. References](https://amisamity.github.io/contract-training/slides/7_References.md.html)
10 |
11 | ## 台科大 (03/17/2017)
12 | - [0. Agenda](https://amisamity.github.io/contract-training/slides/0_Agenda_03172017.md.html)
13 | - [1. Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools.md.html)
14 | - [2. Ðapp Example - FlightDelay](https://amisamity.github.io/contract-training/slides/8_Insurance_Examples.md.html)
15 | - [3. Web3 JavaScript Ðapp API](https://amisamity.github.io/contract-training/slides/10_Web3_JavaScript.md.html)
16 | - [4. Ðapps Development](https://amisamity.github.io/contract-training/slides/9_Dapps_Development.md.html)
17 | - [5. References](https://amisamity.github.io/contract-training/slides/7_References.md.html)
18 |
19 | ## 保發中心 (03/10/2017)
20 | - [0. Agenda](https://amisamity.github.io/contract-training/slides/0_Agenda_03102017.md.html)
21 | - [1. Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools.md.html)
22 | - [2. Smart Contract and Solidity](https://amisamity.github.io/contract-training/slides/3_Smart_Contract_Solidity_Quick_Start.md.html)
23 | - [3. Insurance Example](https://amisamity.github.io/contract-training/slides/8_Insurance_Examples.md.html)
24 | - [4. Web3 JavaScript Ðapp API](https://amisamity.github.io/contract-training/slides/10_Web3_JavaScript.md.html)
25 | - [5. Ðapps Development](https://amisamity.github.io/contract-training/slides/9_Dapps_Development.md.html)
26 | - [6. Solidity Security](https://amisamity.github.io/contract-training/slides/4_Solidity_Security.md.html)
27 | - [7. Solidity Patterns](https://amisamity.github.io/contract-training/slides/5_Solidity_Patterns.md.html)
28 | - [8. Solidity Testing](https://amisamity.github.io/contract-training/slides/6_Solidity_Testing.md.html)
29 | - [9. References](https://amisamity.github.io/contract-training/slides/7_References.md.html)
30 |
31 | ## 政大 (11/14/2016)
32 | - [0. Agenda](https://amisamity.github.io/contract-training/slides/0_Agenda_1114.md.html)
33 | - [1. Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools.md.html)
34 | - [2. Smart Contract and Solidity](https://amisamity.github.io/contract-training/slides/3_Smart_Contract_Solidity.md.html)
35 | - [3. Solidity Security](https://amisamity.github.io/contract-training/slides/4_Solidity_Security.md.html)
36 | - [4. Solidity Patterns](https://amisamity.github.io/contract-training/slides/5_Solidity_Patterns.md.html)
37 | - [5. Solidity Testing](https://amisamity.github.io/contract-training/slides/6_Solidity_Testing.md.html)
38 | - [6. References](https://amisamity.github.io/contract-training/slides/7_References.md.html)
39 | - [7. Devcon2](https://goo.gl/PEj4Ka)
40 |
41 | ## 台科大 (09/06/2016)
42 | - [0. Agenda](https://amisamity.github.io/contract-training/slides/0_Agenda_0906.md.html)
43 | - [1. Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools.md.html)
44 | - [2. Smart Contract and Solidity](https://amisamity.github.io/contract-training/slides/3_Smart_Contract_Solidity.md.html)
45 |
--------------------------------------------------------------------------------
/slides/4_Solidity_Security.md:
--------------------------------------------------------------------------------
1 | class: middle, center
2 |
3 | # Solidity Security
4 |
5 | ---
6 | ## Private information and randomness
7 |
8 | - Everything you use in a smart contract is publicly visible, even local variables and state variables marked `private`.
9 |
10 | - Using random numbers in smart contracts is quite tricky if you do not want miners to be able to cheat.
11 | Reference: https://github.com/randao/randao
12 |
13 | ---
14 | ## Re-entrancy
15 |
16 | Any interaction from a contract (A) with another contract (B) and any transfer of Ether hands over control to that contract (B). This makes it possible for B to call back into A before this interaction is completed.
17 |
18 | ```Javascript
19 | // THIS CONTRACT CONTAINS A BUG - DO NOT USE
20 | contract Fund {
21 | /// Mapping of ether shares of the contract.
22 | mapping(address => uint) shares;
23 | /// Withdraw your share.
24 | function withdraw() {
25 | if (msg.sender.send(shares[msg.sender]))
26 | shares[msg.sender] = 0;
27 | }
28 | }
29 | ```
30 |
31 | ---
32 | ## Checks-Effects-Interactions pattern
33 |
34 | ```Javascript
35 | function auctionEnd() {
36 | // 1. checking conditions
37 | // 2. performing actions (potentially changing conditions)
38 | // 3. interacting with other contracts
39 |
40 | // 1. Conditions
41 | if (now <= auctionStart + biddingTime)
42 | throw; // auction did not yet end
43 | if (ended)
44 | throw; // this function has already been called
45 |
46 | // 2. Effects
47 | ended = true;
48 | AuctionEnded(highestBidder, highestBid);
49 |
50 | // 3. Interaction
51 | if (!beneficiary.send(highestBid))
52 | throw;
53 | }
54 | ```
55 |
56 | ---
57 | ## Gas limit and loops
58 | - Be careful for loops that do not have a fixed number of iterations.
59 |
60 | - Most fallback function (called by `send`) rely on the "gas stipend" (2300 gas)
61 |
62 | - There is a way to forward more gas to the receiving contract using addr.call.value(x)(). Be careful for malicious actors.
63 |
64 | - If you are using address.send.
65 |
66 | - If the recipient is a contact, you will call its fallback function
67 |
68 | - Sending Ether can fail due to the call depth going above 1024.
69 |
70 | ---
71 | ## tx.origin
72 | Never use tx.origin for authorization. Let’s say you have a wallet contract like this:
73 | ``` Javascript
74 | contract TxUserWallet {
75 | address owner;
76 |
77 | function TxUserWallet() {
78 | owner = msg.sender;
79 | }
80 |
81 | function transfer(address dest, uint amount) {
82 | if (tx.origin != owner) { throw; }
83 | if (!dest.call.value(amount)()) throw;
84 | }
85 | }
86 | ```
87 | ---
88 | ## tx.origin
89 | Now someone tricks you into sending ether to the address of this attack wallet:
90 | ```Javascript
91 | contract TxAttackWallet {
92 | address owner;
93 |
94 | function TxAttackWallet() {
95 | owner = msg.sender;
96 | }
97 |
98 | function() {
99 | TxUserWallet(msg.sender).transfer(owner, msg.sender.balance);
100 | }
101 | }
102 | ```
103 |
104 | ---
105 | ## Recommendations
106 |
107 | - Restrict the Amount of Ether
108 |
109 | - Keep it Small and Modular
110 |
111 | - Use the Checks-Effects-Interactions Pattern
112 |
113 | - Include a Fail-Safe Mode
114 |
115 | ---
116 | ## DAO attack
117 |
118 | Fix: https://github.com/slockit/DAO/pull/242
119 |
120 | ManagedAccount.sol
121 | ```Javascript
122 | function payOut(address _recipient, uint _amount) returns (bool) {
123 | if (msg.sender != owner || msg.value > 0 || (payOwnerOnly && _recipient != owner))
124 | throw;
125 | if (_recipient.call.value(_amount)()) {
126 | PayOut(_recipient, _amount);
127 | return true;
128 | } else {
129 | return false;
130 | }
131 | }
132 | ```
133 |
134 | ---
135 | ## DAO attack
136 | DAO.sol
137 |
138 | ```Javascript
139 | function withdrawRewardFor(address _account) noEther internal returns (bool _success) {
140 | if ((balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply < paidOut[_account])
141 | throw;
142 |
143 | uint reward =
144 | (balanceOf(_account) * rewardAccount.accumulatedInput()) / totalSupply - paidOut[_account];
145 |
146 | reward = rewardAccount.balance < reward ? rewardAccount.balance : reward;
147 |
148 | + paidOut[_account] += reward;
149 |
150 | if (!rewardAccount.payOut(_account, reward))
151 | throw;
152 |
153 | - paidOut[_account] += reward;
154 |
155 | return true;
156 | }
157 | ```
158 |
--------------------------------------------------------------------------------
/contracts/SimpleAuction.sol:
--------------------------------------------------------------------------------
1 | contract SimpleAuction {
2 | // Parameters of the auction. Times are either
3 | // absolute unix timestamps (seconds since 1970-01-01)
4 | // or time periods in seconds.
5 | address public beneficiary;
6 | uint public auctionStart;
7 | uint public biddingTime;
8 |
9 | // Current state of the auction.
10 | address public highestBidder;
11 | uint public highestBid;
12 |
13 | // Allowed withdrawals of previous bids
14 | mapping(address => uint) pendingReturns;
15 |
16 | // Set to true at the end, disallows any change
17 | bool ended;
18 |
19 | // Events that will be fired on changes.
20 | event HighestBidIncreased(address bidder, uint amount);
21 | event AuctionEnded(address winner, uint amount);
22 |
23 | // The following is a so-called natspec comment,
24 | // recognizable by the three slashes.
25 | // It will be shown when the user is asked to
26 | // confirm a transaction.
27 |
28 | /// Create a simple auction with `_biddingTime`
29 | /// seconds bidding time on behalf of the
30 | /// beneficiary address `_beneficiary`.
31 | function SimpleAuction(
32 | uint _biddingTime,
33 | address _beneficiary
34 | ) {
35 | beneficiary = _beneficiary;
36 | auctionStart = now;
37 | biddingTime = _biddingTime;
38 | }
39 |
40 | /// Bid on the auction with the value sent
41 | /// together with this transaction.
42 | /// The value will only be refunded if the
43 | /// auction is not won.
44 | function bid() {
45 | // No arguments are necessary, all
46 | // information is already part of
47 | // the transaction.
48 | if (now > auctionStart + biddingTime) {
49 | // Revert the call if the bidding
50 | // period is over.
51 | throw;
52 | }
53 | if (msg.value <= highestBid) {
54 | // If the bid is not higher, send the
55 | // money back.
56 | throw;
57 | }
58 | if (highestBidder != 0) {
59 | // Sending back the money by simply using
60 | // highestBidder.send(highestBid) is a security risk
61 | // because it can be prevented by the caller by e.g.
62 | // raising the call stack to 1023. It is always safer
63 | // to let the recipient withdraw their money themselves.
64 | pendingReturns[highestBidder] += highestBid;
65 | }
66 | highestBidder = msg.sender;
67 | highestBid = msg.value;
68 | HighestBidIncreased(msg.sender, msg.value);
69 | }
70 |
71 | /// Withdraw a bid that was overbid.
72 | function withdraw() {
73 | var amount = pendingReturns[msg.sender];
74 | // It is important to set this to zero because the recipient
75 | // can call this function again as part of the receiving call
76 | // before `send` returns.
77 | pendingReturns[msg.sender] = 0;
78 | if (!msg.sender.send(amount))
79 | throw; // If anything fails, this will revert the changes above
80 | }
81 |
82 | /// End the auction and send the highest bid
83 | /// to the beneficiary.
84 | function auctionEnd() {
85 | // It is a good guideline to structure functions that interact
86 | // with other contracts (i.e. they call functions or send Ether)
87 | // into three phases:
88 | // 1. checking conditions
89 | // 2. performing actions (potentially changing conditions)
90 | // 3. interacting with other contracts
91 | // If these phases are mixed up, the other contract could call
92 | // back into the current contract and modify the state or cause
93 | // effects (ether payout) to be perfromed multiple times.
94 | // If functions called internally include interaction with external
95 | // contracts, they also have to be considered interaction with
96 | // external contracts.
97 |
98 | // 1. Conditions
99 | if (now <= auctionStart + biddingTime)
100 | throw; // auction did not yet end
101 | if (ended)
102 | throw; // this function has already been called
103 |
104 | // 2. Effects
105 | ended = true;
106 | AuctionEnded(highestBidder, highestBid);
107 |
108 | // 3. Interaction
109 | if (!beneficiary.send(highestBid))
110 | throw;
111 | }
112 |
113 | function () {
114 | // This function gets executed if a
115 | // transaction with invalid data is sent to
116 | // the contract or just ether without data.
117 | // We revert the send so that no-one
118 | // accidentally loses money when using the
119 | // contract.
120 | throw;
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/contracts/Ballot.sol:
--------------------------------------------------------------------------------
1 | /// @title Voting with delegation.
2 | contract Ballot {
3 | // This declares a new complex type which will
4 | // be used for variables later.
5 | // It will represent a single voter.
6 | struct Voter {
7 | uint weight; // weight is accumulated by delegation
8 | bool voted; // if true, that person already voted
9 | address delegate; // person delegated to
10 | uint vote; // index of the voted proposal
11 | }
12 |
13 | // This is a type for a single proposal.
14 | struct Proposal
15 | {
16 | bytes32 name; // short name (up to 32 bytes)
17 | uint voteCount; // number of accumulated votes
18 | }
19 |
20 | address public chairperson;
21 |
22 | // This declares a state variable that
23 | // stores a `Voter` struct for each possible address.
24 | mapping(address => Voter) public voters;
25 |
26 | // A dynamically-sized array of `Proposal` structs.
27 | Proposal[] public proposals;
28 |
29 | /// Create a new ballot to choose one of `proposalNames`.
30 | function Ballot(bytes32[] proposalNames) {
31 | chairperson = msg.sender;
32 | voters[chairperson].weight = 1;
33 |
34 | // For each of the provided proposal names,
35 | // create a new proposal object and add it
36 | // to the end of the array.
37 | for (uint i = 0; i < proposalNames.length; i++) {
38 | // `Proposal({...})` creates a temporary
39 | // Proposal object and `proposals.push(...)`
40 | // appends it to the end of `proposals`.
41 | proposals.push(Proposal({
42 | name: proposalNames[i],
43 | voteCount: 0
44 | }));
45 | }
46 | }
47 |
48 | // Give `voter` the right to vote on this ballot.
49 | // May only be called by `chairperson`.
50 | function giveRightToVote(address voter) {
51 | if (msg.sender != chairperson || voters[voter].voted) {
52 | // `throw` terminates and reverts all changes to
53 | // the state and to Ether balances. It is often
54 | // a good idea to use this if functions are
55 | // called incorrectly. But watch out, this
56 | // will also consume all provided gas.
57 | throw;
58 | }
59 | voters[voter].weight = 1;
60 | }
61 |
62 | /// Delegate your vote to the voter `to`.
63 | function delegate(address to) {
64 | // assigns reference
65 | Voter sender = voters[msg.sender];
66 | if (sender.voted)
67 | throw;
68 |
69 | // Forward the delegation as long as
70 | // `to` also delegated.
71 | // In general, such loops are very dangerous,
72 | // because if they run too long, they might
73 | // need more gas than is available in a block.
74 | // In this case, the delegation will not be executed,
75 | // but in other situations, such loops might
76 | // cause a contract to get "stuck" completely.
77 | while (
78 | voters[to].delegate != address(0) &&
79 | voters[to].delegate != msg.sender
80 | ) {
81 | to = voters[to].delegate;
82 | }
83 |
84 | // We found a loop in the delegation, not allowed.
85 | if (to == msg.sender) {
86 | throw;
87 | }
88 |
89 | // Since `sender` is a reference, this
90 | // modifies `voters[msg.sender].voted`
91 | sender.voted = true;
92 | sender.delegate = to;
93 | Voter delegate = voters[to];
94 | if (delegate.voted) {
95 | // If the delegate already voted,
96 | // directly add to the number of votes
97 | proposals[delegate.vote].voteCount += sender.weight;
98 | }
99 | else {
100 | // If the delegate did not vote yet,
101 | // add to her weight.
102 | delegate.weight += sender.weight;
103 | }
104 | }
105 |
106 | /// Give your vote (including votes delegated to you)
107 | /// to proposal `proposals[proposal].name`.
108 | function vote(uint proposal) {
109 | Voter sender = voters[msg.sender];
110 | if (sender.voted)
111 | throw;
112 | sender.voted = true;
113 | sender.vote = proposal;
114 |
115 | // If `proposal` is out of the range of the array,
116 | // this will throw automatically and revert all
117 | // changes.
118 | proposals[proposal].voteCount += sender.weight;
119 | }
120 |
121 | /// @dev Computes the winning proposal taking all
122 | /// previous votes into account.
123 | function winningProposal() constant
124 | returns (uint winningProposal)
125 | {
126 | uint winningVoteCount = 0;
127 | for (uint p = 0; p < proposals.length; p++) {
128 | if (proposals[p].voteCount > winningVoteCount) {
129 | winningVoteCount = proposals[p].voteCount;
130 | winningProposal = p;
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/contracts/build/Ballot.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b604051610ab1380380610ab1833981016040528080518201919050505b600033600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160016000600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000181905550600090505b815181101561016b57600280548060010182816100f89190610173565b916000526020600020906002020160005b604060405190810160405280868681518110151561012357fe5b906020019060200201516000191681526020016000815250909190915060008201518160000190600019169055602082015181600101555050505b80806001019150506100db565b5b50506101d5565b8154818355818115116101a05760020281600202836000526020600020918201910161019f91906101a5565b5b505050565b6101d291905b808211156101ce57600060008201600090556001820160009055506002016101ab565b5090565b90565b6108cd806101e46000396000f30060606040523615610081576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630121b93f14610083578063013cf08b146100a35780632e4176cf146100e65780635c19a95c14610138578063609ff1bd1461016e5780639e7b8d6114610194578063a3ec138d146101ca575bfe5b341561008b57fe5b6100a16004808035906020019091905050610259565b005b34156100ab57fe5b6100c16004808035906020019091905050610319565b6040518083600019166000191681526020018281526020019250505060405180910390f35b34156100ee57fe5b6100f661034d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561014057fe5b61016c600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610373565b005b341561017657fe5b61017e6106be565b6040518082815260200191505060405180910390f35b341561019c57fe5b6101c8600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610745565b005b34156101d257fe5b6101fe600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610844565b60405180858152602001841515151581526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200194505050505060405180910390f35b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff16156102b857610000565b60018160010160006101000a81548160ff02191690831515021790555081816002018190555080600001546002838154811015156102f257fe5b906000526020600020906002020160005b50600101600082825401925050819055505b5050565b60028181548110151561032857fe5b906000526020600020906002020160005b915090508060000154908060010154905082565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002091508160010160009054906101000a900460ff16156103d457610000565b5b600073ffffffffffffffffffffffffffffffffffffffff16600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415801561050257503373ffffffffffffffffffffffffffffffffffffffff16600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b1561057157600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1692506103d5565b3373ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156105aa57610000565b60018260010160006101000a81548160ff021916908315150217905550828260010160016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060010160009054906101000a900460ff16156106a15781600001546002826002015481548110151561067a57fe5b906000526020600020906002020160005b50600101600082825401925050819055506106b8565b816000015481600001600082825401925050819055505b5b505050565b60006000600060009150600090505b60028054905081101561073f57816002828154811015156106ea57fe5b906000526020600020906002020160005b506001015411156107315760028181548110151561071557fe5b906000526020600020906002020160005b506001015491508092505b5b80806001019150506106cd565b5b505090565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415806107ee5750600160008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900460ff165b156107f857610000565b6001600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001819055505b50565b60016020528060005260406000206000915090508060000154908060010160009054906101000a900460ff16908060010160019054906101000a900473ffffffffffffffffffffffffffffffffffffffff169080600201549050845600a165627a7a72305820e8c4b61e79292c26738d22f5e6776af18bb3a4fada27400684670263b82f9d650029
--------------------------------------------------------------------------------
/contracts/BlindAuction.sol:
--------------------------------------------------------------------------------
1 | contract BlindAuction {
2 | struct Bid {
3 | bytes32 blindedBid;
4 | uint deposit;
5 | }
6 |
7 | address public beneficiary;
8 | uint public auctionStart;
9 | uint public biddingEnd;
10 | uint public revealEnd;
11 | bool public ended;
12 |
13 | mapping(address => Bid[]) public bids;
14 |
15 | address public highestBidder;
16 | uint public highestBid;
17 |
18 | // Allowed withdrawals of previous bids
19 | mapping(address => uint) pendingReturns;
20 |
21 | event AuctionEnded(address winner, uint highestBid);
22 |
23 | /// Modifiers are a convenient way to validate inputs to
24 | /// functions. `onlyBefore` is applied to `bid` below:
25 | /// The new function body is the modifier's body where
26 | /// `_` is replaced by the old function body.
27 | modifier onlyBefore(uint _time) { if (now >= _time) throw; _; }
28 | modifier onlyAfter(uint _time) { if (now <= _time) throw; _; }
29 |
30 | function BlindAuction(
31 | uint _biddingTime,
32 | uint _revealTime,
33 | address _beneficiary
34 | ) {
35 | beneficiary = _beneficiary;
36 | auctionStart = now;
37 | biddingEnd = now + _biddingTime;
38 | revealEnd = biddingEnd + _revealTime;
39 | }
40 |
41 | /// Place a blinded bid with `_blindedBid` = sha3(value,
42 | /// fake, secret).
43 | /// The sent ether is only refunded if the bid is correctly
44 | /// revealed in the revealing phase. The bid is valid if the
45 | /// ether sent together with the bid is at least "value" and
46 | /// "fake" is not true. Setting "fake" to true and sending
47 | /// not the exact amount are ways to hide the real bid but
48 | /// still make the required deposit. The same address can
49 | /// place multiple bids.
50 | function bid(bytes32 _blindedBid)
51 | onlyBefore(biddingEnd)
52 | {
53 | bids[msg.sender].push(Bid({
54 | blindedBid: _blindedBid,
55 | deposit: msg.value
56 | }));
57 | }
58 |
59 | /// Reveal your blinded bids. You will get a refund for all
60 | /// correctly blinded invalid bids and for all bids except for
61 | /// the totally highest.
62 | function reveal(
63 | uint[] _values,
64 | bool[] _fake,
65 | bytes32[] _secret
66 | )
67 | onlyAfter(biddingEnd)
68 | onlyBefore(revealEnd)
69 | {
70 | uint length = bids[msg.sender].length;
71 | if (
72 | _values.length != length ||
73 | _fake.length != length ||
74 | _secret.length != length
75 | ) {
76 | throw;
77 | }
78 |
79 | uint refund;
80 | for (uint i = 0; i < length; i++) {
81 | var bid = bids[msg.sender][i];
82 | var (value, fake, secret) =
83 | (_values[i], _fake[i], _secret[i]);
84 | if (bid.blindedBid != sha3(value, fake, secret)) {
85 | // Bid was not actually revealed.
86 | // Do not refund deposit.
87 | continue;
88 | }
89 | refund += bid.deposit;
90 | if (!fake && bid.deposit >= value) {
91 | if (placeBid(msg.sender, value))
92 | refund -= value;
93 | }
94 | // Make it impossible for the sender to re-claim
95 | // the same deposit.
96 | bid.blindedBid = 0;
97 | }
98 | if (!msg.sender.send(refund))
99 | throw;
100 | }
101 |
102 | // This is an "internal" function which means that it
103 | // can only be called from the contract itself (or from
104 | // derived contracts).
105 | function placeBid(address bidder, uint value) internal
106 | returns (bool success)
107 | {
108 | if (value <= highestBid) {
109 | return false;
110 | }
111 | if (highestBidder != 0) {
112 | // Refund the previously highest bidder.
113 | pendingReturns[highestBidder] += highestBid;
114 | }
115 | highestBid = value;
116 | highestBidder = bidder;
117 | return true;
118 | }
119 |
120 | /// Withdraw a bid that was overbid.
121 | function withdraw() {
122 | var amount = pendingReturns[msg.sender];
123 | // It is important to set this to zero because the recipient
124 | // can call this function again as part of the receiving call
125 | // before `send` returns (see the remark above about
126 | // conditions -> effects -> interaction).
127 | pendingReturns[msg.sender] = 0;
128 | if (!msg.sender.send(amount))
129 | throw; // If anything fails, this will revert the changes above
130 | }
131 |
132 | /// End the auction and send the highest bid
133 | /// to the beneficiary.
134 | function auctionEnd()
135 | onlyAfter(revealEnd)
136 | {
137 | if (ended)
138 | throw;
139 | AuctionEnded(highestBidder, highestBid);
140 | ended = true;
141 | // We send all the money we have, because some
142 | // of the refunds might have failed.
143 | if (!beneficiary.send(this.balance))
144 | throw;
145 | }
146 |
147 | function () {
148 | throw;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/slides/10_Web3_JavaScript.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Web3 JavaScript Ðapp API
4 |
5 | ---
6 |
7 | ## Reference
8 |
9 | https://github.com/ethereum/wiki/wiki/JavaScript-API
10 |
11 | ---
12 |
13 | ## Web3
14 |
15 | - Github: https://github.com/ethereum/web3.js
16 |
17 | - JavaScript library
18 |
19 | - 透過 RPC 與 Ethereum 溝通
20 |
21 | - web3: 一般工具函式
22 |
23 | - web3.eth: Ethereum blockchain 函式
24 |
25 | - web3.net: 網路狀態
26 |
27 | - web3.ssh: Whisper 函式 (略過)
28 |
29 | ---
30 |
31 | ## 安裝 Web3
32 |
33 | - npm: `npm install web3`
34 |
35 | - meteor: `meteor add ethereum:web3`
36 | - Ðapp 開發介紹將使用meteor
37 |
38 | ---
39 |
40 | ## 啟用 RPC
41 |
42 | 選擇其中一種方式:
43 |
44 | - Geth 指令:啟用時帶入下列參數:
45 |
46 | `--rpc --rpccorsdomain "*" --rpcapi "eth,net,web3"`
47 |
48 | - Geth console:
49 |
50 | `admin.startRPC("0.0.0.0", 8545, "*","eth,net,web3")`
51 |
52 | - 直接使用 Mist browser
53 |
54 | Develop -> Toggle Develop Tools -> Mist UI -> `web3.currentProvider`
55 |
56 | - 直接使用 MetaMask
57 |
58 | View -> Developer -> JavaScript Console -> `web3.currentPovider`
59 |
60 | - Web3 library supported RPC APIs: `eth, db, net, personal`
61 |
62 | https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console
63 |
64 | ---
65 |
66 |
67 | ## Web3 連線
68 |
69 |
70 | ```Javascript
71 | if (typeof web3 !== 'undefined') {
72 | web3 = new Web3(web3.currentProvider);
73 | } else {
74 | // set the provider you want from Web3.providers
75 | web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
76 | }
77 | ```
78 |
79 | ---
80 |
81 | ## 同步呼叫
82 |
83 | ```Javascript
84 | var block = web3.eth.getBlock(48);
85 | console.log(block);
86 | ```
87 |
88 | ---
89 |
90 | ## 非同步呼叫 - 使用 callbacks
91 |
92 | ```Javascript
93 | web3.eth.getBlock(48, function(error, result){
94 | if(!error)
95 | console.log(result)
96 | else
97 | console.error(error);
98 | });
99 |
100 | ```
101 |
102 | ---
103 |
104 | ## BigNumber (1/2)
105 |
106 | JavaScript 無法處理 big number
107 | ```JavaScript
108 | Number.MAX_SAFE_INTEGER
109 | 9007199254740991
110 | ```
111 |
112 | Ethereum 中最大的數字 uint256: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
113 |
114 | Web3 回傳的數值都使用 bignumber.js
115 | https://github.com/MikeMcl/bignumber.js/
116 |
117 | ---
118 |
119 | ## BigNumber (2/2)
120 |
121 | ```Javascript
122 | var balance = new BigNumber('131242344353464564564574574567456');
123 | balance.plus(21).toString(10); // toString(10) converts it to a number string
124 | // "131242344353464564564574574567477"
125 | ```
126 |
127 | __Note__: 浮點數只支援到20位,所以盡量都使用Wei(Ethereum貨幣中最小的單位)
128 | ```Javascript
129 | var balance = new BigNumber('13124.234435346456466666457455567456');
130 | balance.plus(21).toString(10); // toString(10) converts it to a number string, but can only show max 20 floating points
131 | // "13145.23443534645646666646" // you number would be cut after the 20 floating point
132 | ```
133 |
134 | ---
135 |
136 | ## Web3 所有函式列表
137 |
138 | https://github.com/ethereum/wiki/wiki/JavaScript-API#web3js-api-reference
139 |
140 | ---
141 |
142 | ## Web3 常用工具函式
143 |
144 | - 單位轉換:(http://ether.fund/tool/converter)
145 |
146 | ```Javascript
147 | var weiValue = web3.toWei('12', 'ether');
148 | var value = web3.fromWei(weiValue, 'ether');
149 | ```
150 |
151 | - 編碼:
152 |
153 | ```Javascript:
154 | var str = web3.toHex({test: 'test'});
155 | console.log(str); // '0x7b22746573742
156 | web3.toAscii(str);
157 | web3.sha3(str);
158 | ```
159 |
160 | ---
161 |
162 | ## Web3 常用 eth 函式 - 區塊鏈資訊
163 |
164 | ```Javascript
165 | var callback = function(error, result){
166 | if(!error)
167 | console.log(result);
168 | else
169 | console.error(error);
170 | };
171 | web3.eth.getBlockNumber(callback);
172 | web3.eth.getBlock(10, callback);
173 | web3.eth.getBlock("0xda882aeff30f59eda9da2b3ace3023366ab9d4219b5a83cdd589347baae8678e", callback);
174 | ```
175 |
176 | ---
177 |
178 | ## Web3 常用 eth 函式 - 交易函式
179 |
180 | ```Javascript
181 | web3.eth.sendTransaction({value: 123, to: "0x764248D16C713Cb168ddfB5a5456fBC9F9e7357b", gas: 40000}, callback);
182 | web3.eth.getTransaction('0xcc82f65ac8c62c1bc0337aeee5b5b7db33b1eacfe9706af178d9113c5827cd42', callback);
183 | web3.eth.getTransactionReceipt('0xcc82f65ac8c62c1bc0337aeee5b5b7db33b1eacfe9706af178d9113c5827cd42', callback);
184 |
185 | ```
186 |
187 | ---
188 |
189 | ## Web3 常用 eth 函式 - 合約函式
190 |
191 | 參考: ClientReceipt.sol, watch-client-receipt.js
192 |
193 | ``` Javascript
194 | web3.eth.contract(abiArray)
195 | web3.eth.contract.myMethod()
196 | web3.eth.contract.myEvent()
197 | ```
198 |
199 | ```Javascript
200 | var abi = [{"constant":false,"inputs":[{"name":"_id","type":"bytes32"}],"name":"deposit","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_id","type":"bytes32"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Deposit","type":"event"}];
201 | var ClientReceipt = web3.eth.contract(abi);
202 | var clientReceipt = ClientReceipt.at("0x32cb389a408cb79ab1e2d23bf1a454f4420f80b2");
203 | var event = clientReceipt.Deposit();
204 | event.watch(function(error, result){
205 | console.log(error, result);
206 | console.log("Deposit id: " + result.args._id);
207 | event.stopWatching();
208 | });
209 | clientReceipt.deposit.sendTransaction(123, {gas: 50000},callback);
210 |
211 | ```
212 |
--------------------------------------------------------------------------------
/contracts/build/BlindAuction.bin:
--------------------------------------------------------------------------------
1 | 6060604052341561000c57fe5b604051606080610c0a833981016040528080519060200190919080519060200190919080519060200190919050505b80600060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055504260018190555082420160028190555081600254016003819055505b5050505b610b5f806100ab6000396000f300606060405236156100b8576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806301495c1c146100cd57806312fa6feb1461012f5780632a24f46c1461015957806338af3eed1461016b5780633ccfd60b146101bd578063423b217f146101cf5780634f245ef7146101f5578063900f080a1461021b57806391f90157146102f2578063957bb1e014610344578063a6e6647714610368578063d57bde791461038e575b34156100c057fe5b6100cb5b610000565b565b005b34156100d557fe5b61010a600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103b4565b6040518083600019166000191681526020018281526020019250505060405180910390f35b341561013757fe5b61013f6103f5565b604051808215151515815260200191505060405180910390f35b341561016157fe5b610169610408565b005b341561017357fe5b61017b61055e565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156101c557fe5b6101cd610584565b005b34156101d757fe5b6101df610654565b6040518082815260200191505060405180910390f35b34156101fd57fe5b61020561065a565b6040518082815260200191505060405180910390f35b341561022357fe5b6102f06004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610660565b005b34156102fa57fe5b6103026108cd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b341561034c57fe5b6103666004808035600019169060200190919050506108f3565b005b341561037057fe5b6103786109a8565b6040518082815260200191505060405180910390f35b341561039657fe5b61039e6109ae565b6040518082815260200191505060405180910390f35b6005602052816000526040600020818154811015156103cf57fe5b906000526020600020906002020160005b91509150508060000154908060010154905082565b600460009054906101000a900460ff1681565b600354804211151561041957610000565b600460009054906101000a900460ff161561043357610000565b7fdaec4582d5d9595688c8c98545fdd1c696d41c6aeaeb636737e84ed2f5c00eda600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600754604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390a16001600460006101000a81548160ff021916908315150217905550600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc3073ffffffffffffffffffffffffffffffffffffffff16319081150290604051809050600060405180830381858888f19350505050151561055957610000565b5b5b50565b600060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000600860003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051809050600060405180830381858888f19350505050151561065057610000565b5b50565b60025481565b60015481565b6000600060006000600060006000600254804211151561067f57610000565b600354804210151561069057610000565b600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509850888c511415806106e65750888b5114155b806106f25750888a5114155b156106fc57610000565b600096505b8887101561087957600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208781548110151561075557fe5b906000526020600020906002020160005b5095508b8781518110151561077757fe5b906020019060200201518b8881518110151561078f57fe5b906020019060200201518b898151811015156107a757fe5b906020019060200201519450945094508484846040518084815260200183151515157f0100000000000000000000000000000000000000000000000000000000000000028152600101826000191660001916815260200193505050506040518091039020600019168660000154600019161415156108245761086c565b8560010154880197508315801561083f575084866001015410155b1561085a5761084e33866109b4565b156108595784880397505b5b60006001028660000181600019169055505b8680600101975050610701565b3373ffffffffffffffffffffffffffffffffffffffff166108fc899081150290604051809050600060405180830381858888f1935050505015156108bc57610000565b5b5b505b5050505050505050505050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600254804210151561090457610000565b600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080548060010182816109559190610ad1565b916000526020600020906002020160005b6040604051908101604052808660001916815260200134815250909190915060008201518160000190600019169055602082015181600101555050505b5b5050565b60035481565b60075481565b6000600754821115156109ca5760009050610acb565b6000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16141515610a7e5760075460086000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b8160078190555082600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600190505b92915050565b815481835581811511610afe57600202816002028360005260206000209182019101610afd9190610b03565b5b505050565b610b3091905b80821115610b2c5760006000820160009055600182016000905550600201610b09565b5090565b905600a165627a7a72305820cbf27fe851ff6a486ad595a12c02c25a48c70715a9720512a532c65ae76cdbca0029
--------------------------------------------------------------------------------
/slides/9_Dapps_Development.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Dapps Development
4 |
5 | ---
6 |
7 | ## What are Dapps
8 |
9 | - Dapps - decentralized applications
10 |
11 | - Ethereum Dapps - applications interact with Ethereum blockchain
12 |
13 | ---
14 |
15 | ## Development environment
16 |
17 | - Ethereum RPC: (Geth, Mist, MetaMask)
18 |
19 | - Library: Web3
20 |
21 | - Framework: Meteor, Truffle
22 |
23 | - We will focus on __Meteor__ in this lecture
24 |
25 | - For __Truffle__ please see [Ethereum Development Environment and Tools](https://amisamity.github.io/contract-training/slides/2_Ethereum_Development_Environment_and_Tools.md.html)
26 |
27 | ---
28 |
29 | ## Web3 API Connection
30 |
31 | - Geth: ` admin.startRPC("0.0.0.0", 8545, "*","db,eth,net,web3,personal")`
32 | ```Javascript
33 | web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
34 | ```
35 | - Mist: `http://localhost:3000/`
36 | Will be replaced with IpcProvider
37 | ```Javascript
38 | > web3.currentProvider
39 | > IpcProvider
40 | ```
41 | - MetaMask: `http://localhost:3000/` in Chrome
42 | Will be replaced with MetamaskInpageProvider
43 | ```Javascript
44 | > web3.currentProvider
45 | > MetamaskInpageProvider
46 | ```
47 |
48 | ---
49 |
50 | ## Dapp example (Meteor): Ethereum Wallet
51 |
52 | ```
53 | git clone git@github.com:ethereum/meteor-dapp-wallet.git
54 | npm install
55 | cd meteor-dapp-wallet/app
56 | meteor
57 | ```
58 |
59 | - Client options:
60 |
61 | - Mist browser
62 |
63 | - Chrome with MetaMask
64 |
65 | - Browser with Geth RPC
66 |
67 | ---
68 |
69 | ## Meteor
70 |
71 | - Framework for building javascript apps.
72 | https://www.meteor.com/
73 |
74 | ---
75 |
76 | ## Meteor - get started
77 |
78 | - Install:
79 |
80 | `curl https://install.meteor.com/ | sh`
81 |
82 | - Create app
83 |
84 | `meteor create myDapp`
85 |
86 | - Install app packages
87 |
88 | `cd myDapp && npm install`
89 |
90 | - Run
91 |
92 | `meteor`
93 |
94 | ---
95 |
96 | ## Meteor - add Libraries
97 |
98 | - Required:
99 |
100 | ```
101 | meteor add ethereum:web3
102 | meteor add less
103 | meteor add ethereum:dapp-styles
104 | ```
105 |
106 | - Optionals
107 |
108 | ```
109 | meteor add ethereum:tools
110 | meteor add ethereum:elements
111 | meteor add ethereum:accounts
112 | meteor add ethereum:blocks
113 | meteor add frozeman:template-var
114 | meteor add frozeman:persistent-minimongo2
115 | ```
116 |
117 | ---
118 |
119 | ## Meteor - ethereum libraries
120 |
121 | - `ethereum:tools`: https://github.com/ethereum/meteor-package-tools
122 |
123 | - `ethereum:blocks`: https://github.com/ethereum/meteor-package-blocks
124 |
125 | - `ethereum:elements`: https://github.com/ethereum/meteor-package-elements
126 |
127 | - `ethereum:accounts:`: https://github.com/ethereum/meteor-package-accounts
128 |
129 | ---
130 |
131 | ## Meteor - file structure
132 |
133 | - __client__ : loaded by the client. Most of our files go.
134 |
135 | - __lib__: loaded before other files in the same folder.
136 |
137 | - __public__: assets available on the root of the Dapp.
138 |
139 | ---
140 |
141 | ## Meteor - add web3 Library
142 |
143 | ```
144 | mkdir lib
145 | cd lib && touch init.js
146 | ```
147 |
148 | Add following:
149 |
150 | ```Javascript
151 | if(typeof web3 === 'undefined')
152 | web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));
153 | ```
154 |
155 | ---
156 |
157 | ## Meteor - check web3 connection
158 |
159 | - Run meteor:
160 |
161 | ```bash
162 | meteor
163 | ```
164 |
165 | - Open chrome:
166 | View -> Developer -> Javascript Console
167 |
168 | ```bash
169 | web3.eth.accounts
170 | ```
171 |
172 | ---
173 |
174 | ## Meteor - styling
175 |
176 | - rename main.css to main.less
177 |
178 | - add following
179 |
180 | ```Javascript
181 | // libs
182 | @import '{ethereum:dapp-styles}/dapp-styles.less';
183 |
184 | ```
185 |
186 | ---
187 |
188 | ## Meteor - using ethereum packages (1/2)
189 |
190 | - In main.html:
191 | - Add `{{> blockInfo}}` in `body` section.
192 | - Add following in the end
193 |
194 | ```html
195 |
196 | Block height: {{currentBlock}}
197 |
198 | ```
199 |
200 | ---
201 |
202 | ## Meteor - using ethereum packages (2/2)
203 |
204 | - In main.js:
205 |
206 | ```Javascript
207 | Template.blockInfo.onCreated(function blockInfoOnCreated(){
208 | EthBlocks.init();
209 | });
210 |
211 | Template.blockInfo.helpers({
212 | currentBlock(){
213 | return EthBlocks.latest.number;
214 | },
215 | });
216 | ```
217 |
218 | ---
219 |
220 | ## OneValue with Meteor - OneValue Contract
221 |
222 | Deployed at: `0xe07438274839E9793baEAaa757F695CfED4A9e26`
223 |
224 | ```Javascript
225 | pragma solidity ^0.4.4;
226 |
227 | contract OneValue {
228 | uint256 value;
229 |
230 | function OneValue(uint256 initValue) {
231 | value = initValue;
232 | }
233 |
234 | function setValue(uint256 v) {
235 | value = v;
236 | }
237 |
238 | function getValue() constant returns (uint256 result) {
239 | return value;
240 | }
241 | }
242 | ```
243 |
244 | ---
245 |
246 | ## OneValue with Meteor - interaction (1/2)
247 |
248 | OneValue instance:
249 |
250 | ```Javascript
251 | var abi = [{"constant":true,"inputs":[],"name":"getValue","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"v","type":"uint256"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"initValue","type":"uint256"}],"type":"constructor"}];;
252 | var OneValueContract = web3.eth.contract(abi);
253 | this.contractAddress = '0xe07438274839E9793baEAaa757F695CfED4A9e26';
254 | var oneValue = this.oneValue = OneValueContract.at(this.contractAddress);
255 | ```
256 |
257 | ---
258 |
259 | ## OneValue with Meteor - interaction (1/2)
260 |
261 | - Get value:
262 | ```Javascript
263 | oneValue.getValue(function(err, res){
264 | currentValue.set(res.toNumber());
265 | });
266 | ```
267 |
268 | - Set value:
269 | ```Javascript
270 | oneValue.setValue.sendTransaction(_.toNumber(newValue), function(err, res){
271 | message.set("Transaction hash: " + res);
272 | });
273 | ```
274 |
275 | ---
276 |
277 | ## Deployment - Meteor Galaxy
278 |
279 | - Create account: https://galaxy.meteor.com/
280 |
281 | - Pricing: starts from $0.04/ hour
282 |
283 | - Deploy doc: http://galaxy-guide.meteor.com/
284 |
285 | - Quick command: `meteor deploy .meteorapp.com`
286 |
287 | ---
288 |
289 | ## Meteor galaxy dashboard
290 |
291 | 
292 |
--------------------------------------------------------------------------------
/slides/2_Ethereum_Development_Environment_and_Tools_03202017.md:
--------------------------------------------------------------------------------
1 | ## 以太坊開發工具
2 | - __結點 / 錢包__
3 | - 智能合約開發工具,函式庫
4 |
5 | ---
6 |
7 | ## 圖形化錢包 / 節點:Mist/Ethereum wallet
8 | - 錢包
9 | - Ðapps 瀏覽器
10 | - 本地節點
11 | - Github: https://github.com/ethereum/mist
12 | - Installable binaries: https://github.com/ethereum/mist/releases
13 |
14 | ---
15 |
16 | ## Ethereum wallet demo
17 | - Network: mainnet and testnet
18 | - Mining: testnet only (can still enable it via console)
19 | - Wallets
20 | - Send
21 | - Contracts
22 |
23 | ---
24 |
25 | ## 雲端錢包: MetaMask
26 | - 雲端節點: 不須等待資料同步
27 | - MetaMask: https://metamask.io/
28 | 
29 |
30 | ---
31 |
32 | ## Geth 節點
33 | - 以太坊 Golang 實作節點
34 | - Mist 預設使用節點
35 | - Ethstats 上大部分是 `Geth` 和 `Parity`
36 | - https://ethstats.net/
37 |
38 | ---
39 |
40 | ## 利用 geth 連上 mainnet
41 | ```bash
42 | geth --fast \
43 | --datadir "~/.eth/mainnet" \
44 | --rpc --rpccorsdomain "*" \
45 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
46 | --rpcapi "db,eth,net,web3,personal" \
47 | --rpcport "8547" \
48 | --port "30305" \
49 | console
50 | ```
51 |
52 | ---
53 |
54 | ## 利用 geth 連上 testnet
55 | ```bash
56 | geth --fast \
57 | --datadir "~/.eth/testnet" \
58 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
59 | --rpc --rpccorsdomain "*" \
60 | --rpcapi "db,eth,net,web3,personal" \
61 | --rpcport "8546" \
62 | --port "30304" \
63 | --testnet \
64 | console
65 | ```
66 |
67 | ---
68 |
69 | ## 利用 geth 跑私有鏈
70 | - 使用 `networkid`
71 |
72 | ```bash
73 | geth --fast \
74 | --datadir "~/.eth/privnet" \
75 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
76 | --rpc --rpccorsdomain "*" \
77 | --rpcapi "db,eth,net,web3,personal" \
78 | --rpcport "8545" \
79 | --port "30303" \
80 | --networkid "12345" \
81 | --nodiscover \
82 | console
83 | ```
84 |
85 | ---
86 |
87 | ## 利用 geth 跑私有鏈
88 | - 使用 `networkid`及`genesis.json`
89 |
90 | ```JavaScript
91 | {
92 | "nonce": "0x0000000000000042",
93 | "timestamp": "0x0",
94 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
95 | "extraData": "Any extra data 134ADFAD",
96 | "gasLimit": "0x47e7c4",
97 | "difficulty": "0x9c40",
98 | "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
99 | "coinbase": "0x3333333333333333333333333333333333333333",
100 | "alloc": {
101 | "0x60cafee22ae353ac9de07852a682558c9bb84e61": {
102 | "balance": "999999999999999999999999999999999"
103 | }
104 | }
105 | }
106 | ```
107 |
108 | ---
109 |
110 | ## 利用 geth 跑私有鏈
111 | - 使用 `networkid`及`genesis.json`
112 |
113 | Init blockchain:
114 | ```bash
115 | geth --datadir "~/.eth/privnet2" \
116 | init "/PATH/TO/genesis.json"
117 | ```
118 |
119 | Run:
120 | ```bash
121 | geth --fast \
122 | --datadir "~/.eth/privnet2" \
123 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
124 | --rpc --rpccorsdomain "*" \
125 | --rpcapi "db,eth,net,web3,personal" \
126 | --rpcport "8545" \
127 | --port "30303" \
128 | --networkid "12345" \
129 | --nodiscover \
130 | console
131 | ```
132 |
133 | ---
134 |
135 | ## 以太坊節點
136 | - 同步區塊鏈網路資料:建立本地端資料備份
137 | - 錢包:發送交易
138 | - 提供 API 接口:RPC, IPC, WebSocket
139 |
140 | ---
141 |
142 | ## 以太坊開發工具
143 | - 結點 / 錢包
144 | - __智能合約開發工具,函式庫__
145 |
146 | ---
147 |
148 | ## Simple contract: OneValueContract
149 | ```Javascript
150 | contract OneValue {
151 | uint256 value;
152 |
153 | function OneValue(uint256 initValue) {
154 | value = initValue;
155 | }
156 |
157 | function setValue(uint256 v) {
158 | value = v;
159 | }
160 |
161 | function getValue() constant returns (uint256 result){
162 | return value;
163 | }
164 | }
165 | ```
166 |
167 | ---
168 |
169 | ## Solidity compiler: solc
170 | - solcjs
171 | ```bash
172 | npm install solc -g
173 | ```
174 |
175 | - solc: https://github.com/ethereum/solidity
176 | ```bash
177 | git clone --recursive https://github.com/ethereum/solidity.git
178 | cd solidity
179 | mkdir build
180 | cd build
181 | cmake .. && make && make install
182 | ```
183 |
184 | ---
185 |
186 | ## Compile contract
187 | - Browser-Solidity (Remix IDE):
188 | https://ethereum.github.io/browser-solidity/
189 | - solc
190 | ```bash
191 | solc --abi --bin --gas -o ./build OneValue.sol
192 | ```
193 |
194 | ---
195 |
196 | ## Web3
197 | - Web3: ethereum compatible [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API) which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) spec
198 |
199 | - 安裝: `npm install web3`
200 |
201 | ---
202 |
203 | ## Web3 使用方式
204 | - Enable rpc in console:
205 | ```Javascript
206 | admin.startRPC("0.0.0.0", 8545, "*","db,eth,net,web3,personal")
207 | ```
208 | - Example code: `node web3-test.js`
209 | ```Javascript
210 | var Web3 = require('web3');
211 | var web3 = new Web3(
212 | new Web3.providers.HttpProvider("http://localhost:8545"));
213 |
214 | web3.eth.getBlock(48, function(error, result){
215 | if(!error)
216 | console.log(result)
217 | else
218 | console.error(error);
219 | });
220 | ```
221 |
222 | ---
223 | ## Contract deployment
224 | - Mist
225 | - Web3
226 |
227 | ---
228 | ## Deploy contract with Mist
229 | - Contracts → Deploy new contract → Paste code and deploy
230 | - Remix IDE → Create
231 |
232 | ---
233 |
234 | ## Deploy contract with Web3
235 | - Deploy to testnet:
236 | ```Javascript
237 | node deploy-contract-test.js
238 | ```
239 |
240 | ---
241 |
242 | ## Deploy contract with Web3 程式碼節錄
243 | - Example code (partial):
244 | ```Javascript
245 | var abi = ...
246 | var evmCode = ...
247 | var OneValueContract = web3.eth.contract(abi);
248 | var oneValue = OneValueContract.new(initValue,
249 | {from:addr, data: evmCode, gas: 4700000},
250 | function(error, contract){
251 | ...
252 | }
253 | );
254 | ```
255 | ---
256 |
257 | ## Testrpc
258 |
259 | - Fast Ethereum RPC client for testing and development. (RPC mock)
260 | - 安裝:
261 | ```bash
262 | npm install -g ethereumjs-testrpc
263 | ```
264 | - 使用:
265 | ```bash
266 | testrpc -p 8547
267 | ```
268 |
269 | ---
270 |
271 | ## Web3 連線到 Testrpc
272 | - Connect with Web3:
273 | ```bash
274 | node web3-testrpc.js
275 | ```
276 |
277 | ```Javascript
278 | var Web3 = require('web3');
279 | var TestRPC = require("ethereumjs-testrpc");
280 | var web3 = new Web3(TestRPC.provider());
281 | web3.eth.getAccounts(function(e, accts){
282 | console.log("error:", e);
283 | console.log("accounts:", accts);
284 | process.exit(0);
285 | });
286 | ```
287 |
288 | ---
289 |
290 | ## Deploy contract with Web3
291 | - Deploy to testrpc:
292 | ```Javascript
293 | node deploy-contract-testrpc.js
294 | ```
295 |
296 | ---
297 |
298 | ## 與智能合約互動 (Express + Web3)
299 |
300 | - Example (partial):
301 |
302 | ```Javascript
303 | var abi = ... var OneValueContract = web3.eth.contract(abi);
304 | var contractAddress = '0x36274a6286c9cf3c8e09c85c5bfa572a8827fddc'; //Testnet
305 | var oneValue = OneValueContract.at(contractAddress);
306 |
307 | app.get('/', function (req, res) {
308 | res.send(
309 | 'OneValue Instance: ' + contractAddress + "\n" +
310 | 'Value: '+ oneValue.getValue() + "\n");
311 | });
312 |
313 | app.listen(3000)
314 | ```
315 |
316 | - Run: `node express-example.js`
317 | - Test: `curl http://localhost:3000`
318 |
--------------------------------------------------------------------------------
/slides/8_Insurance_Examples.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Insurance Examples - Flight Delay
4 |
5 | ---
6 |
7 | ## Cryptocoins: Blockchain to Disrupt Air Travel and Insurance with FlightDelay
8 |
9 | - FlightDelay: https://fdd.etherisc.com/
10 | - Github: https://github.com/etherisc/flightDelay
11 | - Cryptocoins news article: https://www.cryptocoinsnews.com/blockchain-disrupt-air-travel-insurance-flightdelay/
12 |
13 | ---
14 | ## FlightDelay example from Cryptocoins News
15 | - Picked a random flight and pay 0.5 ETH premium
16 | - No delay: receive nothing
17 | - Delay for 15 to 29 minutes (20.34%): receive 0.95 ETH
18 | 
19 |
20 | ---
21 | ## FlightDelay DApp Demo - MetaMask
22 | - MetaMask: https://metamask.io/
23 | 
24 |
25 | ---
26 | ## FlightDelay DApp Demo - Mist
27 | - Mist: https://github.com/ethereum/mist/releases
28 | 
29 |
30 | ---
31 |
32 | ## FlightDelay code tracing
33 | - Github: https://github.com/etherisc/flightDelay/blob/master/FlightDelay.sol
34 | - Oraclize: https://github.com/oraclize/ethereum-api
35 | - Underwriting: flight delay probability
36 | - Payout: how much delay
37 | - Flight Stats API: https://developer.flightstats.com/api-docs/
38 |
39 | ---
40 |
41 | ## FlightDelay.sol
42 |
43 | - 使用 Oraclize 取得外部資料:事實上還是由 Oraclize 將外部資料填入智能合約當中。
44 | - 主要兩種 API:
45 | - Ratings: 班機延誤評等 API。用來核保,及計算理賠金額。
46 | - Status: 班機起降狀態 API。用來核賠。
47 |
48 | ```JavaScript
49 | contract FlightDelay is usingOraclize {
50 | ...
51 | string constant oraclize_RatingsBaseUrl =
52 | "[URL] json(https://api.flightstats.com/flex/ratings/rest/v1/json/flight/";
53 | ...
54 | string constant oraclize_StatusBaseUrl =
55 | "[URL] json(https://api.flightstats.com/flex/flightstatus/rest/v2/json/flight/status/";
56 |
57 | ...
58 | }
59 | ```
60 |
61 | ---
62 |
63 | ## FlightDelay.sol - 合約狀態 (1/2)
64 | - Applied: 客戶已經支付保費,但是 oracle 還沒檢查投保班機延誤評等。
65 | - Accepted: oracle 已檢查投保班機評等並承保該保單。
66 | - Revoked: 客戶取消保單,費用扣除手續費後退回給客戶。
67 | - PaidOut: 確認班機延誤並已理賠。
68 | - Expired: 確認班機延誤時間少於 15 分鐘,不理賠。
69 | - Declined: 核保未通過,費用扣除手續費後退回給客戶。
70 | - SendFailed: 退費或是理賠失敗,將金額置入 RiskFund 中。
71 |
72 |
73 | ---
74 |
75 | ## FlightDelay.sol - 合約狀態 (2/2)
76 |
77 | ```Javascript
78 | // 00 01 02 03
79 | enum policyState {Applied, Accepted, Revoked, PaidOut,
80 | // 04 05 06
81 | Expired, Declined, SendFailed}
82 | ```
83 |
84 | ---
85 |
86 | ## FlightDelay.solc - 保單資料結構
87 |
88 | ```Javascript
89 | struct policy {
90 | // 0 - the customer
91 | address customer;
92 | // 1 - premium
93 | uint premium;
94 |
95 | // risk specific parameters:
96 | // 2 - pointer to the risk in the risks mapping
97 | bytes32 riskId;
98 | // 3 - probability weight. this is the central parameter
99 | uint weight;
100 | // 4 - calculated Payout
101 | uint calculatedPayout;
102 | // 5 - actual Payout
103 | uint actualPayout;
104 |
105 | // status fields:
106 | // 6 - the state of the policy
107 | policyState state;
108 | // 7 - time of last state change
109 | uint stateTime;
110 | // 8 - state change message/reason
111 | bytes32 stateMessage;
112 | // 9 - TLSNotary Proof
113 | bytes proof;
114 | }
115 | ```
116 |
117 | ---
118 |
119 | ## FlightDelay.sol - 航班險資料結構
120 |
121 | ```Javascript
122 | struct risk {
123 | // 0 - Airline Code + FlightNumber
124 | string carrierFlightNumber;
125 | // 1 - scheduled departure and arrival time in the format /dep/YYYY/MM/DD
126 | string departureYearMonthDay;
127 | // 2 - the initial arrival time
128 | uint arrivalTime;
129 | // 3 - the final delay in minutes
130 | uint delayInMinutes;
131 | // 4 - the determined delay category (0-5)
132 | uint8 delay;
133 | // 5 - counter; limit the number of identical risks.
134 | uint8 counter;
135 | }
136 | ```
137 |
138 | ---
139 |
140 | ## FlightDelay.sol - 產生保單
141 |
142 | ```JavaScript
143 | function newPolicy(
144 | string _carrierFlightNumber, string _departureYearMonthDay,
145 | uint _departureTime, uint _arrivalTime){
146 | ...
147 | bytes32 riskId = sha3(_carrierFlightNumber, _departureYearMonthDay, _arrivalTime);
148 | risk r = risks[riskId];
149 | ...
150 | uint policyId = policies.length++;
151 | policy p = policies[policyId];
152 | p.customer = msg.sender;
153 | p.premium = bookAndCalcRemainingPremium();
154 | p.riskId = riskId;
155 | ...
156 | r.carrierFlightNumber = _carrierFlightNumber;
157 | r.departureYearMonthDay = _departureYearMonthDay;
158 | r.arrivalTime = _arrivalTime;
159 | ...
160 |
161 | // now we have successfully applied
162 | p.state = policyState.Applied;
163 | p.stateMessage = 'Policy applied by customer';
164 | p.stateTime = now;
165 |
166 | // call oraclize to get Flight Stats; this will also call underwrite()
167 | getFlightStats(policyId, _carrierFlightNumber);
168 | }
169 | ```
170 |
171 | ---
172 |
173 | ## FlightDelay.sol - 取得航班評等資料
174 |
175 | ```Javascript
176 | function getFlightStats( uint _policyId, string _carrierFlightNumber) {
177 |
178 | // call oraclize and retrieve the number of observations from flightstats API
179 | // format https://api.flightstats.com/flex/ratings/rest/v1/json/flight/OS/75?appId=**&appKey=**
180 |
181 | string memory oraclize_url = strConcat(
182 | oraclize_RatingsBaseUrl,
183 | _carrierFlightNumber,
184 | oraclizeRatingsQuery
185 | );
186 |
187 | bytes32 queryId = oraclize_query("nested", oraclize_url, oraclizeGas);
188 | // calculate the spent gas
189 | bookkeeping(acc_OraclizeCosts, acc_Balance, uint((-ledger[acc_Balance]) - int(this.balance)));
190 | oraclizeCallbacks[queryId] = oraclizeCallback(_policyId, oraclizeState.ForUnderwriting, 0);
191 | }
192 | ```
193 |
194 | ---
195 |
196 | ## FlightDelay.sol - 等待 Oraclize 回應以後決定承保或是拒保
197 |
198 | ``` Javascript
199 | function callback_ForUnderwriting(uint _policyId, string _result, bytes _proof)
200 | onlyInState(_policyId, policyState.Applied)
201 | internal {
202 |
203 | var sl_result = _result.toSlice();
204 | ...
205 | if (observations <= minObservations) {
206 | decline(_policyId, 'Declined (too few observations)', _proof);
207 | } else {
208 | uint[6] memory statistics;
209 | // calculate statistics (scaled by 100)
210 | statistics[0] = observations;
211 | ...
212 | // underwrite policy
213 | underwrite(_policyId, statistics, _proof);
214 | }
215 | }
216 | ```
217 |
218 | ---
219 |
220 | ## FlightDelay.sol - 承保,並排程 Oraclize 取得該航班狀態
221 |
222 | ``` Javascript
223 | function underwrite(uint _policyId, uint[6] _statistics, bytes _proof) internal {
224 | policy p = policies[_policyId]; // throws if _policyId invalid
225 | for (uint8 i = 1; i <= 5; i++ ) {
226 | p.weight += weightPattern[i] * _statistics[i];
227 | // 1% = 100 / 100% = 10,000
228 | }
229 | // to avoid div0 in the payout section, we have to make a minimal assumption on p.weight.
230 | if (p.weight == 0) { p.weight = 100000 / _statistics[0]; }
231 | p.proof = _proof;
232 | risk r = risks[p.riskId];
233 |
234 | // schedule payout Oracle
235 | schedulePayoutOraclizeCall(
236 | _policyId,
237 | r.carrierFlightNumber,
238 | r.departureYearMonthDay,
239 | r.arrivalTime + 15 minutes
240 | );
241 |
242 | p.state = policyState.Accepted;
243 | p.stateMessage = 'Policy underwritten by oracle';
244 | p.stateTime = now;
245 | }
246 | ```
247 |
248 | ---
249 |
250 | ## FlightDelay.sol - 排程 Oraclize 取得該航班狀態
251 |
252 | ```JavaScript
253 | function schedulePayoutOraclizeCall(
254 | uint _policyId,
255 | string _carrierFlightNumber,
256 | string _departureYearMonthDay,
257 | uint _oraclizeTime)
258 | internal {
259 |
260 | string memory oraclize_url = strConcat(
261 | oraclize_StatusBaseUrl,
262 | _carrierFlightNumber,
263 | _departureYearMonthDay,
264 | oraclizeStatusQuery
265 | );
266 |
267 | bytes32 queryId = oraclize_query(_oraclizeTime, 'nested', oraclize_url, oraclizeGas);
268 | bookkeeping(acc_OraclizeCosts, acc_Balance, uint((-ledger[acc_Balance]) - int(this.balance)));
269 | oraclizeCallbacks[queryId] = oraclizeCallback(_policyId, oraclizeState.ForPayout, _oraclizeTime);
270 | }
271 | ```
272 |
273 | ---
274 |
275 | ## FlightDelay.sol - 取得 Oraclize 回應並決定是否理賠 (1/2)
276 |
277 | ```Javascript
278 | function callback_ForPayout(bytes32 _queryId, string _result, bytes _proof) internal {
279 | oraclizeCallback memory o = oraclizeCallbacks[_queryId];
280 | uint policyId = o.policyId;
281 | var sl_result = _result.toSlice();
282 | ...
283 | bytes1 status = bytes(sl_result.toString())[0]; // s = L
284 |
285 | // 取消或是改航線
286 | if (status == 'C') {
287 | // flight cancelled --> payout
288 | payOut(policyId, 4, 0);
289 | return;
290 | } else if (status == 'D') {
291 | // flight diverted --> payout
292 | payOut(policyId, 5, 0);
293 | return;
294 | } else if (status != 'L' && status != 'A' && status != 'C' && status != 'D') {
295 | LOG_PolicyManualPayout(policyId, 'Unprocessable status');
296 | return;
297 | }
298 | ...
299 | }
300 | ```
301 |
302 | ---
303 |
304 | ## FlightDelay.sol - 取得 Oraclize 回應並決定是否理賠 (2/2)
305 |
306 | ```Javascript
307 | function callback_ForPayout(bytes32 _queryId, string _result, bytes _proof) internal {
308 | ...
309 | sl_result = _result.toSlice();
310 | bool arrived = sl_result.contains('actualGateArrival'.toSlice());
311 | if (status == 'A' || (status == 'L' && !arrived)) {
312 | // flight still active or not at gate --> reschedule
313 | ...
314 | schedulePayoutOraclizeCall(policyId, r.carrierFlightNumber, r.departureYearMonthDay, o.oraclizeTime + 45 minutes);
315 | } else if (status == 'L' && arrived) {
316 | uint delayInMinutes = ...
317 | if (delayInMinutes < 15) {
318 | payOut(policyId, 0, 0);
319 | } else if (delayInMinutes < 30) {
320 | payOut(policyId, 1, delayInMinutes);
321 | } else if (delayInMinutes < 45) {
322 | payOut(policyId, 2, delayInMinutes);
323 | } else {
324 | payOut(policyId, 3, delayInMinutes);
325 | }
326 | } else { // no delay info
327 | payOut(policyId, 0, 0);
328 | }
329 | }
330 | ```
331 |
--------------------------------------------------------------------------------
/slides/2_Ethereum_Development_Environment_and_Tools.md:
--------------------------------------------------------------------------------
1 | class: center, middle
2 |
3 | # Ethereum Development Environment and Tools
4 |
5 | ---
6 | ## Ethereum and Smart Contract
7 |
8 | - General purpose blockchain
9 |
10 | - Ethereum: TCP/IP = Bitcoin: SMTP
11 |
12 | - Smart contract: logic + data at a specific address
13 |
14 | ---
15 | ## Ethereum accounts
16 |
17 | - External accounts: controlled by public-private key pairs (i.e. humans)
18 | - ether
19 |
20 | - Contract accounts: controlled by the code stored together with the account.
21 | - ether
22 | - code (logic)
23 | - data (storage)
24 |
25 | - EVM treats the two types equally
26 |
27 | ---
28 | ## Simple contract: OneValueContract
29 | ```Javascript
30 | contract OneValue {
31 | uint256 value;
32 |
33 | function OneValue(uint256 initValue) {
34 | value = initValue;
35 | }
36 |
37 | function setValue(uint256 v) {
38 | value = v;
39 | }
40 |
41 | function getValue() constant returns (uint256 result){
42 | return value;
43 | }
44 | }
45 | ```
46 |
47 | ---
48 | ## All in one wallet: Mist/Ethereum Wallet
49 | - The Mist browser is the tool of choice to browse and use Ðapps (decentralized applications).
50 |
51 | - Github: https://github.com/ethereum/mist
52 |
53 | - Installable binaries: https://github.com/ethereum/mist/releases
54 |
55 | ---
56 |
57 | ## Ethereum wallet demo
58 |
59 | - Network: mainnet and testnet
60 |
61 | - Mining: testnet only (can still enable it via console)
62 |
63 | - Wallets
64 |
65 | - Send
66 |
67 | - Contracts
68 |
69 | ---
70 |
71 | ## Mist / Ethereum data location
72 |
73 | - Mist:
74 | - Windows: `%APPDATA%\Mist`
75 |
76 | - Mac: `~/Library/Application Support/Mist`
77 |
78 | - Linux: `~/.config/Mist`
79 |
80 | - Ethereum:
81 |
82 | - Mac: `~/Library/Ethereum`
83 |
84 | ---
85 |
86 | ## In browser wallet - MetaMask
87 |
88 | - MetaMask: https://metamask.io/
89 |
90 | - Chrome plugin: https://goo.gl/8uPYIA
91 |
92 | 
93 |
94 |
95 | ---
96 | ## Geth
97 |
98 | - Ethereum go implementation (Mist is actually using geth)
99 | - `ps -aef | grep geth`
100 |
101 | - Install:
102 | - https://www.ethereum.org/cli
103 |
104 | - Management API:
105 | - https://github.com/ethereum/go-ethereum/wiki/Management-APIs
106 |
107 | - Javascript Console:
108 | - https://github.com/ethereum/go-ethereum/wiki/JavaScript-Console
109 |
110 | ---
111 |
112 | ## Run geth (mainnet)
113 |
114 | ```bash
115 | geth --fast \
116 | --datadir "~/.eth/mainnet" \
117 | --rpc --rpccorsdomain "*" \
118 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
119 | --rpcapi "db,eth,net,web3,personal" \
120 | --rpcport "8547" \
121 | --port "30305" \
122 | console
123 | ```
124 |
125 | ---
126 |
127 | ## Run geth (testnet)
128 |
129 | ```bash
130 | geth --fast \
131 | --datadir "~/.eth/testnet" \
132 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
133 | --rpc --rpccorsdomain "*" \
134 | --rpcapi "db,eth,net,web3,personal" \
135 | --rpcport "8546" \
136 | --port "30304" \
137 | --testnet \
138 | console
139 | ```
140 |
141 | ---
142 |
143 | ## Run geth (private chain)
144 | option 1: use `networkid`
145 |
146 | ```bash
147 | geth --fast \
148 | --datadir "~/.eth/privnet" \
149 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
150 | --rpc --rpccorsdomain "*" \
151 | --rpcapi "db,eth,net,web3,personal" \
152 | --rpcport "8545" \
153 | --port "30303" \
154 | --networkid "12345" \
155 | --nodiscover \
156 | console
157 | ```
158 |
159 | ---
160 |
161 | ## Run geth (private chain)
162 | option 2: use both `networkid` and custom `genesis.json`
163 |
164 | Example genesis.json:
165 |
166 | ```JSON
167 | {
168 | "nonce": "0x0000000000000042",
169 | "timestamp": "0x0",
170 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
171 | "extraData": "Any extra data 134ADFAD",
172 | "gasLimit": "0x47e7c4",
173 | "difficulty": "0x9c40",
174 | "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
175 | "coinbase": "0x3333333333333333333333333333333333333333",
176 | "alloc": {
177 | "0x60cafee22ae353ac9de07852a682558c9bb84e61": {
178 | "balance": "999999999999999999999999999999999"
179 | }
180 | }
181 | }
182 | ```
183 |
184 | ---
185 |
186 | ## Run geth (private chain)
187 | option 2: use both `networkid` and custom `genesis.json`, so we can avoid network id collision.
188 |
189 | Init blockchain:
190 | ```bash
191 | geth --datadir "~/.eth/privnet2" \
192 | init "/PATH/TO/genesis.json"
193 | ```
194 |
195 | Run:
196 | ```bash
197 | geth --fast \
198 | --datadir "~/.eth/privnet2" \
199 | --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \
200 | --rpc --rpccorsdomain "*" \
201 | --rpcapi "db,eth,net,web3,personal" \
202 | --rpcport "8545" \
203 | --port "30303" \
204 | --networkid "12345" \
205 | --nodiscover \
206 | console
207 | ```
208 |
209 | ---
210 | ## Geth API
211 |
212 | - IPC: Unix socket
213 |
214 | - Attach to Mist geth console:
215 | ```
216 | geth attach ipc:~/Library/Ethereum/geth.ipc
217 | ```
218 |
219 | - RPC: HTTP API
220 |
221 | - WebSocket
222 |
223 | ---
224 | ## Solidity compiler: solc
225 |
226 | - solcjs
227 |
228 | ```bash
229 | npm install solc -g
230 | ```
231 |
232 | - solc: https://github.com/ethereum/solidity
233 |
234 | ```bash
235 | git clone --recursive https://github.com/ethereum/solidity.git
236 | cd solidity
237 | mkdir build
238 | cd build
239 | cmake .. && make && make install
240 | ```
241 |
242 | ---
243 | ## Compile contract
244 |
245 | - Browser-Solidity: https://ethereum.github.io/browser-solidity/
246 |
247 | - solc
248 |
249 | ```
250 | solc --abi --bin --gas -o ./build OneValue.sol
251 | ```
252 |
253 | ---
254 |
255 | ## Solidity editor
256 |
257 | - Atom: language-ethereum
258 |
259 | - SublimeText: ethereum
260 |
261 | - Visual Studio: Solidity
262 |
263 | - Remix (formerly Mix) IDE https://github.com/ethereum/remix
264 |
265 | ---
266 |
267 | ## Mist demo - Remix IDE
268 |
269 | 
270 |
271 | ---
272 |
273 | ## Libraries and development tools
274 |
275 | - Web3: https://github.com/ethereum/web3.js
276 |
277 | This is the Ethereum compatible [JavaScript API](https://github.com/ethereum/wiki/wiki/JavaScript-API) which implements the [Generic JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) spec.
278 |
279 | - Testrpc: https://github.com/ethereumjs/testrpc
280 |
281 | Fast Ethereum RPC client for testing and development. (RPC mock)
282 |
283 |
284 | - Truffle: https://github.com/ConsenSys/truffle
285 |
286 | Truffle is a development environment, testing framework and asset pipeline for Ethereum, aiming to make life as an Ethereum developer easier.
287 |
288 | ---
289 | ## Web3
290 |
291 | - Install:
292 |
293 | `npm install web3`
294 |
295 | - Enable rpc in console:
296 |
297 | `admin.startRPC("0.0.0.0", 8545, "*","db,eth,net,web3,personal")`
298 |
299 | - Example code: `node web3-test.js`
300 |
301 | ```Javascript
302 | var Web3 = require('web3');
303 | var web3 = new Web3(
304 | new Web3.providers.HttpProvider("http://localhost:8545"));
305 |
306 | web3.eth.getBlock(48, function(error, result){
307 | if(!error)
308 | console.log(result)
309 | else
310 | console.error(error);
311 | });
312 | ```
313 |
314 | ---
315 | ## Testrpc
316 |
317 | - Install:
318 |
319 | `npm install -g ethereumjs-testrpc`
320 |
321 |
322 | - Run testrpc:
323 |
324 | `testrpc -p 8547`
325 |
326 | - Connect with Web3: `node web3-testrpc.js`
327 |
328 | ```Javascript
329 | var Web3 = require('web3');
330 | var TestRPC = require("ethereumjs-testrpc");
331 | var web3 = new Web3(TestRPC.provider());
332 | web3.eth.getAccounts(function(e, accts){
333 | console.log("error:", e);
334 | console.log("accounts:", accts);
335 | process.exit(0);
336 | });
337 | ```
338 |
339 | - NOTE: As of version 3.0.2, testrpc requires at least Node 6.9.1 to run - this is because the ethereumjs-vm@2.0.1 dependency is now shipping using ES2015 language features.
340 |
341 | - Suggestion: using NVM [https://github.com/creationix/nvm](https://github.com/creationix/nvm)
342 |
343 | ---
344 | ## NVM
345 | Node Version Manager - Simple bash script to manage multiple active node.js versions
346 |
347 | - Install:
348 |
349 | https://github.com/creationix/nvm#installation
350 |
351 | - Use nvm:
352 | ```
353 | > cd js
354 | > nvm use
355 | ```
356 |
357 | ---
358 | ## NVM (install 6.9.1)
359 |
360 | - Install:
361 | ```
362 | nvm install 6.9.1
363 | ```
364 |
365 | - List installations:
366 | ```
367 | nvm list
368 | ```
369 |
370 | - Use:
371 | ```
372 | nvm use 6.9.1
373 | ```
374 |
375 | ---
376 | ## Truffle
377 | - Document: http://truffleframework.com/docs/
378 |
379 | - Install:
380 | `npm install -g truffle`
381 |
382 | - Init:
383 | `truffle init`
384 |
385 | - Compile:
386 | `truffle compile`
387 |
388 | - Deploy:
389 | `truffle migrate`
390 |
391 | - Test:
392 | `truffle test`
393 |
394 | ---
395 | ## Truffle Dapp
396 |
397 | - Default builder is no longer shipped with truffle from 3.*
398 |
399 | - Install default builder:
400 | `npm install truffle-default-builder --save`
401 |
402 | - Config `truffle.js`
403 |
404 | - Build frontend:
405 | `truffle build`
406 |
407 | - Run frontend:
408 | `truffle serve`
409 |
410 | - Edit `truffle.js` to config rpc.
411 |
412 | - Open dapp:
413 | `open http://localhost:8080`
414 |
415 | ---
416 | ## Contract deployment
417 | - Mist
418 |
419 | - Truffle
420 |
421 | - Web3
422 |
423 | ---
424 | ## Deploy contract with Mist
425 |
426 | - Contracts -> Deploy new contract -> Paste code and deploy
427 |
428 | - Remix IDE -> Create
429 |
430 | ---
431 | ## Deploy contract with Truffle
432 |
433 | - Update rpc setting in `truffle.js`
434 |
435 | - Create contract: `truffle create:contract OneValue`
436 |
437 | - Edit `OneValue.sol`
438 |
439 | - Compile: `truffle compile`
440 |
441 | - Add migration file: `3_deploy_one_value_contract.js`
442 |
443 | - Deploy: `truffle migrate`
444 |
445 | - Note: need to unlock account before deployment if you are using live network.
446 |
447 | ---
448 | ## Deploy contract with Web3
449 |
450 | - Deploy to testrpc: `node deploy-contract-testrpc.js`
451 |
452 | - Deploy to testnet: `node deploy-contract-test.js`
453 |
454 | - Example code (partial):
455 |
456 | ```Javascript
457 | var abi = ...
458 | var evmCode = ...
459 | var OneValueContract = web3.eth.contract(abi);
460 | var oneValue = OneValueContract.new(initValue,
461 | {from:addr, data: evmCode, gas: 4700000},
462 | function(error, contract){
463 | ...
464 | }
465 | );
466 | ```
467 |
468 | ---
469 | ## Mining
470 |
471 | - In console:
472 |
473 | ```
474 | miner.start(1)
475 | ```
476 |
477 | - In geth command:
478 |
479 | ```
480 | geth --mine --minerthread "4"
481 | ```
482 |
483 | - In mist: (testnet only)
484 |
485 | - Develop -> Start Mining
486 |
487 |
488 | ---
489 | ## Interact with contract (Express + Web3)
490 |
491 | - Example (partial):
492 |
493 | ```Javascript
494 | var abi = ... var OneValueContract = web3.eth.contract(abi);
495 | var contractAddress = '0x36274a6286c9cf3c8e09c85c5bfa572a8827fddc'; //Testnet
496 | var oneValue = OneValueContract.at(contractAddress);
497 |
498 | app.get('/', function (req, res) {
499 | res.send(
500 | 'OneValue Instance: ' + contractAddress + "\n" +
501 | 'Value: '+ oneValue.getValue() + "\n");
502 | });
503 |
504 | app.listen(3000)
505 | ```
506 |
507 | - Run: `node express-example.js`
508 |
509 | - Test: `curl http://localhost:3000`
510 |
--------------------------------------------------------------------------------
/FlightDelay/FlightDelay.sol:
--------------------------------------------------------------------------------
1 | /*
2 | Source: https://github.com/etherisc/flightDelay/blob/master/FlightDelay.sol
3 | */
4 | /*
5 | FlightDelay with Oraclized Underwriting and Payout
6 | All times are UTC.
7 | Copyright (C) Christoph Mussenbrock, Stephan Karpischek
8 |
9 | */
10 | import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";
11 | import "github.com/Arachnid/solidity-stringutils/strings.sol";
12 |
13 | contract FlightDelay is usingOraclize {
14 |
15 | using strings for *;
16 |
17 | modifier noEther { if (msg.value > 0) throw; _; }
18 | modifier onlyOwner { if (msg.sender != owner) throw; _; }
19 | modifier onlyOraclize { if (msg.sender != oraclize_cbAddress()) throw; _; }
20 |
21 | modifier onlyInState (uint _policyId, policyState _state) {
22 |
23 | policy p = policies[_policyId];
24 | if (p.state != _state) throw;
25 | _;
26 |
27 | }
28 |
29 | modifier onlyCustomer(uint _policyId) {
30 |
31 | policy p = policies[_policyId];
32 | if (p.customer != msg.sender) throw;
33 | _;
34 |
35 | }
36 |
37 | modifier notInMaintenance {
38 | healthCheck();
39 | if (maintenance_mode >= maintenance_Emergency) throw;
40 | _;
41 | }
42 |
43 | // the following modifier is always checked at last, so previous modifiers
44 | // may throw without affecting reentrantGuard
45 | modifier noReentrant {
46 | if (reentrantGuard) throw;
47 | reentrantGuard = true;
48 | _;
49 | reentrantGuard = false;
50 | }
51 |
52 | // policy Status Codes and meaning:
53 | //
54 | // 00 = Applied: the customer has payed a premium, but the oracle has
55 | // not yet checked and confirmed.
56 | // The customer can still revoke the policy.
57 | // 01 = Accepted: the oracle has checked and confirmed.
58 | // The customer can still revoke the policy.
59 | // 02 = Revoked: The customer has revoked the policy.
60 | // The premium minus cancellation fee is payed back to the
61 | // customer by the oracle.
62 | // 03 = PaidOut: The flight has ended with delay.
63 | // The oracle has checked and payed out.
64 | // 04 = Expired: The flight has endet with <15min. delay.
65 | // No payout.
66 | // 05 = Declined: The application was invalid.
67 | // The premium minus cancellation fee is payed back to the
68 | // customer by the oracle.
69 | // 06 = SendFailed: During Revoke, Decline or Payout, sending ether failed
70 | // for unknown reasons.
71 | // The funds remain in the contracts RiskFund.
72 |
73 |
74 | // 00 01 02 03
75 | enum policyState {Applied, Accepted, Revoked, PaidOut,
76 | // 04 05 06
77 | Expired, Declined, SendFailed}
78 |
79 | // oraclize callback types:
80 | enum oraclizeState { ForUnderwriting, ForPayout }
81 |
82 | event LOG_PolicyApplied(
83 | uint policyId,
84 | address customer,
85 | string carrierFlightNumber,
86 | uint premium
87 | );
88 | event LOG_PolicyAccepted(
89 | uint policyId,
90 | uint statistics0,
91 | uint statistics1,
92 | uint statistics2,
93 | uint statistics3,
94 | uint statistics4,
95 | uint statistics5
96 | );
97 | event LOG_PolicyRevoked(
98 | uint policyId
99 | );
100 | event LOG_PolicyPaidOut(
101 | uint policyId,
102 | uint amount
103 | );
104 | event LOG_PolicyExpired(
105 | uint policyId
106 | );
107 | event LOG_PolicyDeclined(
108 | uint policyId,
109 | bytes32 reason
110 | );
111 | event LOG_PolicyManualPayout(
112 | uint policyId,
113 | bytes32 reason
114 | );
115 | event LOG_SendFail(
116 | uint policyId,
117 | bytes32 reason
118 | );
119 | event LOG_OraclizeCall(
120 | uint policyId,
121 | bytes32 queryId,
122 | string oraclize_url
123 | );
124 | event LOG_OraclizeCallback(
125 | uint policyId,
126 | bytes32 queryId,
127 | string result,
128 | bytes proof
129 | );
130 | event LOG_HealthCheck(
131 | bytes32 message,
132 | int diff,
133 | uint balance,
134 | int ledgerBalance
135 | );
136 |
137 | // some general constants for the system:
138 | // minimum observations for valid prediction
139 | uint constant minObservations = 10;
140 | // minimum premium to cover costs
141 | uint constant minPremium = 500 finney;
142 | // maximum premium
143 | uint constant maxPremium = 5 ether;
144 | // maximum payout
145 | uint constant maxPayout = 200 ether;
146 | // maximum number of identical risks
147 | uint8 constant maxIdenticalRisks = 10;
148 | // 1 percent for DAO, 1 percent for maintainer
149 | uint8 constant rewardPercent = 2;
150 | // reserve for tail risks
151 | uint8 constant reservePercent = 1;
152 | // the weight pattern; in future versions this may become part of the policy struct.
153 | // currently can't be constant because of compiler restrictions
154 | // weightPattern[0] is not used, just to be consistent
155 | uint8[6] weightPattern = [0, 10,20,30,50,50];
156 | // Deadline for acceptance of policies: Mon, 26 Sep 2016 12:00:00 GMT
157 | uint contractDeadline = 1474891200;
158 |
159 | // account numbers for the internal ledger:
160 | // sum of all Premiums of all currently active policies
161 | uint8 constant acc_Premium = 0;
162 | // Risk fund; serves as reserve for tail risks
163 | uint8 constant acc_RiskFund = 1;
164 | // sum of all payed out policies
165 | uint8 constant acc_Payout = 2;
166 | // the balance of the contract (negative!!)
167 | uint8 constant acc_Balance = 3;
168 | // the reward account for DAO and maintainer
169 | uint8 constant acc_Reward = 4;
170 | // oraclize costs
171 | uint8 constant acc_OraclizeCosts = 5;
172 | // when adding more accounts, remember to increase ledger array length
173 |
174 | // Maintenance modes
175 | uint8 constant maintenance_None = 0;
176 | uint8 constant maintenance_BalTooHigh = 1;
177 | uint8 constant maintenance_Emergency = 255;
178 |
179 |
180 | // gas Constants for oraclize
181 | uint constant oraclizeGas = 500000;
182 |
183 | // URLs and query strings for oraclize
184 |
185 | string constant oraclize_RatingsBaseUrl =
186 | "[URL] json(https://api.flightstats.com/flex/ratings/rest/v1/json/flight/";
187 | string constant oraclizeRatingsQuery =
188 | "?${[decrypt] BDhAVBaQP2CS2VqQ/coqIStcYpSdSdLc1RJoC0gSoh++xsk6cBtLmJBHmB82X6mTMyzJXJPIvfa7ISzfwwhY+k8C3N+oP7htYGZ3N4INH03Uorw7Sif70hOw+xMR6PTX9ri2vkqiNwu9ensNkvTLyGd2l6NHJuij+RmgVw/mXGGZb9wHYC2T}).ratings[0]['observations','late15','late30','late45','cancelled','diverted']";
189 |
190 | // [URL] json(https://api.flightstats.com/flex/flightstatus/rest/v2/json/flight/status/LH/410/dep/2016/09/01?appId={appId}&appKey={appKey})
191 | string constant oraclize_StatusBaseUrl =
192 | "[URL] json(https://api.flightstats.com/flex/flightstatus/rest/v2/json/flight/status/";
193 | string constant oraclizeStatusQuery =
194 | "?${[decrypt] BDhAVBaQP2CS2VqQ/coqIStcYpSdSdLc1RJoC0gSoh++xsk6cBtLmJBHmB82X6mTMyzJXJPIvfa7ISzfwwhY+k8C3N+oP7htYGZ3N4INH03Uorw7Sif70hOw+xMR6PTX9ri2vkqiNwu9ensNkvTLyGd2l6NHJuij+RmgVw/mXGGZb9wHYC2T}).flightStatuses[0]['status','delays','operationalTimes']";
195 |
196 |
197 | // the policy structure: this structure keeps track of the individual parameters of a policy.
198 | // typically customer address, premium and some status information.
199 |
200 | struct policy {
201 |
202 | // 0 - the customer
203 | address customer;
204 | // 1 - premium
205 | uint premium;
206 |
207 | // risk specific parameters:
208 | // 2 - pointer to the risk in the risks mapping
209 | bytes32 riskId;
210 | // custom payout pattern
211 | // in future versions, customer will be able to tamper with this array.
212 | // to keep things simple, we have decided to hard-code the array for all policies.
213 | // uint8[5] pattern;
214 | // 3 - probability weight. this is the central parameter
215 | uint weight;
216 | // 4 - calculated Payout
217 | uint calculatedPayout;
218 | // 5 - actual Payout
219 | uint actualPayout;
220 |
221 | // status fields:
222 | // 6 - the state of the policy
223 | policyState state;
224 | // 7 - time of last state change
225 | uint stateTime;
226 | // 8 - state change message/reason
227 | bytes32 stateMessage;
228 | // 9 - TLSNotary Proof
229 | bytes proof;
230 | }
231 |
232 | // the risk structure; this structure keeps track of the risk-specific parameters.
233 | // several policies can share the same risk structure (typically some people flying
234 | // with the same plane)
235 |
236 | struct risk {
237 |
238 | // 0 - Airline Code + FlightNumber
239 | string carrierFlightNumber;
240 | // 1 - scheduled departure and arrival time in the format /dep/YYYY/MM/DD
241 | string departureYearMonthDay;
242 | // 2 - the inital arrival time
243 | uint arrivalTime;
244 | // 3 - the final delay in minutes
245 | uint delayInMinutes;
246 | // 4 - the determined delay category (0-5)
247 | uint8 delay;
248 | // 5 - counter; limit the number of identical risks.
249 | uint8 counter;
250 | }
251 |
252 | // the oraclize callback structure: we use several oraclize calls.
253 | // all oraclize calls will result in a common callback to __callback(...).
254 | // to keep track of the different querys we have to introduce this struct.
255 |
256 | struct oraclizeCallback {
257 |
258 | // for which policy have we called?
259 | uint policyId;
260 | // for which purpose did we call? {ForUnderwrite | ForPayout}
261 | oraclizeState oState;
262 | uint oraclizeTime;
263 |
264 | }
265 |
266 | address public owner;
267 |
268 | // Table of policies
269 | policy[] public policies;
270 | // Lookup policyIds from customer addresses
271 | mapping (address => uint[]) public customerPolicies;
272 | // Lookup policy Ids from queryIds
273 | mapping (bytes32 => oraclizeCallback) public oraclizeCallbacks;
274 | mapping (bytes32 => risk) public risks;
275 | // Internal ledger
276 | int[6] public ledger;
277 |
278 | // invariant: acc_Premium + acc_RiskFund + acc_Payout
279 | // + acc_Balance + acc_Reward == 0
280 |
281 | // Mutex
282 | bool public reentrantGuard;
283 | uint8 public maintenance_mode;
284 |
285 | function healthCheck() internal {
286 | int diff = int(this.balance-msg.value) + ledger[acc_Balance];
287 | if (diff == 0) {
288 | return; // everything ok.
289 | }
290 | if (diff > 0) {
291 | LOG_HealthCheck('Balance too high', diff, this.balance, ledger[acc_Balance]);
292 | maintenance_mode = maintenance_BalTooHigh;
293 | } else {
294 | LOG_HealthCheck('Balance too low', diff, this.balance, ledger[acc_Balance]);
295 | maintenance_mode = maintenance_Emergency;
296 | }
297 | }
298 |
299 | // manually perform healthcheck.
300 | // @param _maintenance_mode:
301 | // 0 = reset maintenance_mode, even in emergency
302 | // 1 = perform health check
303 | // 255 = set maintenance_mode to maintenance_emergency (no newPolicy anymore)
304 | function performHealthCheck(uint8 _maintenance_mode) onlyOwner {
305 | maintenance_mode = _maintenance_mode;
306 | if (maintenance_mode > 0 && maintenance_mode < maintenance_Emergency) {
307 | healthCheck();
308 | }
309 | }
310 |
311 | function payReward() onlyOwner {
312 |
313 | if (!owner.send(this.balance)) throw;
314 | maintenance_mode = maintenance_Emergency; // don't accept any policies
315 |
316 | }
317 |
318 | function bookkeeping(uint8 _from, uint8 _to, uint _amount) internal {
319 |
320 | ledger[_from] -= int(_amount);
321 | ledger[_to] += int(_amount);
322 |
323 | }
324 |
325 | // if ledger gets corrupt for unknown reasons, have a way to correct it:
326 | function audit(uint8 _from, uint8 _to, uint _amount) onlyOwner {
327 |
328 | bookkeeping (_from, _to, _amount);
329 |
330 | }
331 |
332 | function getPolicyCount(address _customer)
333 | constant returns (uint _count) {
334 | return policies.length;
335 | }
336 |
337 | function getCustomerPolicyCount(address _customer)
338 | constant returns (uint _count) {
339 | return customerPolicies[_customer].length;
340 | }
341 |
342 | function bookAndCalcRemainingPremium() internal returns (uint) {
343 |
344 | uint v = msg.value;
345 | uint reserve = v * reservePercent / 100;
346 | uint remain = v - reserve;
347 | uint reward = remain * rewardPercent / 100;
348 |
349 | bookkeeping(acc_Balance, acc_Premium, v);
350 | bookkeeping(acc_Premium, acc_RiskFund, reserve);
351 | bookkeeping(acc_Premium, acc_Reward, reward);
352 |
353 | return (uint(remain - reward));
354 |
355 | }
356 |
357 | // constructor
358 | function FlightDelay () {
359 |
360 | owner = msg.sender;
361 | reentrantGuard = false;
362 | maintenance_mode = maintenance_None;
363 |
364 | // initially put all funds in risk fund.
365 | bookkeeping(acc_Balance, acc_RiskFund, msg.value);
366 | oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
367 |
368 | }
369 |
370 | // create new policy
371 | function newPolicy(
372 | string _carrierFlightNumber,
373 | string _departureYearMonthDay,
374 | uint _departureTime,
375 | uint _arrivalTime
376 | )
377 | notInMaintenance {
378 |
379 | // sanity checks:
380 |
381 | // don't accept to low or to high policies
382 |
383 | if (msg.value < minPremium || msg.value > maxPremium) {
384 | LOG_PolicyDeclined(0, 'Invalid premium value');
385 | if (!msg.sender.send(msg.value)) {
386 | LOG_SendFail(0, 'newPolicy sendback failed (1)');
387 | }
388 | return;
389 | }
390 |
391 | // don't accept flights with departure time earlier than in 24 hours,
392 | // or arrivalTime before departureTime, or departureTime after Mon, 26 Sep 2016 12:00:00 GMT
393 | if (
394 | _arrivalTime < _departureTime ||
395 | _arrivalTime > _departureTime + 2 days ||
396 | _departureTime < now + 24 hours ||
397 | _departureTime > contractDeadline) {
398 | LOG_PolicyDeclined(0, 'Invalid arrival/departure time');
399 | if (!msg.sender.send(msg.value)) {
400 | LOG_SendFail(0, 'newPolicy sendback failed (2)');
401 | }
402 | return;
403 | }
404 |
405 | // accept only a number of maxIdenticalRisks identical risks:
406 |
407 | bytes32 riskId = sha3(_carrierFlightNumber, _departureYearMonthDay, _arrivalTime);
408 | risk r = risks[riskId];
409 |
410 | if (r.counter >= maxIdenticalRisks) {
411 | LOG_PolicyDeclined(0, 'To many identical risks');
412 | if (!msg.sender.send(msg.value)) {
413 | LOG_SendFail(0, 'newPolicy sendback failed (3)');
414 | }
415 | return;
416 | }
417 |
418 | // store or update policy
419 | uint policyId = policies.length++;
420 | customerPolicies[msg.sender].push(policyId);
421 | policy p = policies[policyId];
422 |
423 | p.customer = msg.sender;
424 | p.premium = bookAndCalcRemainingPremium();
425 | p.riskId = riskId;
426 | // the remaining premium after deducting reserve and reward
427 |
428 | // store risk parameters
429 | // Airline Code
430 | if (r.counter == 0) {
431 | // we have a new struct
432 | r.carrierFlightNumber = _carrierFlightNumber;
433 | r.departureYearMonthDay = _departureYearMonthDay;
434 | r.arrivalTime = _arrivalTime;
435 | }
436 | // increase counter;
437 | r.counter += 1;
438 |
439 | // now we have successfully applied
440 | p.state = policyState.Applied;
441 | p.stateMessage = 'Policy applied by customer';
442 | p.stateTime = now;
443 | LOG_PolicyApplied(policyId, msg.sender, _carrierFlightNumber, p.premium);
444 |
445 | // call oraclize to get Flight Stats; this will also call underwrite()
446 | getFlightStats(policyId, _carrierFlightNumber);
447 | }
448 |
449 | function underwrite(uint _policyId, uint[6] _statistics, bytes _proof) internal {
450 |
451 | policy p = policies[_policyId]; // throws if _policyId invalid
452 | for (uint8 i = 1; i <= 5; i++ ) {
453 | p.weight += weightPattern[i] * _statistics[i];
454 | // 1% = 100 / 100% = 10,000
455 | }
456 | // to avoid div0 in the payout section, we have to make a minimal assumption on p.weight.
457 | if (p.weight == 0) { p.weight = 100000 / _statistics[0]; }
458 | p.proof = _proof;
459 | risk r = risks[p.riskId];
460 |
461 | // schedule payout Oracle
462 | schedulePayoutOraclizeCall(
463 | _policyId,
464 | r.carrierFlightNumber,
465 | r.departureYearMonthDay,
466 | r.arrivalTime + 15 minutes
467 | );
468 |
469 | p.state = policyState.Accepted;
470 | p.stateMessage = 'Policy underwritten by oracle';
471 | p.stateTime = now;
472 |
473 | LOG_PolicyAccepted(
474 | _policyId,
475 | _statistics[0],
476 | _statistics[1],
477 | _statistics[2],
478 | _statistics[3],
479 | _statistics[4],
480 | _statistics[5]
481 | );
482 |
483 | }
484 |
485 | function decline(uint _policyId, bytes32 _reason, bytes _proof) internal {
486 |
487 | policy p = policies[_policyId];
488 |
489 | p.state = policyState.Declined;
490 | p.stateMessage = _reason;
491 | p.stateTime = now; // won't be reverted in case of errors
492 | p.proof = _proof;
493 | bookkeeping(acc_Premium, acc_Balance, p.premium);
494 |
495 | if (!p.customer.send(p.premium)) {
496 | bookkeeping(acc_Balance, acc_RiskFund, p.premium);
497 | p.state = policyState.SendFailed;
498 | p.stateMessage = 'decline: Send failed.';
499 | LOG_SendFail(_policyId, 'decline sendfail');
500 | }
501 | else {
502 | LOG_PolicyDeclined(_policyId, _reason);
503 | }
504 |
505 |
506 | }
507 |
508 | function schedulePayoutOraclizeCall(
509 | uint _policyId,
510 | string _carrierFlightNumber,
511 | string _departureYearMonthDay,
512 | uint _oraclizeTime)
513 | internal {
514 |
515 | string memory oraclize_url = strConcat(
516 | oraclize_StatusBaseUrl,
517 | _carrierFlightNumber,
518 | _departureYearMonthDay,
519 | oraclizeStatusQuery
520 | );
521 |
522 | bytes32 queryId = oraclize_query(_oraclizeTime, 'nested', oraclize_url, oraclizeGas);
523 | bookkeeping(acc_OraclizeCosts, acc_Balance, uint((-ledger[acc_Balance]) - int(this.balance)));
524 | oraclizeCallbacks[queryId] = oraclizeCallback(_policyId, oraclizeState.ForPayout, _oraclizeTime);
525 |
526 | LOG_OraclizeCall(_policyId, queryId, oraclize_url);
527 | }
528 |
529 | function payOut(uint _policyId, uint8 _delay, uint _delayInMinutes)
530 | notInMaintenance
531 | onlyOraclize
532 | onlyInState(_policyId, policyState.Accepted)
533 | internal {
534 |
535 | policy p = policies[_policyId];
536 | risk r = risks[p.riskId];
537 | r.delay = _delay;
538 | r.delayInMinutes = _delayInMinutes;
539 |
540 | if (_delay == 0) {
541 | p.state = policyState.Expired;
542 | p.stateMessage = 'Expired - no delay!';
543 | p.stateTime = now;
544 | LOG_PolicyExpired(_policyId);
545 | } else {
546 |
547 | uint payout = p.premium * weightPattern[_delay] * 10000 / p.weight;
548 | p.calculatedPayout = payout;
549 |
550 | if (payout > maxPayout) {
551 | payout = maxPayout;
552 | }
553 |
554 | if (payout > uint(-ledger[acc_Balance])) { // don't go for chapter 11
555 | payout = uint(-ledger[acc_Balance]);
556 | }
557 |
558 | p.actualPayout = payout;
559 | bookkeeping(acc_Payout, acc_Balance, payout); // cash out payout
560 |
561 |
562 | if (!p.customer.send(payout)) {
563 | bookkeeping(acc_Balance, acc_Payout, payout);
564 | p.state = policyState.SendFailed;
565 | p.stateMessage = 'Payout, send failed!';
566 | p.actualPayout = 0;
567 | LOG_SendFail(_policyId, 'payout sendfail');
568 | }
569 | else {
570 | p.state = policyState.PaidOut;
571 | p.stateMessage = 'Payout successful!';
572 | p.stateTime = now; // won't be reverted in case of errors
573 | LOG_PolicyPaidOut(_policyId, payout);
574 | }
575 | }
576 |
577 | }
578 |
579 | // fallback function: don't accept ether, except from owner
580 | function () onlyOwner {
581 |
582 | // put additional funds in risk fund.
583 | bookkeeping(acc_Balance, acc_RiskFund, msg.value);
584 |
585 | }
586 |
587 | // internal, so no reentrant guard neccessary
588 | function getFlightStats(
589 | uint _policyId,
590 | string _carrierFlightNumber)
591 | internal {
592 |
593 | // call oraclize and retrieve the number of observations from flightstats API
594 | // format https://api.flightstats.com/flex/ratings/rest/v1/json/flight/OS/75?appId=**&appKey=**
595 |
596 | // using nested data sources (query type nested) and partial
597 | // encrypted queries in the next release of oraclize
598 | // note that the first call maps the encrypted string to the
599 | // sending contract address, this string can't be used from any other sender
600 | string memory oraclize_url = strConcat(
601 | oraclize_RatingsBaseUrl,
602 | _carrierFlightNumber,
603 | oraclizeRatingsQuery
604 | );
605 |
606 | bytes32 queryId = oraclize_query("nested", oraclize_url, oraclizeGas);
607 | // calculate the spent gas
608 | bookkeeping(acc_OraclizeCosts, acc_Balance, uint((-ledger[acc_Balance]) - int(this.balance)));
609 | oraclizeCallbacks[queryId] = oraclizeCallback(_policyId, oraclizeState.ForUnderwriting, 0);
610 |
611 | LOG_OraclizeCall(_policyId, queryId, oraclize_url);
612 |
613 | }
614 |
615 | // this is a dispatcher, but must be called __callback
616 | function __callback(bytes32 _queryId, string _result, bytes _proof)
617 | onlyOraclize
618 | noReentrant {
619 |
620 | oraclizeCallback memory o = oraclizeCallbacks[_queryId];
621 | LOG_OraclizeCallback(o.policyId, _queryId, _result, _proof);
622 |
623 | if (o.oState == oraclizeState.ForUnderwriting) {
624 | callback_ForUnderwriting(o.policyId, _result, _proof);
625 | }
626 | else {
627 | callback_ForPayout(_queryId, _result, _proof);
628 | }
629 | }
630 |
631 | function callback_ForUnderwriting(uint _policyId, string _result, bytes _proof)
632 | onlyInState(_policyId, policyState.Applied)
633 | internal {
634 |
635 | var sl_result = _result.toSlice();
636 | risk memory r = risks[policies[_policyId].riskId];
637 |
638 | // we expect result to contain 6 values, something like
639 | // "[61, 10, 4, 3, 0, 0]" ->
640 | // ['observations','late15','late30','late45','cancelled','diverted']
641 |
642 | if (bytes(_result).length == 0) {
643 | decline(_policyId, 'Declined (empty result)', _proof);
644 | } else {
645 |
646 | // now slice the string using
647 | // https://github.com/Arachnid/solidity-stringutils
648 |
649 | if (sl_result.count(', '.toSlice()) != 5) { // check if result contains 6 values
650 | decline(_policyId, 'Declined (invalid result)', _proof);
651 | } else {
652 | sl_result.beyond("[".toSlice()).until("]".toSlice());
653 |
654 | uint observations = parseInt(sl_result.split(', '.toSlice()).toString());
655 |
656 | // decline on < minObservations observations,
657 | // can't calculate reasonable probabibilities
658 | if (observations <= minObservations) {
659 | decline(_policyId, 'Declined (too few observations)', _proof);
660 | } else {
661 | uint[6] memory statistics;
662 | // calculate statistics (scaled by 100)
663 | statistics[0] = observations;
664 | for(uint i = 1; i <= 5; i++) {
665 | statistics[i] =
666 | parseInt(sl_result.split(', '.toSlice()).toString()) * 10000/observations;
667 | }
668 |
669 | // underwrite policy
670 | underwrite(_policyId, statistics, _proof);
671 | }
672 | }
673 | }
674 | }
675 |
676 | function callback_ForPayout(bytes32 _queryId, string _result, bytes _proof) internal {
677 |
678 | oraclizeCallback memory o = oraclizeCallbacks[_queryId];
679 | uint policyId = o.policyId;
680 | var sl_result = _result.toSlice();
681 |
682 | if (bytes(_result).length == 0) {
683 | // hmm ... bad! try again some minutes later ...
684 | schedulePayoutOraclizeCall(policyId, r.carrierFlightNumber, r.departureYearMonthDay, o.oraclizeTime + 45 minutes);
685 | } else {
686 |
687 | // first check status
688 |
689 | // extract the status field:
690 | sl_result.find('"'.toSlice()).beyond('"'.toSlice());
691 | sl_result.until(sl_result.copy().find('"'.toSlice()));
692 | bytes1 status = bytes(sl_result.toString())[0]; // s = L
693 |
694 | if (status == 'C') {
695 | // flight cancelled --> payout
696 | payOut(policyId, 4, 0);
697 | return;
698 | } else if (status == 'D') {
699 | // flight diverted --> payout
700 | payOut(policyId, 5, 0);
701 | return;
702 | } else if (status != 'L' && status != 'A' && status != 'C' && status != 'D') {
703 | LOG_PolicyManualPayout(policyId, 'Unprocessable status');
704 | return;
705 | }
706 |
707 | // process the rest of the response:
708 | sl_result = _result.toSlice();
709 | bool arrived = sl_result.contains('actualGateArrival'.toSlice());
710 |
711 | if (status == 'A' || (status == 'L' && !arrived)) {
712 | // flight still active or not at gate --> reschedule
713 | risk memory r = risks[policies[policyId].riskId];
714 | if (o.oraclizeTime > r.arrivalTime + 120 minutes) {
715 | LOG_PolicyManualPayout(policyId, 'No arrival at +120 min');
716 | } else {
717 | schedulePayoutOraclizeCall(policyId, r.carrierFlightNumber, r.departureYearMonthDay, o.oraclizeTime + 45 minutes);
718 | }
719 | } else if (status == 'L' && arrived) {
720 | var aG = '"arrivalGateDelayMinutes": '.toSlice();
721 | if (sl_result.contains(aG)) {
722 | sl_result.find(aG).beyond(aG);
723 | sl_result.until(sl_result.copy().find('"'.toSlice()).beyond('"'.toSlice()));
724 | sl_result.until(sl_result.copy().find('}'.toSlice()));
725 | sl_result.until(sl_result.copy().find(','.toSlice()));
726 | uint delayInMinutes = parseInt(sl_result.toString());
727 | } else {
728 | delayInMinutes = 0;
729 | }
730 |
731 | if (delayInMinutes < 15) {
732 | payOut(policyId, 0, 0);
733 | } else if (delayInMinutes < 30) {
734 | payOut(policyId, 1, delayInMinutes);
735 | } else if (delayInMinutes < 45) {
736 | payOut(policyId, 2, delayInMinutes);
737 | } else {
738 | payOut(policyId, 3, delayInMinutes);
739 | }
740 | } else { // no delay info
741 | payOut(policyId, 0, 0);
742 | }
743 | }
744 | }
745 | }
746 |
--------------------------------------------------------------------------------