├── .gitignore
├── contrib
├── using-puppeth.asciidoc
├── example.asciidoc
├── aws-setup.asciidoc
├── scaling.asciidoc
└── aws-network-operation.asciidoc
├── code
├── auction_dapp
│ ├── frontend
│ │ ├── static
│ │ │ └── .gitkeep
│ │ ├── config
│ │ │ ├── prod.env.js
│ │ │ ├── dev.env.js
│ │ │ └── index.js
│ │ ├── build
│ │ │ ├── logo.png
│ │ │ ├── vue-loader.conf.js
│ │ │ ├── build.js
│ │ │ ├── check-versions.js
│ │ │ ├── webpack.base.conf.js
│ │ │ ├── utils.js
│ │ │ ├── webpack.dev.conf.js
│ │ │ └── webpack.prod.conf.js
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── .babelrc
│ │ ├── .postcssrc.js
│ │ ├── README.md
│ │ ├── src
│ │ │ ├── router
│ │ │ │ └── index.js
│ │ │ ├── config.js
│ │ │ ├── models
│ │ │ │ ├── ChatRoom.js
│ │ │ │ ├── DeedRepository.js
│ │ │ │ └── AuctionRepository.js
│ │ │ └── main.js
│ │ ├── index.html
│ │ └── package.json
│ ├── .gitignore
│ ├── backend
│ │ ├── .gitignore
│ │ ├── test
│ │ │ ├── output.address
│ │ │ ├── 2_deedrepository.js
│ │ │ └── 1_auctionrepository.js
│ │ ├── migrations
│ │ │ ├── 1_initial_migration.js
│ │ │ └── 2_deploy_contracts.js
│ │ ├── truffle.js
│ │ ├── contracts
│ │ │ ├── ERC721
│ │ │ │ ├── ERC721Holder.sol
│ │ │ │ ├── DeprecatedERC721.sol
│ │ │ │ ├── ERC721.sol
│ │ │ │ ├── ERC721Receiver.sol
│ │ │ │ ├── ERC721Basic.sol
│ │ │ │ └── ERC721Token.sol
│ │ │ ├── utils
│ │ │ │ ├── math
│ │ │ │ │ ├── Math.sol
│ │ │ │ │ └── SafeMath.sol
│ │ │ │ └── AddressUtils.sol
│ │ │ ├── Migrations.sol
│ │ │ └── DeedRepository.sol
│ │ └── scripts
│ │ │ └── prepare.js
│ ├── auction_diagram.png
│ ├── DEV_README.md
│ └── README.md
├── jsonrpc
│ ├── http
│ │ └── js
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ └── index.js
│ ├── websockets
│ │ ├── .gitignore
│ │ ├── README.md
│ │ └── app.js
│ └── ipc
│ │ └── client.go
├── truffle
│ ├── Faucet
│ │ ├── migrations
│ │ │ ├── 2_deploy_contracts.js
│ │ │ └── 1_initial_migration.js
│ │ ├── truffle-config.js
│ │ ├── package.json
│ │ └── contracts
│ │ │ ├── Faucet.sol
│ │ │ └── Migrations.sol
│ ├── FaucetEvents
│ │ ├── migrations
│ │ │ ├── 2_deploy_contracts.js
│ │ │ └── 1_initial_migration.js
│ │ ├── truffle-config.js
│ │ ├── package.json
│ │ ├── contracts
│ │ │ ├── Migrations.sol
│ │ │ └── Faucet.sol
│ │ └── gas_estimates.js
│ ├── console
│ │ ├── migrations
│ │ │ └── 1_initial_migration.js
│ │ ├── package.json
│ │ ├── contracts
│ │ │ └── Migrations.sol
│ │ ├── truffle-config.js
│ │ └── nonce.js
│ ├── CallExamples
│ │ ├── migrations
│ │ │ ├── 1_initial_migration.js
│ │ │ └── 2_deploy_contracts.js
│ │ ├── package.json
│ │ ├── contracts
│ │ │ ├── Migrations.sol
│ │ │ └── CallExamples.sol
│ │ └── truffle-config.js
│ ├── METoken
│ │ ├── migrations
│ │ │ ├── 2_deploy_contracts.js
│ │ │ └── 1_initial_migration.js
│ │ ├── package.json
│ │ ├── contracts
│ │ │ ├── METoken.sol
│ │ │ └── Migrations.sol
│ │ ├── test
│ │ │ └── METoken.test.js
│ │ └── truffle-config.js
│ ├── METoken_Faucet
│ │ ├── migrations
│ │ │ ├── 3_deploy_faucet.js
│ │ │ ├── 2_deploy_contracts.js
│ │ │ └── 1_initial_migration.js
│ │ ├── package.json
│ │ ├── contracts
│ │ │ ├── Faucet.sol
│ │ │ ├── METoken.sol
│ │ │ └── Migrations.sol
│ │ └── truffle-config.js
│ ├── METoken_METFaucet
│ │ ├── migrations
│ │ │ ├── 1_initial_migration.js
│ │ │ └── 2_deploy_contracts.js
│ │ ├── package.json
│ │ ├── contracts
│ │ │ ├── METoken.sol
│ │ │ ├── Migrations.sol
│ │ │ └── METFaucet.sol
│ │ ├── test
│ │ │ └── test_approve_transferFrom.js
│ │ └── truffle-config.js
│ └── FaucetReentryAttack
│ │ └── package.json
├── Solidity
│ ├── Token.sol
│ ├── Faucet.sol
│ ├── Faucet2.sol
│ ├── Faucet3.sol
│ ├── Faucet4.sol
│ ├── Faucet5.sol
│ ├── Faucet6.sol
│ ├── Faucet7.sol
│ └── Faucet8.sol
├── OpenZeppelin
│ ├── contracts
│ │ ├── SampleToken.sol
│ │ └── SampleCrowdsale.sol
│ └── migrations
│ │ └── 2_deploy_contracts.js
├── web3js
│ ├── raw_tx
│ │ ├── package.json
│ │ └── raw_tx_demo.js
│ └── web3js_demo
│ │ ├── web3-contract-basic-interaction-async-await.js
│ │ └── web3-contract-basic-interaction.js
└── aws
│ ├── genesis.json
│ └── truffle-config.js
├── images
├── cover.png
├── theme.png
├── branches.png
├── cover_oe.png
├── ens-bid.png
├── ens-flow.png
├── newproj.png
├── tarsier.png
├── bip39-part1.png
├── bip39-part2.png
├── bip39_web.png
├── block_time.png
├── cover_thumb.png
├── difficulty.png
├── eip_process.png
├── ens-auction.png
├── ens-manager.png
├── gas_limit.png
├── hd_wallet.png
├── proxy-lib.png
├── quickbuilds.png
├── remix_run.png
├── rlpx_rpc_xs.png
├── web3suite.png
├── eip_workflow.png
├── ens-checkname.png
├── remix_compile.png
├── remix_toolbar.png
├── swarm-gateway.png
├── TransferToFriend.gif
├── auction_diagram.png
├── ens-bid-revealed.png
├── ens-metamask-bid.png
├── ens-reveal-bid.png
├── evm-architecture.png
├── ganache_metoken.png
├── metamask_account.png
├── offline_signing.png
├── remix_close_tab.png
├── remix_withdraw.png
├── send_to_faucet.png
├── contract_published.png
├── coordination_game.png
├── governance_process.png
├── metamask_download.png
├── metamask_mnemonic.png
├── metamask_password.png
├── metamask_withdraw.png
├── remix_faucet_load.png
├── Faucet_disassembled.png
├── focal_point_squares.png
├── http_ws_ipc_jsonrpc.png
├── remix_deploy_contract.png
├── remix_metamask_create.png
├── simple_elliptic_curve.png
├── ens-manager-set-content.png
├── etherscan_withdrawal_tx.png
├── metamask_ropsten_faucet.png
├── remix_contract_address.png
├── remix_contract_interact.png
├── ropsten_block_explorer.png
├── Faucet_jumpi_instruction.png
├── auction_dapp_home_screen.png
├── ec_over_small_prime_field.png
├── ens-manager-set-resolver.png
├── ens_manager_add_subdomain.png
├── etherscan_contract_address.png
├── ganache_metoken_transfer.png
├── metamask_send_to_contract.png
├── parity_txdemo_novalue_data.png
├── parity_txdemo_value_data.png
├── parity_txdemo_value_nodata.png
├── solidity_function_syntax.png
├── architecture_diagram_webapp.png
├── aws-topology-simple-bootnode.png
├── parity_txdemo_novalue_nodata.png
├── approve_transferFrom_workflow.png
├── auction_dapp_final_architecture.png
├── block_explorer_account_history.png
├── etherscan_withdrawal_internal.png
├── metamask_account_context_menu.png
├── parity_deployment_confirmation.png
├── published_contract_transactions.png
└── ens-manager-set-default-resolver.png
├── headings_cn.asciidoc
├── title_cn.asciidoc
├── settings_cn.asciidoc
├── book_cn.asciidoc
├── README.md
├── appdx-shortlinks_cn.asciidoc
├── 14consensus_cn.asciidoc
├── github_contrib.asciidoc
├── preface_open_edition_cn.asciidoc
├── appdx-standards-eip-erc_cn.asciidoc
└── appdx-web3js-tutorial_cn.asciidoc
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
--------------------------------------------------------------------------------
/contrib/using-puppeth.asciidoc:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/code/auction_dapp/.gitignore:
--------------------------------------------------------------------------------
1 | _local_dev/
2 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/test/output.address:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/code/jsonrpc/http/js/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/code/jsonrpc/websockets/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/images/cover.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/cover.png
--------------------------------------------------------------------------------
/images/theme.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/theme.png
--------------------------------------------------------------------------------
/images/branches.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/branches.png
--------------------------------------------------------------------------------
/images/cover_oe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/cover_oe.png
--------------------------------------------------------------------------------
/images/ens-bid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-bid.png
--------------------------------------------------------------------------------
/images/ens-flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-flow.png
--------------------------------------------------------------------------------
/images/newproj.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/newproj.png
--------------------------------------------------------------------------------
/images/tarsier.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/tarsier.png
--------------------------------------------------------------------------------
/images/bip39-part1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/bip39-part1.png
--------------------------------------------------------------------------------
/images/bip39-part2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/bip39-part2.png
--------------------------------------------------------------------------------
/images/bip39_web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/bip39_web.png
--------------------------------------------------------------------------------
/images/block_time.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/block_time.png
--------------------------------------------------------------------------------
/images/cover_thumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/cover_thumb.png
--------------------------------------------------------------------------------
/images/difficulty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/difficulty.png
--------------------------------------------------------------------------------
/images/eip_process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/eip_process.png
--------------------------------------------------------------------------------
/images/ens-auction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-auction.png
--------------------------------------------------------------------------------
/images/ens-manager.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-manager.png
--------------------------------------------------------------------------------
/images/gas_limit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/gas_limit.png
--------------------------------------------------------------------------------
/images/hd_wallet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/hd_wallet.png
--------------------------------------------------------------------------------
/images/proxy-lib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/proxy-lib.png
--------------------------------------------------------------------------------
/images/quickbuilds.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/quickbuilds.png
--------------------------------------------------------------------------------
/images/remix_run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_run.png
--------------------------------------------------------------------------------
/images/rlpx_rpc_xs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/rlpx_rpc_xs.png
--------------------------------------------------------------------------------
/images/web3suite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/web3suite.png
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/images/eip_workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/eip_workflow.png
--------------------------------------------------------------------------------
/images/ens-checkname.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-checkname.png
--------------------------------------------------------------------------------
/images/remix_compile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_compile.png
--------------------------------------------------------------------------------
/images/remix_toolbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_toolbar.png
--------------------------------------------------------------------------------
/images/swarm-gateway.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/swarm-gateway.png
--------------------------------------------------------------------------------
/images/TransferToFriend.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/TransferToFriend.gif
--------------------------------------------------------------------------------
/images/auction_diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/auction_diagram.png
--------------------------------------------------------------------------------
/images/ens-bid-revealed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-bid-revealed.png
--------------------------------------------------------------------------------
/images/ens-metamask-bid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-metamask-bid.png
--------------------------------------------------------------------------------
/images/ens-reveal-bid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-reveal-bid.png
--------------------------------------------------------------------------------
/images/evm-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/evm-architecture.png
--------------------------------------------------------------------------------
/images/ganache_metoken.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ganache_metoken.png
--------------------------------------------------------------------------------
/images/metamask_account.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_account.png
--------------------------------------------------------------------------------
/images/offline_signing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/offline_signing.png
--------------------------------------------------------------------------------
/images/remix_close_tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_close_tab.png
--------------------------------------------------------------------------------
/images/remix_withdraw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_withdraw.png
--------------------------------------------------------------------------------
/images/send_to_faucet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/send_to_faucet.png
--------------------------------------------------------------------------------
/images/contract_published.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/contract_published.png
--------------------------------------------------------------------------------
/images/coordination_game.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/coordination_game.png
--------------------------------------------------------------------------------
/images/governance_process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/governance_process.png
--------------------------------------------------------------------------------
/images/metamask_download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_download.png
--------------------------------------------------------------------------------
/images/metamask_mnemonic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_mnemonic.png
--------------------------------------------------------------------------------
/images/metamask_password.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_password.png
--------------------------------------------------------------------------------
/images/metamask_withdraw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_withdraw.png
--------------------------------------------------------------------------------
/images/remix_faucet_load.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_faucet_load.png
--------------------------------------------------------------------------------
/images/Faucet_disassembled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/Faucet_disassembled.png
--------------------------------------------------------------------------------
/images/focal_point_squares.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/focal_point_squares.png
--------------------------------------------------------------------------------
/images/http_ws_ipc_jsonrpc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/http_ws_ipc_jsonrpc.png
--------------------------------------------------------------------------------
/images/remix_deploy_contract.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_deploy_contract.png
--------------------------------------------------------------------------------
/images/remix_metamask_create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_metamask_create.png
--------------------------------------------------------------------------------
/images/simple_elliptic_curve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/simple_elliptic_curve.png
--------------------------------------------------------------------------------
/images/ens-manager-set-content.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-manager-set-content.png
--------------------------------------------------------------------------------
/images/etherscan_withdrawal_tx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/etherscan_withdrawal_tx.png
--------------------------------------------------------------------------------
/images/metamask_ropsten_faucet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_ropsten_faucet.png
--------------------------------------------------------------------------------
/images/remix_contract_address.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_contract_address.png
--------------------------------------------------------------------------------
/images/remix_contract_interact.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/remix_contract_interact.png
--------------------------------------------------------------------------------
/images/ropsten_block_explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ropsten_block_explorer.png
--------------------------------------------------------------------------------
/code/auction_dapp/auction_diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/code/auction_dapp/auction_diagram.png
--------------------------------------------------------------------------------
/images/Faucet_jumpi_instruction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/Faucet_jumpi_instruction.png
--------------------------------------------------------------------------------
/images/auction_dapp_home_screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/auction_dapp_home_screen.png
--------------------------------------------------------------------------------
/images/ec_over_small_prime_field.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ec_over_small_prime_field.png
--------------------------------------------------------------------------------
/images/ens-manager-set-resolver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-manager-set-resolver.png
--------------------------------------------------------------------------------
/images/ens_manager_add_subdomain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens_manager_add_subdomain.png
--------------------------------------------------------------------------------
/images/etherscan_contract_address.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/etherscan_contract_address.png
--------------------------------------------------------------------------------
/images/ganache_metoken_transfer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ganache_metoken_transfer.png
--------------------------------------------------------------------------------
/images/metamask_send_to_contract.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_send_to_contract.png
--------------------------------------------------------------------------------
/images/parity_txdemo_novalue_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/parity_txdemo_novalue_data.png
--------------------------------------------------------------------------------
/images/parity_txdemo_value_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/parity_txdemo_value_data.png
--------------------------------------------------------------------------------
/images/parity_txdemo_value_nodata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/parity_txdemo_value_nodata.png
--------------------------------------------------------------------------------
/images/solidity_function_syntax.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/solidity_function_syntax.png
--------------------------------------------------------------------------------
/images/architecture_diagram_webapp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/architecture_diagram_webapp.png
--------------------------------------------------------------------------------
/images/aws-topology-simple-bootnode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/aws-topology-simple-bootnode.png
--------------------------------------------------------------------------------
/images/parity_txdemo_novalue_nodata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/parity_txdemo_novalue_nodata.png
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/code/auction_dapp/frontend/build/logo.png
--------------------------------------------------------------------------------
/images/approve_transferFrom_workflow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/approve_transferFrom_workflow.png
--------------------------------------------------------------------------------
/images/auction_dapp_final_architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/auction_dapp_final_architecture.png
--------------------------------------------------------------------------------
/images/block_explorer_account_history.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/block_explorer_account_history.png
--------------------------------------------------------------------------------
/images/etherscan_withdrawal_internal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/etherscan_withdrawal_internal.png
--------------------------------------------------------------------------------
/images/metamask_account_context_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/metamask_account_context_menu.png
--------------------------------------------------------------------------------
/images/parity_deployment_confirmation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/parity_deployment_confirmation.png
--------------------------------------------------------------------------------
/images/published_contract_transactions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/published_contract_transactions.png
--------------------------------------------------------------------------------
/images/ens-manager-set-default-resolver.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ouyun/MasterEthereumChineseOpenEdition/HEAD/images/ens-manager-set-default-resolver.png
--------------------------------------------------------------------------------
/code/truffle/Faucet/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var Faucet = artifacts.require("./Faucet.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Faucet);
5 | };
6 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var Faucet = artifacts.require("./Faucet.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Faucet);
5 | };
6 |
--------------------------------------------------------------------------------
/code/truffle/Faucet/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/code/truffle/console/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/headings_cn.asciidoc:
--------------------------------------------------------------------------------
1 | ////
2 | Do not translate the :variable names:
3 | Translate the content following the variables
4 | ////
5 | :index_heading: Index
6 | :toc-title: 本书目录
7 | :table-caption: Table
8 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/code/truffle/CallExamples/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("./Migrations.sol");
2 |
3 | module.exports = function(deployer) {
4 | deployer.deploy(Migrations);
5 | };
6 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/code/Solidity/Token.sol:
--------------------------------------------------------------------------------
1 | import "Faucet.sol"
2 |
3 | contract Token is mortal {
4 |
5 | Faucet _faucet;
6 |
7 | constructor(address _f) {
8 | _faucet = Faucet(_f);
9 | _faucet.withdraw(0.1 ether)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/truffle.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | networks: {
3 | development: {
4 | host: "localhost",
5 | port: 8545,
6 | network_id: "*",
7 | gas: 3000000
8 | }
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/code/truffle/METoken/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var METoken = artifacts.require("METoken");
2 |
3 | module.exports = function(deployer) {
4 | // Deploy the METoken contract as our only task
5 | deployer.deploy(METoken);
6 | };
7 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/migrations/3_deploy_faucet.js:
--------------------------------------------------------------------------------
1 | var Faucet = artifacts.require("Faucet");
2 |
3 | module.exports = function(deployer) {
4 | // Deploy the Faucet contract as our only task
5 | deployer.deploy(Faucet);
6 | };
7 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var METoken = artifacts.require("METoken");
2 |
3 | module.exports = function(deployer) {
4 | // Deploy the METoken contract as our only task
5 | deployer.deploy(METoken);
6 | };
7 |
--------------------------------------------------------------------------------
/code/truffle/METoken/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("Migrations");
2 |
3 | module.exports = function(deployer) {
4 | // Deploy the Migrations contract as our only task
5 | deployer.deploy(Migrations);
6 | };
7 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("Migrations");
2 |
3 | module.exports = function(deployer) {
4 | // Deploy the Migrations contract as our only task
5 | deployer.deploy(Migrations);
6 | };
7 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/migrations/1_initial_migration.js:
--------------------------------------------------------------------------------
1 | var Migrations = artifacts.require("Migrations");
2 |
3 | module.exports = function(deployer) {
4 | // Deploy the Migrations contract as our only task
5 | deployer.deploy(Migrations);
6 | };
7 |
--------------------------------------------------------------------------------
/title_cn.asciidoc:
--------------------------------------------------------------------------------
1 | ////
2 | Do not translate the :variable names:
3 | Translate the content following the variables
4 | ////
5 | :author: Andreas M. Antonopoulos, Gavin Wood
6 | :book_title: 《精通以太坊》中文开放版
7 | :subtitle: 构建智能合约(Smart Contractts)和分布式应用(DApps)
8 | :publisher: Aantonop 图书有限公司
9 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/ERC721/ERC721Holder.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 | import "./ERC721Receiver.sol";
4 |
5 |
6 | contract ERC721Holder is ERC721Receiver {
7 | function onERC721Received(address, uint256, bytes) public returns(bytes4) {
8 | return ERC721_RECEIVED;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/code/truffle/Faucet/truffle-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | networks: {
3 | localnode: { // Whatever network our local node connects to
4 | network_id: "*", // Match any network id
5 | host: "localhost",
6 | port: 8545,
7 | gas: 4700000,
8 | gasPrice: 100000000000,
9 | }
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"]
12 | }
13 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/truffle-config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | networks: {
3 | localnode: { // Whatever network our local node connects to
4 | network_id: "*", // Match any network id
5 | host: "localhost",
6 | port: 8545,
7 | gas: 4700000,
8 | gasPrice: 100000000000,
9 | }
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/code/OpenZeppelin/contracts/SampleToken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.23;
2 |
3 | import 'openzeppelin-solidity/contracts/token/ERC20/MintableToken.sol';
4 |
5 | contract SampleToken is MintableToken {
6 | string public name = "SAMPLE TOKEN";
7 | string public symbol = "SAM";
8 | uint8 public decimals = 18;
9 | }
10 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/code/web3js/raw_tx/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "raw_tx",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "raw_tx_demo.js",
6 | "scripts": {
7 | "test": "raw_tx_demo.js"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "ethereumjs-tx": "^1.3.3",
13 | "ethereumjs-util": "^5.1.5",
14 | "rlp": "^2.0.0"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var AuctionRepository = artifacts.require("./AuctionRepository.sol");
2 | var DeedRepository = artifacts.require("./DeedRepository.sol");
3 | // DeedRepository => 0xbb55adc67f64d1e6f08ba7523ecd2eca2ee434a3
4 | module.exports = function(deployer) {
5 | deployer.deploy(AuctionRepository);
6 | deployer.deploy(DeedRepository, "Ultra Auction NFT", "UANFT");
7 | };
8 |
--------------------------------------------------------------------------------
/code/jsonrpc/http/js/README.md:
--------------------------------------------------------------------------------
1 | # Ethereum HTTP Client
2 |
3 | Connect to a node using HTTP(POST) and call the following rpc:
4 | - Get accounts associated with a node(Only you should be able to access these endpoint)
5 | - Get the current block number
6 |
7 |
8 | ## Build Setup
9 |
10 | ``` bash
11 | # install dependencies
12 | npm install
13 |
14 | # run the node script
15 | npm run http
16 |
17 | ```
18 |
--------------------------------------------------------------------------------
/code/jsonrpc/websockets/README.md:
--------------------------------------------------------------------------------
1 | # Ethereum WS Client
2 |
3 | Connect to a node using Websockets and call the following rpc:
4 | - Get accounts associated with a node(Only you should be able to access these endpoint)
5 | - Get the current block number
6 |
7 |
8 | ## Build Setup
9 |
10 | ``` bash
11 | # install dependencies
12 | npm install
13 |
14 | # run the node script
15 | npm run rpc
16 |
17 | ```
18 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/README.md:
--------------------------------------------------------------------------------
1 | # Auction Platform Fronten
2 |
3 | > Decentralized Auction Platform
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 |
--------------------------------------------------------------------------------
/code/truffle/CallExamples/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var caller = artifacts.require("caller");
2 | var calledContract = artifacts.require("calledContract");
3 | var calledLibrary = artifacts.require("calledLibrary");
4 |
5 | module.exports = function(deployer) {
6 |
7 | deployer.deploy(calledContract);
8 | deployer.deploy(calledLibrary);
9 |
10 | deployer.link(calledLibrary, [caller]);
11 |
12 | deployer.deploy(caller);
13 | };
14 |
--------------------------------------------------------------------------------
/code/truffle/console/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web3_console",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "nonce.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "dotenv": "^5.0.1",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/Faucet/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "faucet",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "truffle-config.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "dotenv": "^5.0.0",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "faucet",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "truffle-config.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "dotenv": "^5.0.0",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/CallExamples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "contractcalls",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "truffle-config.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "dotenv": "^5.0.1",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/METoken/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "metoken",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "truffle.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "zeppelin-solidity": "^1.6.0"
13 | },
14 | "devDependencies": {
15 | "dotenv": "^5.0.0",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "metoken",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "truffle.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "zeppelin-solidity": "^1.6.0"
13 | },
14 | "devDependencies": {
15 | "dotenv": "^5.0.0",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "metoken",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "truffle.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "openzeppelin-solidity": "^1.6.0"
13 | },
14 | "devDependencies": {
15 | "dotenv": "^5.0.0",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/code/truffle/FaucetReentryAttack/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "faucet",
3 | "version": "1.0.0",
4 | "main": "truffle-config.js",
5 | "directories": {
6 | "test": "test"
7 | },
8 | "scripts": {
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {},
14 | "devDependencies": {
15 | "dotenv": "^5.0.1",
16 | "ethereumjs-wallet": "^0.6.0",
17 | "truffle-wallet-provider": "0.0.5"
18 | },
19 | "description": ""
20 | }
21 |
--------------------------------------------------------------------------------
/code/aws/genesis.json:
--------------------------------------------------------------------------------
1 | {
2 | "config": {
3 | "chainId": 15,
4 | "homesteadBlock": 0,
5 | "eip155Block": 0,
6 | "eip158Block": 0
7 | },
8 | "nonce": "0x0000000000000042",
9 | "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
10 | "difficulty": "0x4000",
11 | "alloc": {},
12 | "coinbase": "0x0000000000000000000000000000000000000000",
13 | "timestamp": "0x00",
14 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
15 | "gasLimit": "0xffffffff"
16 | }
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | var METoken = artifacts.require("METoken");
2 | var METFaucet = artifacts.require("METFaucet");
3 | var owner = web3.eth.accounts[0];
4 |
5 | module.exports = function(deployer) {
6 |
7 | // Deploy the METoken contract first
8 | deployer.deploy(METoken, {from: owner}).then(function() {
9 | // then deploy METFaucet and pass the address of METoken
10 | // and the address of the owner of all the MET who will approve METFaucet
11 | return deployer.deploy(METFaucet, METoken.address, owner);
12 | });
13 | }
14 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Home from '@/components/Home'
4 | import Auction from '@/components/Auction'
5 |
6 | Vue.use(Router)
7 |
8 | export default new Router({
9 | routes: [
10 | {
11 | path: '/',
12 | name: 'Home',
13 | component: Home
14 | },
15 | {
16 | path: '/auctions/:id',
17 | name: 'Auction',
18 | component: Auction
19 | }
20 | ],
21 | mode: 'history',
22 | scrollBehavior (to, from, savedPosition) {
23 | return { x: 0, y: 0 }
24 | }
25 | })
26 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.6.0;
3 |
4 | // Our first contract is a faucet!
5 | contract Faucet {
6 | // Accept any incoming amount
7 | receive () external payable {}
8 |
9 | // Give out ether to anyone who asks
10 | function withdraw(uint withdraw_amount) public {
11 |
12 | // Limit withdrawal amount
13 | require(withdraw_amount <= 100000000000000000);
14 |
15 | // Send the amount to the address that requested it
16 | msg.sender.transfer(withdraw_amount);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/code/truffle/Faucet/contracts/Faucet.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.19;
3 |
4 | // Our first contract is a faucet!
5 | contract Faucet {
6 |
7 | // Give out ether to anyone who asks
8 | function withdraw(uint withdraw_amount) public {
9 |
10 | // Limit withdrawal amount
11 | require(withdraw_amount <= 100000000000000000);
12 |
13 | // Send the amount to the address that requested it
14 | msg.sender.transfer(withdraw_amount);
15 | }
16 |
17 | // Accept any incoming amount
18 | function () external payable {}
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet2.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.19;
3 |
4 | // Our first contract is a faucet!
5 | contract Faucet {
6 |
7 | // Give out ether to anyone who asks
8 | function withdraw(uint withdraw_amount) public {
9 |
10 | // Limit withdrawal amount
11 | require(withdraw_amount <= 100000000000000000);
12 |
13 | // Send the amount to the address that requested it
14 | msg.sender.transfer(withdraw_amount);
15 | }
16 |
17 | // Accept any incoming amount
18 | function () external payable {}
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/contracts/Faucet.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.19;
3 |
4 | // Our first contract is a faucet!
5 | contract Faucet {
6 |
7 | // Give out ether to anyone who asks
8 | function withdraw(uint withdraw_amount) public {
9 |
10 | // Limit withdrawal amount
11 | require(withdraw_amount <= 100000000000000000);
12 |
13 | // Send the amount to the address that requested it
14 | msg.sender.transfer(withdraw_amount);
15 | }
16 |
17 | // Accept any incoming amount
18 | function () external payable {}
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/code/truffle/METoken/contracts/METoken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.21;
2 |
3 | import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol';
4 |
5 | contract METoken is StandardToken {
6 | string public constant name = 'Mastering Ethereum Token';
7 | string public constant symbol = 'MET';
8 | uint8 public constant decimals = 2;
9 | uint constant _initial_supply = 2100000000;
10 |
11 | function METoken() public {
12 | totalSupply_ = _initial_supply;
13 | balances[msg.sender] = _initial_supply;
14 | emit Transfer(address(0), msg.sender, _initial_supply);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/contracts/METoken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 | import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol';
4 |
5 | contract METoken is StandardToken {
6 | string public constant name = 'Mastering Ethereum Token';
7 | string public constant symbol = 'MET';
8 | uint8 public constant decimals = 2;
9 | uint constant _initial_supply = 2100000000;
10 |
11 | function METoken() public {
12 | totalSupply_ = _initial_supply;
13 | balances[msg.sender] = _initial_supply;
14 | Transfer(address(0), msg.sender, _initial_supply);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/contracts/METoken.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 | import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol';
4 |
5 | contract METoken is StandardToken {
6 | string public constant name = 'Mastering Ethereum Token';
7 | string public constant symbol = 'MET';
8 | uint8 public constant decimals = 2;
9 | uint constant _initial_supply = 2100000000;
10 |
11 | function METoken() public {
12 | totalSupply_ = _initial_supply;
13 | balances[msg.sender] = _initial_supply;
14 | Transfer(address(0), msg.sender, _initial_supply);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/code/truffle/Faucet/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/truffle/METoken/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/truffle/console/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/truffle/CallExamples/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/ERC721/DeprecatedERC721.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 | import "./ERC721.sol";
4 |
5 |
6 | /**
7 | * @title ERC-721 methods shipped in OpenZeppelin v1.7.0, removed in the latest version of the standard
8 | * @dev Only use this interface for compatibility with previously deployed contracts
9 | * @dev Use ERC721 for interacting with new contracts which are standard-compliant
10 | */
11 | contract DeprecatedERC721 is ERC721 {
12 | function takeOwnership(uint256 _tokenId) public;
13 | function transfer(address _to, uint256 _tokenId) public;
14 | function tokensOf(address _owner) public view returns (uint256[]);
15 | }
16 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/utils/math/Math.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 |
4 | /**
5 | * @title Math
6 | * @dev Assorted math operations
7 | */
8 | library Math {
9 | function max64(uint64 a, uint64 b) internal pure returns (uint64) {
10 | return a >= b ? a : b;
11 | }
12 |
13 | function min64(uint64 a, uint64 b) internal pure returns (uint64) {
14 | return a < b ? a : b;
15 | }
16 |
17 | function max256(uint256 a, uint256 b) internal pure returns (uint256) {
18 | return a >= b ? a : b;
19 | }
20 |
21 | function min256(uint256 a, uint256 b) internal pure returns (uint256) {
22 | return a < b ? a : b;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/code/OpenZeppelin/contracts/SampleCrowdsale.sol:
--------------------------------------------------------------------------------
1 | pragma solidity 0.4.23;
2 |
3 | import './SampleToken.sol';
4 | import 'openzeppelin-solidity/contracts/crowdsale/emission/MintedCrowdsale.sol';
5 | import 'openzeppelin-solidity/contracts/crowdsale/ \
6 | distribution/PostDeliveryCrowdsale.sol';
7 |
8 | contract SampleCrowdsale is PostDeliveryCrowdsale, MintedCrowdsale {
9 |
10 | constructor(
11 | uint256 _openingTime,
12 | uint256 _closingTime
13 | uint256 _rate,
14 | address _wallet,
15 | MintableToken _token
16 | )
17 | public
18 | Crowdsale(_rate, _wallet, _token)
19 | PostDeliveryCrowdsale(_openingTime, _closingTime)
20 | {
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/Migrations.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
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() public {
12 | owner = msg.sender;
13 | }
14 |
15 | function setCompleted(uint completed) public restricted {
16 | last_completed_migration = completed;
17 | }
18 |
19 | function upgrade(address new_address) public restricted {
20 | Migrations upgraded = Migrations(new_address);
21 | upgraded.setCompleted(last_completed_migration);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/contrib/example.asciidoc:
--------------------------------------------------------------------------------
1 | ////
2 | Source: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
3 | License: CC0
4 | Added By: @aantonop
5 | ////
6 |
7 |
8 | = The ERC20 Token Standard
9 |
10 | The ERC20 standard allows for the implementation of a standard API for tokens within smart contracts. This standard provides basic functionality to transfer tokens, as well as allow tokens to be approved so they can be spent by another on-chain third party. It is documented in https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md[EIP-20 Token Standard]
11 |
12 | == What Are Tokens?
13 |
14 | Tokens are abstractions that represent ownership, access or value...
15 |
16 | == Known Problems with ERC20 Tokens
17 |
18 | == Additional Standards (ERC223)
19 |
20 | === Rationale
21 |
--------------------------------------------------------------------------------
/code/OpenZeppelin/migrations/2_deploy_contracts.js:
--------------------------------------------------------------------------------
1 | const SampleCrowdsale = artifacts.require('./SampleCrowdsale.sol');
2 | const SampleToken = artifacts.require('./SampleToken.sol');
3 |
4 | module.exports = function(deployer, network, accounts) {
5 | const openingTime = web3.eth.getBlock('latest').timestamp + 2; // 2s in future
6 | const closingTime = openingTime + 86400 * 20; // 20 days
7 | const rate = new web3.BigNumber(1000);
8 | const wallet = accounts[1];
9 |
10 | return deployer
11 | .then(() => {
12 | return deployer.deploy(SampleToken);
13 | })
14 | .then(() => {
15 | return deployer.deploy(
16 | SampleCrowdsale,
17 | openingTime,
18 | closingTime,
19 | rate,
20 | wallet,
21 | SampleToken.address
22 | );
23 | });
24 | };
25 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/test/test_approve_transferFrom.js:
--------------------------------------------------------------------------------
1 | var METoken = artifacts.require("METoken");
2 | var METFaucet = artifacts.require("METFaucet");
3 |
4 | contract('METoken', function(accounts) {
5 | var Alice = accounts[0];
6 | var Bob = accounts[1];
7 |
8 |
9 | it("should approve METFaucet for up to 1000 MET ", function() {
10 | return METoken.deployed().then(instance => {
11 | instance.approve(METFaucet.address, 100000).then(function(result) {
12 | assert(result.logs[0].event, "Approval", "Expected approval event")
13 | });
14 | });
15 | });
16 | it("should allow Bob to withdraw 10 MET from METFaucet", function() {
17 | return METFaucet.deployed().then(instance => {
18 | instance.withdraw(1000, {from: Bob}).then(function(result) {
19 | console.log(result.logs);
20 | });
21 | });
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet3.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | // Our first contract is a faucet!
5 | contract Faucet {
6 |
7 | address owner;
8 |
9 | // Contract constructor: set owner
10 | constructor() {
11 | owner = msg.sender;
12 | }
13 |
14 | // Contract destructor
15 | function destroy() public {
16 | require(msg.sender == owner);
17 | selfdestruct(owner);
18 | }
19 |
20 | // Give out ether to anyone who asks
21 | function withdraw(uint withdraw_amount) public {
22 |
23 | // Limit withdrawal amount
24 | require(withdraw_amount <= 0.1 ether);
25 |
26 | // Send the amount to the address that requested it
27 | msg.sender.transfer(withdraw_amount);
28 | }
29 |
30 | // Accept any incoming amount
31 | function () external payable {}
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Auction Dapp
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
22 |
--------------------------------------------------------------------------------
/code/jsonrpc/websockets/app.js:
--------------------------------------------------------------------------------
1 | const WebSocket = require('ws');
2 | const wsEndpoint = "ws://172.16.163.129:8546"
3 | const ws = new WebSocket(wsEndpoint);
4 |
5 | const requests = [
6 | {
7 | // Get the current block number
8 | jsonrpc: "2.0",
9 | method: "eth_blockNumber",
10 | params: [],
11 | id: 1234
12 | },
13 | {
14 | // Get accounts on this node
15 | jsonrpc: "2.0",
16 | method: "eth_accounts",
17 | params: [],
18 | id: 12345
19 | }
20 | ]
21 |
22 | // Connection is established
23 | ws.on('open', function open() {
24 | requests.map((req) => {
25 | console.log("Call procedure: ", req.method)
26 | ws.send(JSON.stringify(req))
27 | })
28 | });
29 |
30 | // Listen for incoming messages
31 | ws.on('message', function incoming(data) {
32 | console.log("Ethereum node response: ", JSON.parse(data));
33 | });
34 |
--------------------------------------------------------------------------------
/settings_cn.asciidoc:
--------------------------------------------------------------------------------
1 | ////
2 | Do not translate
3 | ////
4 | ////
5 | General Settings
6 | ////
7 | :openedition:
8 | :doctype: book
9 | :toc:
10 | :toclevels: 6
11 | :imagesdir: .
12 | :stem: latexmath
13 | :latex:
14 | ////
15 | Available icon font sets
16 | fa: fontawesome
17 | octicon: Octicons
18 | fi: Foundation Icons
19 | pf: Payment Font
20 | ////
21 | :icons: font
22 | :icon-set: fa
23 | ////
24 | Print Variables
25 | ////
26 | :autofit-option:
27 | :media: prepress
28 | :pdf-page-size: 8in x 9in
29 | :pdf-style: theme.yml
30 | :pdf-fontsdir: fonts
31 | :pdf-stylesdir: .
32 | ////
33 | ePUB variables
34 | ////
35 | :front-cover-image: cover_oe.png
36 | :epub3-stylesdir: .
37 | ////
38 | Title variables
39 | ////
40 | :creator: {author}
41 | :authors: {author}
42 | :doctitle: {book_title}
43 | :web_URL: https://aantonop.com/
44 | :copyright_year: 2021
45 |
46 | :abspath: /path/to/images/folder/prefix/
--------------------------------------------------------------------------------
/code/jsonrpc/http/js/index.js:
--------------------------------------------------------------------------------
1 | const axios = require("axios")
2 | const url = "http://172.16.163.129:8545"
3 |
4 | const requests = [
5 | {
6 | // Get the current block number
7 | jsonrpc: "2.0",
8 | method: "eth_blockNumber",
9 | params: [],
10 | id: 1234
11 | },
12 | {
13 | // Get accounts on this node
14 | jsonrpc: "2.0",
15 | method: "eth_accounts",
16 | params: [],
17 | id: 12345
18 | }
19 | ]
20 |
21 | requests.map(async (request) => {
22 | try {
23 | // send the request
24 | console.log("Call procedure: ", request.method)
25 | const result = await axios.post(url, request)
26 |
27 | // check for errors
28 | if(result.data.error)
29 | console.log("Error: ", result.data.error.message)
30 | else
31 | console.log("Ethereum node response: ", result.data)
32 | } catch (e) {
33 | console.log("Error while connecting to the remote server", e)
34 | }
35 |
36 | })
--------------------------------------------------------------------------------
/code/Solidity/Faucet4.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | // Our first contract is a faucet!
5 | contract Faucet {
6 |
7 | address owner;
8 |
9 | // Contract constructor: set owner
10 | constructor() {
11 | owner = msg.sender;
12 | }
13 |
14 | // Access control modifier
15 | modifier onlyOwner {
16 | require(msg.sender == owner);
17 | _;
18 | }
19 |
20 | // Contract destructor
21 | function destroy() public onlyOwner {
22 | selfdestruct(owner);
23 | }
24 |
25 | // Give out ether to anyone who asks
26 | function withdraw(uint withdraw_amount) public {
27 |
28 | // Limit withdrawal amount
29 | require(withdraw_amount <= 0.1 ether);
30 |
31 | // Send the amount to the address that requested it
32 | msg.sender.transfer(withdraw_amount);
33 | }
34 |
35 | // Accept any incoming amount
36 | function () external payable {}
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet5.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | contract owned {
5 | address owner;
6 | // Contract constructor: set owner
7 | constructor() {
8 | owner = msg.sender;
9 | }
10 | // Access control modifier
11 | modifier onlyOwner {
12 | require(msg.sender == owner);
13 | _;
14 | }
15 | }
16 |
17 | contract mortal is owned {
18 | // Contract destructor
19 | function destroy() public onlyOwner {
20 | selfdestruct(owner);
21 | }
22 | }
23 |
24 | contract Faucet is mortal {
25 | // Give out ether to anyone who asks
26 | function withdraw(uint withdraw_amount) public {
27 | // Limit withdrawal amount
28 | require(withdraw_amount <= 0.1 ether);
29 | // Send the amount to the address that requested it
30 | msg.sender.transfer(withdraw_amount);
31 | }
32 | // Accept any incoming amount
33 | function () external payable {}
34 | }
35 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet6.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | contract owned {
5 | address owner;
6 | // Contract constructor: set owner
7 | constructor() {
8 | owner = msg.sender;
9 | }
10 | // Access control modifier
11 | modifier onlyOwner {
12 | require(msg.sender == owner, "Only the contract owner can call this function");
13 | _;
14 | }
15 | }
16 |
17 | contract mortal is owned {
18 | // Contract destructor
19 | function destroy() public onlyOwner {
20 | selfdestruct(owner);
21 | }
22 | }
23 |
24 | contract Faucet is mortal {
25 | // Give out ether to anyone who asks
26 | function withdraw(uint withdraw_amount) public {
27 | // Limit withdrawal amount
28 | require(withdraw_amount <= 0.1 ether);
29 | // Send the amount to the address that requested it
30 | msg.sender.transfer(withdraw_amount);
31 | }
32 | // Accept any incoming amount
33 | function () external payable {}
34 | }
35 |
--------------------------------------------------------------------------------
/code/truffle/METoken/test/METoken.test.js:
--------------------------------------------------------------------------------
1 | const METoken = artifacts.require("METoken");
2 |
3 | contract('METoken', accounts => {
4 |
5 | beforeEach(async function () {
6 | InstanceMEToken = await METoken.new();
7 | });
8 |
9 | it('has a name', async function () {
10 | const name = await InstanceMEToken.name();
11 | assert.notEqual(name, "", "token name shouldn't be empty");
12 | });
13 |
14 | it('has a symbol', async function () {
15 | const symbol = await InstanceMEToken.symbol();
16 | assert.notEqual(symbol, "", "token symbol shouldn't be empty");
17 | });
18 |
19 | it('has decimals', async function () {
20 | const decimals = await InstanceMEToken.decimals();
21 | assert.notEqual(decimals, "", "token decimals shouldn't be empty");
22 | });
23 |
24 | it('owner has 2100000000 tokens', async function () {
25 | const balance = await InstanceMEToken.balanceOf(accounts[0]);
26 | assert.equal(balance, 2100000000, "owner doesn't have 2100000000 tokens");
27 | });
28 | });
--------------------------------------------------------------------------------
/code/web3js/raw_tx/raw_tx_demo.js:
--------------------------------------------------------------------------------
1 | // Load requirements first:
2 | //
3 | // npm init
4 | // npm install ethereumjs-tx
5 | //
6 | // Run with: $ node raw_tx_demo.js
7 | const ethTx = require('ethereumjs-tx');
8 |
9 | const txData = {
10 | nonce: '0x0',
11 | gasPrice: '0x09184e72a000',
12 | gasLimit: '0x30000',
13 | to: '0xb0920c523d582040f2bcb1bd7fb1c7c1ecebdb34',
14 | value: '0x00',
15 | data: '',
16 | v: "0x1c", // Ethereum mainnet chainID
17 | r: 0,
18 | s: 0
19 | };
20 |
21 | tx = new ethTx(txData);
22 | console.log('RLP-Encoded Tx: 0x' + tx.serialize().toString('hex'))
23 |
24 | txHash = tx.hash(); // This step encodes into RLP and calculates the hash
25 | console.log('Tx Hash: 0x' + txHash.toString('hex'))
26 |
27 | // Sign transaction
28 | const privKey = Buffer.from(
29 | '91c8360c4cb4b5fac45513a7213f31d4e4a7bfcb4630e9fbf074f42a203ac0b9', 'hex');
30 | tx.sign(privKey);
31 |
32 | serializedTx = tx.serialize();
33 | rawTx = 'Signed Raw Transaction: 0x' + serializedTx.toString('hex');
34 | console.log(rawTx)
35 |
--------------------------------------------------------------------------------
/code/truffle/CallExamples/contracts/CallExamples.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.22;
2 |
3 | contract calledContract {
4 | event callEvent(address sender, address origin, address from);
5 | function calledFunction() public {
6 | emit callEvent(msg.sender, tx.origin, this);
7 | }
8 | }
9 |
10 | library calledLibrary {
11 | event callEvent(address sender, address origin, address from);
12 | function calledFunction() public {
13 | emit callEvent(msg.sender, tx.origin, this);
14 | }
15 | }
16 |
17 | contract caller {
18 |
19 | function make_calls(calledContract _calledContract) public {
20 |
21 | // Calling calledContract and calledLibrary directly
22 | _calledContract.calledFunction();
23 | calledLibrary.calledFunction();
24 |
25 | // Low-level calls using the address object for calledContract
26 | require(address(_calledContract).
27 | call(bytes4(keccak256("calledFunction()"))));
28 | require(address(_calledContract).
29 | delegatecall(bytes4(keccak256("calledFunction()"))));
30 |
31 |
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/gas_estimates.js:
--------------------------------------------------------------------------------
1 | var FaucetContract = artifacts.require("Faucet.sol");
2 |
3 | FaucetContract.web3.eth.getGasPrice(function(error, result) {
4 | var gasPrice = Number(result);
5 | console.log("Gas Price is " + gasPrice + " wei"); // "10000000000000"
6 |
7 | // Get the contract instance
8 | FaucetContract.deployed().then(function(FaucetContractInstance) {
9 |
10 | // Use the keyword 'estimateGas' after the function name to get the gas estimation for this particular function (aprove)
11 | FaucetContractInstance.send(web3.utils.toWei(1, "ether"));
12 | return FaucetContractInstance.withdraw.estimateGas(web3.utils.toWei(0.1, "ether"));
13 |
14 | }).then(function(result) {
15 | var gas = Number(result);
16 |
17 | console.log("gas estimation = " + gas + " units");
18 | console.log("gas cost estimation = " + (gas * gasPrice) + " wei");
19 | console.log("gas cost estimation = " + FaucetContract.web3.utils.fromWei((gas * gasPrice), 'ether') + " ether");
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/src/config.js:
--------------------------------------------------------------------------------
1 | var DeedRepository = require('./contracts/DeedRepository')
2 | var AuctionRepository = require('./contracts/AuctionRepository')
3 |
4 | module.exports = {
5 | JSONRPC_ENDPOINT: 'http://52.59.238.144:8545',
6 | JSONRPC_WS_ENDPOINT: 'ws://52.59.238.144:8546', //'ws://52.59.238.144:8546',
7 | BZZ_ENDPOINT: 'http://52.59.238.144:8500',
8 | SHH_ENDPOINT: 'ws://52.59.238.144:8546',
9 |
10 | DEEDREPOSITORY_ADDRESS: '0xfc35c45cd57661197d0bb19399c9d3ede1c50dcc',
11 | AUCTIONREPOSITORY_ADDRESS: '0xefbebbf64a570f7b94f168430f45ecbb87546f06',
12 |
13 | DEEDREPOSITORY_ABI: DeedRepository.abi,
14 | AUCTIONREPOSITORY_ABI: AuctionRepository.abi,
15 |
16 | GAS_AMOUNT: 500000,
17 |
18 | //whisper settings
19 | WHISPER_SHARED_KEY: '0x8bda3abeb454847b515fa9b404cede50b1cc63cfdeddd4999d074284b4c21e15'
20 |
21 | }
22 |
23 | // web3.eth.sendTransaction({from: web3.eth.accounts[0], to: "0x6f0023D1CFe5A7A56F96e61E0169B775Ac97f90E" , value: web3.utils.toWei(1, 'ether'), gasLimit: 21000, gasPrice: 20000000000})
24 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/contracts/METFaucet.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.19;
3 |
4 | import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol';
5 |
6 |
7 | // A faucet for ERC20 token MET
8 | contract METFaucet {
9 |
10 | StandardToken public METoken;
11 | address public METOwner;
12 |
13 | // METFaucet constructor, provide the address of METoken contract and
14 | // the owner address we will be approved to transferFrom
15 | function METFaucet(address _METoken, address _METOwner) public {
16 |
17 | // Initialize the METoken from the address provided
18 | METoken = StandardToken(_METoken);
19 | METOwner = _METOwner;
20 | }
21 |
22 | function withdraw(uint withdraw_amount) public {
23 |
24 | // Limit withdrawal amount to 10 MET
25 | require(withdraw_amount <= 1000);
26 |
27 | // Use the transferFrom function of METoken
28 | METoken.transferFrom(METOwner, msg.sender, withdraw_amount);
29 | }
30 |
31 | // REJECT any incoming ether
32 | function () external payable { revert(); }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet7.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | contract owned {
5 | address owner;
6 | // Contract constructor: set owner
7 | constructor() {
8 | owner = msg.sender;
9 | }
10 | // Access control modifier
11 | modifier onlyOwner {
12 | require(msg.sender == owner, "Only the contract owner can call this function");
13 | _;
14 | }
15 | }
16 |
17 | contract mortal is owned {
18 | // Contract destructor
19 | function destroy() public onlyOwner {
20 | selfdestruct(owner);
21 | }
22 | }
23 |
24 | contract Faucet is mortal {
25 | // Give out ether to anyone who asks
26 | function withdraw(uint withdraw_amount) public {
27 | // Limit withdrawal amount
28 | require(withdraw_amount <= 0.1 ether);
29 | require(this.balance >= withdraw_amount,
30 | "Insufficient balance in faucet for withdrawal request");
31 | // Send the amount to the address that requested it
32 | msg.sender.transfer(withdraw_amount);
33 | }
34 | // Accept any incoming amount
35 | function () external payable {}
36 | }
37 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/utils/AddressUtils.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 |
4 | /**
5 | * Utility library of inline functions on addresses
6 | */
7 | library AddressUtils {
8 |
9 | /**
10 | * Returns whether the target address is a contract
11 | * @dev This function will return false if invoked during the constructor of a contract,
12 | * as the code is not actually created until after the constructor finishes.
13 | * @param addr address to check
14 | * @return whether the target address is a contract
15 | */
16 | function isContract(address addr) internal view returns (bool) {
17 | uint256 size;
18 | // XXX Currently there is no better way to check if there is a contract in an address
19 | // than to check the size of the code at that address.
20 | // See https://ethereum.stackexchange.com/a/14016/36603
21 | // for more details about how this works.
22 | // TODO Check this again before the Serenity release, because all addresses will be
23 | // contracts then.
24 | assembly { size := extcodesize(addr) } // solium-disable-line security/no-inline-assembly
25 | return size > 0;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/contrib/aws-setup.asciidoc:
--------------------------------------------------------------------------------
1 | [[_anchor_introduction_aws_setup]]
2 | == Introduction
3 |
4 | This section describes in detail the set-up of a private Ethereum network and deployment of *Mastering Ethereum Token (MET)* on Amazon Web Services (AWS) cloud.
5 |
6 | Broadly, there are two categories of steps to work with a private Ethereum network as shown below. Each category calls out the high level steps to be followed.
7 |
8 | 1. *Network set-up*
9 | . Set up nodes for launch
10 | . Configuring genesis for nodes
11 | . Peering
12 |
13 | 2. *Network operation*
14 | . Account set-up
15 | . Mining
16 | . RPC end-point
17 | . Contract deployment and execution
18 |
19 | [[_anchor_pre_requisites]]
20 | == Pre-requisites
21 |
22 | The following pre-requisites apply:
23 |
24 | - An AWS account. If you do not have one, create here https://aws.amazon.com/account/
25 | - General command line knowledge on Linux (ideally, Ubuntu) operating system.
26 |
27 | [[_anchor_network_launch]]
28 | == Launch
29 | To launch a private Ethereum network and deploy contracts, follow the links below:
30 |
31 | * link:aws-network-setup.asciidoc[Setting up a private Ethereum network on AWS]
32 | * link:aws-network-operation.asciidoc[Operating a private Ethereum network on AWS]
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/ERC721/ERC721.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 | import "./ERC721Basic.sol";
4 |
5 |
6 | /**
7 | * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
8 | * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
9 | */
10 | contract ERC721Enumerable is ERC721Basic {
11 | function totalSupply() public view returns (uint256);
12 | function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256 _tokenId);
13 | function tokenByIndex(uint256 _index) public view returns (uint256);
14 | }
15 |
16 |
17 | /**
18 | * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
19 | * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
20 | */
21 | contract ERC721Metadata is ERC721Basic {
22 | function name() public view returns (string _name);
23 | function symbol() public view returns (string _symbol);
24 | function tokenURI(uint256 _tokenId) public view returns (string);
25 | }
26 |
27 |
28 | /**
29 | * @title ERC-721 Non-Fungible Token Standard, full implementation interface
30 | * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
31 | */
32 | contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata {
33 | }
34 |
--------------------------------------------------------------------------------
/book_cn.asciidoc:
--------------------------------------------------------------------------------
1 | include::title_cn.asciidoc[]
2 | include::headings_cn.asciidoc[]
3 | include::settings_cn.asciidoc[]
4 | = {book_title}
5 |
6 | include::preface_open_edition_cn.asciidoc[]
7 |
8 | include::glossary_cn.asciidoc[]
9 |
10 | include::01what-is_cn.asciidoc[]
11 |
12 | include::02intro_cn.asciidoc[]
13 |
14 | include::03clients_cn.asciidoc[]
15 |
16 | include::04keys-addresses_cn.asciidoc[]
17 |
18 | include::05wallets_cn.asciidoc[]
19 |
20 | include::06transactions_cn.asciidoc[]
21 |
22 | include::07smart-contracts-solidity_cn.asciidoc[]
23 |
24 | include::08smart-contracts-vyper_cn.asciidoc[]
25 |
26 | include::09smart-contracts-security_cn.asciidoc[]
27 |
28 | include::10tokens_cn.asciidoc[]
29 |
30 | include::11oracles_cn.asciidoc[]
31 |
32 | include::12dapps_cn.asciidoc[]
33 |
34 | include::13evm_cn.asciidoc[]
35 |
36 | include::14consensus_cn.asciidoc[]
37 |
38 | [appendix]
39 | include::appdx-forks-history_cn.asciidoc[]
40 |
41 | [appendix]
42 | include::appdx-standards-eip-erc_cn.asciidoc[]
43 |
44 | [appendix]
45 | include::appdx-evm-opcodes-gas_cn.asciidoc[]
46 |
47 | [appendix]
48 | include::appdx-dev-tools_cn.asciidoc[]
49 |
50 | [appendix]
51 | include::appdx-web3js-tutorial_cn.asciidoc[]
52 |
53 | [appendix]
54 | include::appdx-shortlinks.asciidoc[]
55 |
--------------------------------------------------------------------------------
/code/Solidity/Faucet8.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | contract owned {
5 | address owner;
6 | // Contract constructor: set owner
7 | constructor() {
8 | owner = msg.sender;
9 | }
10 | // Access control modifier
11 | modifier onlyOwner {
12 | require(msg.sender == owner,
13 | "Only the contract owner can call this function");
14 | _;
15 | }
16 | }
17 |
18 | contract mortal is owned {
19 | // Contract destructor
20 | function destroy() public onlyOwner {
21 | selfdestruct(owner);
22 | }
23 | }
24 |
25 | contract Faucet is mortal {
26 | event Withdrawal(address indexed to, uint amount);
27 | event Deposit(address indexed from, uint amount);
28 |
29 | // Give out ether to anyone who asks
30 | function withdraw(uint withdraw_amount) public {
31 | // Limit withdrawal amount
32 | require(withdraw_amount <= 0.1 ether);
33 | require(this.balance >= withdraw_amount,
34 | "Insufficient balance in faucet for withdrawal request");
35 | // Send the amount to the address that requested it
36 | msg.sender.transfer(withdraw_amount);
37 | emit Withdrawal(msg.sender, withdraw_amount);
38 | }
39 | // Accept any incoming amount
40 | function () external payable {
41 | emit Deposit(msg.sender, msg.value);
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/code/truffle/FaucetEvents/contracts/Faucet.sol:
--------------------------------------------------------------------------------
1 | // Version of Solidity compiler this program was written for
2 | pragma solidity ^0.4.22;
3 |
4 | contract owned {
5 | address owner;
6 | // Contract constructor: set owner
7 | constructor() {
8 | owner = msg.sender;
9 | }
10 | // Access control modifier
11 | modifier onlyOwner {
12 | require(msg.sender == owner, "Only the contract owner can call this function");
13 | _;
14 | }
15 | }
16 |
17 | contract mortal is owned {
18 | // Contract destructor
19 | function destroy() public onlyOwner {
20 | selfdestruct(owner);
21 | }
22 | }
23 |
24 | contract Faucet is mortal {
25 | event Withdrawal(address indexed to, uint amount);
26 | event Deposit(address indexed from, uint amount);
27 |
28 | // Give out ether to anyone who asks
29 | function withdraw(uint withdraw_amount) public {
30 | // Limit withdrawal amount
31 | require(withdraw_amount <= 0.1 ether);
32 | require(this.balance >= withdraw_amount,
33 | "Insufficient balance in faucet for withdrawal request");
34 | // Send the amount to the address that requested it
35 | msg.sender.transfer(withdraw_amount);
36 | emit Withdrawal(msg.sender, withdraw_amount);
37 | }
38 | // Accept any incoming amount
39 | function () external payable {
40 | emit Deposit(msg.sender, msg.value);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/utils/math/SafeMath.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 |
4 | /**
5 | * @title SafeMath
6 | * @dev Math operations with safety checks that throw on error
7 | */
8 | library SafeMath {
9 |
10 | /**
11 | * @dev Multiplies two numbers, throws on overflow.
12 | */
13 | function mul(uint256 a, uint256 b) internal pure returns (uint256) {
14 | if (a == 0) {
15 | return 0;
16 | }
17 | uint256 c = a * b;
18 | assert(c / a == b);
19 | return c;
20 | }
21 |
22 | /**
23 | * @dev Integer division of two numbers, truncating the quotient.
24 | */
25 | function div(uint256 a, uint256 b) internal pure returns (uint256) {
26 | // assert(b > 0); // Solidity automatically throws when dividing by 0
27 | // uint256 c = a / b;
28 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold
29 | return a / b;
30 | }
31 |
32 | /**
33 | * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
34 | */
35 | function sub(uint256 a, uint256 b) internal pure returns (uint256) {
36 | assert(b <= a);
37 | return a - b;
38 | }
39 |
40 | /**
41 | * @dev Adds two numbers, throws on overflow.
42 | */
43 | function add(uint256 a, uint256 b) internal pure returns (uint256) {
44 | uint256 c = a + b;
45 | assert(c >= a);
46 | return c;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/ERC721/ERC721Receiver.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 |
4 | /**
5 | * @title ERC721 token receiver interface
6 | * @dev Interface for any contract that wants to support safeTransfers
7 | * from ERC721 asset contracts.
8 | */
9 | contract ERC721Receiver {
10 | /**
11 | * @dev Magic value to be returned upon successful reception of an NFT
12 | * Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`,
13 | * which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
14 | */
15 | bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba;
16 |
17 | /**
18 | * @notice Handle the receipt of an NFT
19 | * @dev The ERC721 smart contract calls this function on the recipient
20 | * after a `safetransfer`. This function MAY throw to revert and reject the
21 | * transfer. This function MUST use 50,000 gas or less. Return of other
22 | * than the magic value MUST result in the transaction being reverted.
23 | * Note: the contract address is always the message sender.
24 | * @param _from The sending address
25 | * @param _tokenId The NFT identifier which is being transfered
26 | * @param _data Additional data with no specified format
27 | * @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`
28 | */
29 | function onERC721Received(address _from, uint256 _tokenId, bytes _data) public returns(bytes4);
30 | }
31 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/ERC721/ERC721Basic.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 |
4 | /**
5 | * @title ERC721 Non-Fungible Token Standard basic interface
6 | * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
7 | */
8 | contract ERC721Basic {
9 | event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
10 | event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
11 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);
12 |
13 | function balanceOf(address _owner) public view returns (uint256 _balance);
14 | function ownerOf(uint256 _tokenId) public view returns (address _owner);
15 | function exists(uint256 _tokenId) public view returns (bool _exists);
16 |
17 | function approve(address _to, uint256 _tokenId) public;
18 | function getApproved(uint256 _tokenId) public view returns (address _operator);
19 |
20 | function setApprovalForAll(address _operator, bool _approved) public;
21 | function isApprovedForAll(address _owner, address _operator) public view returns (bool);
22 |
23 | function transferFrom(address _from, address _to, uint256 _tokenId) public;
24 | function safeTransferFrom(address _from, address _to, uint256 _tokenId) public;
25 | function safeTransferFrom(
26 | address _from,
27 | address _to,
28 | uint256 _tokenId,
29 | bytes _data
30 | )
31 | public;
32 | }
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MasterEthereumChineseOpenEdition - 《精通以太坊》中文开放版
2 |
3 | 大佬侯俊杰曾在他的著作《深入浅出MFC 2e》中以“勿在浮沙建高台”为第1篇的标题,共勉之!
4 |
5 | 此中文版动态跟踪[Master Ethereum](https://github.com/ethereumbook/ethereumbook/)的开放版分支的最新提交,后续将不断迭代订正并同步。
6 |
7 | ### 封面
8 | 
9 |
10 | ## 目录
11 |
12 | ### [前言](preface_open_edition_cn.asciidoc)
13 | ### [简明词汇⽬录](glossary_cn.asciidoc)
14 | ### [第一章:什么是以太坊](01what-is_cn.asciidoc)
15 | ### [第二章:以太坊基础](02intro_cn.asciidoc)
16 | ### [第三章:以太坊客户](03clients_cn.asciidoc)
17 | ### [第四章:密码学](04keys-addresses_cn.asciidoc)
18 | ### [第五章:钱包](05wallets_cn.asciidoc)
19 | ### [第六章:交易](06transactions_cn.asciidoc)
20 | ### [第七章:智能合约和Solidity](07smart-contracts-solidity_cn.asciidoc)
21 | ### [第八章:智能合约和Vyper语⾔](08smart-contracts-vyper_cn.asciidoc)
22 | ### [第九章:智能合约的安全问题](09smart-contracts-security_cn.asciidoc)
23 | ### [第十章:通证](10tokens_cn.asciidoc)
24 | ### [第十一章:预⾔机](11oracles_cn.asciidoc)
25 | ### [第十二章:去中⼼化应⽤程序(DApps)](12dapps_cn.asciidoc)
26 | ### [第十三章:以太坊虚拟机](13evm_cn.asciidoc)
27 | ### [第十四章:共识](14consensus_cn.asciidoc)
28 | ### [附录A:以太坊分叉历史](appdx-forks-history_cn.asciidoc)
29 | ### [附录B:以太坊标准](appdx-standards-eip-erc_cn.asciidoc)
30 | ### [附录C:以太坊虚拟机EVM操作码和所需燃料gas量](appdx-evm-opcodes-gas_cn.asciidoc)
31 | ### [附录D:开发⼯具,开发框架和库](appdx-dev-tools_cn.asciidoc)
32 | ### [附录E:web3.js教程](appdx-web3js-tutorial_cn.asciidoc)
33 | ### [附录F:本书短链接引用](appdx-shortlinks_cn.asciidoc)
34 |
35 | ## 迭代流程
36 | ### openedition ===> open ---> en_cn <--- cn ---> master
37 |
--------------------------------------------------------------------------------
/code/auction_dapp/DEV_README.md:
--------------------------------------------------------------------------------
1 | # Configuring truffle
2 | Guide to properly configure truffle to build and deploy contracts to the network
3 |
4 |
5 | ## Add local testnet
6 |
7 | Edit `truffle.js` :
8 |
9 | ```
10 | networks: {
11 | development: {
12 | host: "",
13 | port: 8545,
14 | network_id: "*",
15 | gas: 2900000
16 | }
17 | }
18 | ```
19 |
20 | ## Commands
21 |
22 | ```
23 | $ truffle init #initialize truffle project
24 | $ truffle console
25 | $ truffle deploy
26 | $ truffle migrate --reset --compile-all #redeploy the smat contracts
27 |
28 | ```
29 |
30 | ## Errors
31 | Here is a list of possible errors:
32 |
33 | ## ParserError: Expected token Semicolon got 'LParen'
34 |
35 | Emitting events gives compilation error if solc-js not 0.4.21
36 | Update truffle using:
37 |
38 | ```
39 | $ cd /usr/lib/node_modules/truffle
40 | $ npm install solc@0.4.21 --save
41 | ```
42 |
43 | ### Account is locked/Auth needed
44 |
45 | ```
46 | $ truffle console
47 | truffle(development)> var acc = web3.eth.accounts[0]
48 | truffle(development)> web3.personal.unlockAccount(acc, 'pass', 36000)
49 | ```
50 |
51 | Then deploy. Repeat the step when needed
52 |
53 | ### Intrinsic gas too low
54 |
55 | ```
56 | $ truffle console
57 | truffle(development)> web3.eth.getBlock("pending").gasLimit
58 | xxxxxxx
59 | ```
60 |
61 | edit truffle.js
62 |
63 | ```
64 | development: {
65 | ...
66 | gas: xxxxxxxxx,
67 | network_id: "*"
68 | }
69 | ```
70 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/scripts/prepare.js:
--------------------------------------------------------------------------------
1 | var deedabi = require("./build/contracts/DeedRepository.json").abi;
2 | var deedaddress = "0x454e7bd1e743ec2517a104758895bec40d9ffb9d";
3 | var auctionabi = require("./build/contracts/AuctionRepository.json").abi;
4 | var auctionaddress = "0x14fba6349fe2f9187d08391b8dc2ca0c3742e285";
5 |
6 | var deedinstance = web3.eth.contract(deedabi).at(deedaddress);
7 | var auctioninstance = web3.eth.contract(auctionabi).at(auctionaddress);
8 | var acc = web3.eth.accounts[0];
9 | var ops = { from: acc, gas: 300000 };
10 | //register a deed and transfer to auctionrepository address
11 |
12 | deedinstance.registerDeed(acc, 123456789, ops);
13 | deedinstance.approve(auctionaddress, 123456789, ops);
14 | deedinstance.transferFrom( acc ,auctionaddress, 123456789, ops );
15 |
16 | // create auction
17 | var startprice = new web3.BigNumber(1000000000000000000)
18 | auctioninstance.createAuction(deedaddress, 123456789, "My title", "meta://", startprice, 1527811200 , ops );
19 |
20 | auctioninstance.getAuctionsCount(ops); // should be 1
21 |
22 | auctioninstance.getAuctionById(0, ops);
23 |
24 | auctioninstance.bidOnAuction(0, { from: web3.eth.accounts[1], gas: 300000, value: new web3.BigNumber(2000000000000000000) }); // should be 1
25 | // error..cant bid on auction that is owned
26 | auctioninstance.getBidsCount(0, ops)
27 |
28 | // balance of account 2 should be 9899xxxxxx
29 | web3.eth.getBalance(web3.eth.accounts[1]).toNumber()
30 |
31 | auctioninstance.cancelAuction(0, ops);
32 |
33 | // balance back to where it was minus some gas costs
34 | web3.eth.getBalance(web3.eth.accounts[1]).toNumber()
35 |
36 |
--------------------------------------------------------------------------------
/code/jsonrpc/ipc/client.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io"
7 | "log"
8 | "net"
9 | "sync"
10 | )
11 |
12 | // Request represents the jsonrpc2 request
13 | type Request struct {
14 | Jsonrpc string `json:"jsonrpc"`
15 | Method string `json:"method"`
16 | Params interface{} `json:"params"`
17 | ID uint64 `json:"id"`
18 | }
19 |
20 | // ReadIPC reads from a socket
21 | func ReadIPC(r io.Reader, wg *sync.WaitGroup) {
22 | //20KB buffer
23 | buf := make([]byte, 20*1024)
24 | n, err := r.Read(buf[:])
25 | if err != nil {
26 | log.Fatal("Unable to read from socket", err)
27 | }
28 | fmt.Println("Ethereum node response: ", string(buf[0:n]))
29 | wg.Done()
30 | }
31 |
32 | func main() {
33 | var wg sync.WaitGroup
34 | socketfile := "/home/younix/testnet/chaindata/geth.ipc"
35 |
36 | // create a request
37 | params := make([]int, 0)
38 | request := &Request{
39 | Jsonrpc: "2.0",
40 | Method: "eth_blockNumber",
41 | Params: params,
42 | ID: 12345,
43 | }
44 |
45 | // marshal the struct to json string
46 | strRequest, err := json.Marshal(&request)
47 | if err != nil {
48 | log.Fatal("Unable to encode request", err)
49 | }
50 |
51 | // dial the socket
52 | ipc, err := net.Dial("unix", socketfile)
53 | if err != nil {
54 | log.Fatal("Unable to connect to the unix socket", err)
55 | }
56 | defer ipc.Close()
57 |
58 | // listen for incoming messages
59 | wg.Add(1)
60 | go ReadIPC(ipc, &wg)
61 |
62 | // write to the unix socket
63 | fmt.Println("Call procedure: ", request.Method)
64 | _, err = ipc.Write(strRequest)
65 | if err != nil {
66 | log.Fatal("Unable to write to the unix socket", err)
67 | }
68 |
69 | // wait for response
70 | wg.Wait()
71 | }
72 |
--------------------------------------------------------------------------------
/code/truffle/METoken/truffle-config.js:
--------------------------------------------------------------------------------
1 | // Install dependencies:
2 | // npm init
3 | // npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
4 |
5 | // Create .env in project root, with keys:
6 | // ROPSTEN_PRIVATE_KEY="123abc"
7 | // MAINNET_PRIVATE_KEY="123abc"
8 |
9 | require('dotenv').config();
10 | const Web3 = require("web3");
11 | const web3 = new Web3();
12 | const WalletProvider = require("truffle-wallet-provider");
13 | const Wallet = require('ethereumjs-wallet');
14 |
15 | var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
16 | var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
17 | var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
18 |
19 | var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
20 | var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
21 | var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
22 |
23 | module.exports = {
24 | networks: {
25 | dev: { // Whatever network our local node connects to
26 | network_id: "*", // Match any network id
27 | host: "localhost",
28 | port: 8545,
29 | },
30 | mainnet: { // Provided by Infura, load keys in .env file
31 | network_id: "1",
32 | provider: mainNetProvider,
33 | gas: 4600000,
34 | gasPrice: web3.utils.toWei("20", "gwei"),
35 | },
36 | ropsten: { // Provided by Infura, load keys in .env file
37 | network_id: "3",
38 | provider: ropstenProvider,
39 | gas: 4600000,
40 | gasPrice: web3.utils.toWei("20", "gwei"),
41 | },
42 | kovan: {
43 | network_id: 42,
44 | host: "localhost", // parity --chain=kovan
45 | port: 8545,
46 | gas: 5000000
47 | },
48 | ganache: { // Ganache local test RPC blockchain
49 | network_id: "5777",
50 | host: "localhost",
51 | port: 7545,
52 | gas: 6721975,
53 | }
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/code/truffle/console/truffle-config.js:
--------------------------------------------------------------------------------
1 | // Install dependencies:
2 | // npm init
3 | // npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
4 |
5 | // Create .env in project root, with keys:
6 | // ROPSTEN_PRIVATE_KEY="123abc"
7 | // MAINNET_PRIVATE_KEY="123abc"
8 |
9 | require('dotenv').config();
10 | const Web3 = require("web3");
11 | const web3 = new Web3();
12 | const WalletProvider = require("truffle-wallet-provider");
13 | const Wallet = require('ethereumjs-wallet');
14 |
15 | var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
16 | var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
17 | var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
18 |
19 | var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
20 | var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
21 | var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
22 |
23 | module.exports = {
24 | networks: {
25 | dev: { // Whatever network our local node connects to
26 | network_id: "*", // Match any network id
27 | host: "localhost",
28 | port: 8545,
29 | },
30 | mainnet: { // Provided by Infura, load keys in .env file
31 | network_id: "1",
32 | provider: mainNetProvider,
33 | gas: 4600000,
34 | gasPrice: web3.utils.toWei("20", "gwei"),
35 | },
36 | ropsten: { // Provided by Infura, load keys in .env file
37 | network_id: "3",
38 | provider: ropstenProvider,
39 | gas: 4600000,
40 | gasPrice: web3.utils.toWei("20", "gwei"),
41 | },
42 | kovan: {
43 | network_id: 42,
44 | host: "localhost", // parity --chain=kovan
45 | port: 8545,
46 | gas: 5000000
47 | },
48 | ganache: { // Ganache local test RPC blockchain
49 | network_id: "5777",
50 | host: "localhost",
51 | port: 7545,
52 | gas: 6721975,
53 | }
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/code/truffle/CallExamples/truffle-config.js:
--------------------------------------------------------------------------------
1 | // Install dependencies:
2 | // npm init
3 | // npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
4 |
5 | // Create .env in project root, with keys:
6 | // ROPSTEN_PRIVATE_KEY="123abc"
7 | // MAINNET_PRIVATE_KEY="123abc"
8 |
9 | require('dotenv').config();
10 | const Web3 = require("web3");
11 | const web3 = new Web3();
12 | const WalletProvider = require("truffle-wallet-provider");
13 | const Wallet = require('ethereumjs-wallet');
14 |
15 | var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
16 | var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
17 | var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
18 |
19 | var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
20 | var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
21 | var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
22 |
23 | module.exports = {
24 | networks: {
25 | dev: { // Whatever network our local node connects to
26 | network_id: "*", // Match any network id
27 | host: "localhost",
28 | port: 8545,
29 | },
30 | mainnet: { // Provided by Infura, load keys in .env file
31 | network_id: "1",
32 | provider: mainNetProvider,
33 | gas: 4600000,
34 | gasPrice: web3.utils.toWei("20", "gwei"),
35 | },
36 | ropsten: { // Provided by Infura, load keys in .env file
37 | network_id: "3",
38 | provider: ropstenProvider,
39 | gas: 4600000,
40 | gasPrice: web3.utils.toWei("20", "gwei"),
41 | },
42 | kovan: {
43 | network_id: 42,
44 | host: "localhost", // parity --chain=kovan
45 | port: 8545,
46 | gas: 5000000
47 | },
48 | ganache: { // Ganache local test RPC blockchain
49 | network_id: "5777",
50 | host: "localhost",
51 | port: 7545,
52 | gas: 6721975,
53 | }
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/code/truffle/METoken_Faucet/truffle-config.js:
--------------------------------------------------------------------------------
1 | // Install dependencies:
2 | // npm init
3 | // npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
4 |
5 | // Create .env in project root, with keys:
6 | // ROPSTEN_PRIVATE_KEY="123abc"
7 | // MAINNET_PRIVATE_KEY="123abc"
8 |
9 | require('dotenv').config();
10 | const Web3 = require("web3");
11 | const web3 = new Web3();
12 | const WalletProvider = require("truffle-wallet-provider");
13 | const Wallet = require('ethereumjs-wallet');
14 |
15 | var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
16 | var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
17 | var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
18 |
19 | var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
20 | var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
21 | var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
22 |
23 | module.exports = {
24 | networks: {
25 | dev: { // Whatever network our local node connects to
26 | network_id: "*", // Match any network id
27 | host: "localhost",
28 | port: 8545,
29 | },
30 | mainnet: { // Provided by Infura, load keys in .env file
31 | network_id: "1",
32 | provider: mainNetProvider,
33 | gas: 4600000,
34 | gasPrice: web3.utils.toWei("20", "gwei"),
35 | },
36 | ropsten: { // Provided by Infura, load keys in .env file
37 | network_id: "3",
38 | provider: ropstenProvider,
39 | gas: 4600000,
40 | gasPrice: web3.utils.toWei("20", "gwei"),
41 | },
42 | kovan: {
43 | network_id: 42,
44 | host: "localhost", // parity --chain=kovan
45 | port: 8545,
46 | gas: 5000000
47 | },
48 | ganache: { // Ganache local test RPC blockchain
49 | network_id: "5777",
50 | host: "localhost",
51 | port: 7545,
52 | gas: 6721975,
53 | }
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/code/truffle/METoken_METFaucet/truffle-config.js:
--------------------------------------------------------------------------------
1 | // Install dependencies:
2 | // npm init
3 | // npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
4 |
5 | // Create .env in project root, with keys:
6 | // ROPSTEN_PRIVATE_KEY="123abc"
7 | // MAINNET_PRIVATE_KEY="123abc"
8 |
9 | require('dotenv').config();
10 | const Web3 = require("web3");
11 | const web3 = new Web3();
12 | const WalletProvider = require("truffle-wallet-provider");
13 | const Wallet = require('ethereumjs-wallet');
14 |
15 | var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
16 | var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
17 | var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
18 |
19 | var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
20 | var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
21 | var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
22 |
23 | module.exports = {
24 | networks: {
25 | dev: { // Whatever network our local node connects to
26 | network_id: "*", // Match any network id
27 | host: "localhost",
28 | port: 8545,
29 | },
30 | mainnet: { // Provided by Infura, load keys in .env file
31 | network_id: "1",
32 | provider: mainNetProvider,
33 | gas: 4600000,
34 | gasPrice: web3.utils.toWei("20", "gwei"),
35 | },
36 | ropsten: { // Provided by Infura, load keys in .env file
37 | network_id: "3",
38 | provider: ropstenProvider,
39 | gas: 4600000,
40 | gasPrice: web3.utils.toWei("20", "gwei"),
41 | },
42 | kovan: {
43 | network_id: 42,
44 | host: "localhost", // parity --chain=kovan
45 | port: 8545,
46 | gas: 5000000
47 | },
48 | ganache: { // Ganache local test RPC blockchain
49 | network_id: "5777",
50 | host: "localhost",
51 | port: 7545,
52 | gas: 6721975,
53 | }
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/DeedRepository.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.17;
2 | import "./ERC721/ERC721Token.sol";
3 |
4 | /**
5 | * @title Repository of ERC721 Deeds
6 | * This contract contains the list of deeds registered by users.
7 | * This is a demo to show how tokens (deeds) can be minted and added
8 | * to the repository.
9 | */
10 | contract DeedRepository is ERC721Token {
11 |
12 |
13 | /**
14 | * @dev Created a DeedRepository with a name and symbol
15 | * @param _name string represents the name of the repository
16 | * @param _symbol string represents the symbol of the repository
17 | */
18 | function DeedRepository(string _name, string _symbol)
19 | public ERC721Token(_name, _symbol) {}
20 |
21 | /**
22 | * @dev Public function to register a new deed
23 | * @dev Call the ERC721Token minter
24 | * @param _tokenId uint256 represents a specific deed
25 | * @param _uri string containing metadata/uri
26 | */
27 | function registerDeed(uint256 _tokenId, string _uri) public {
28 | _mint(msg.sender, _tokenId);
29 | addDeedMetadata(_tokenId, _uri);
30 | emit DeedRegistered(msg.sender, _tokenId);
31 | }
32 |
33 | /**
34 | * @dev Public function to add metadata to a deed
35 | * @param _tokenId represents a specific deed
36 | * @param _uri text which describes the characteristics of a given deed
37 | * @return whether the deed metadata was added to the repository
38 | */
39 | function addDeedMetadata(uint256 _tokenId, string _uri) public returns(bool){
40 | _setTokenURI(_tokenId, _uri);
41 | return true;
42 | }
43 |
44 | /**
45 | * @dev Event is triggered if deed/token is registered
46 | * @param _by address of the registrar
47 | * @param _tokenId uint256 represents a specific deed
48 | */
49 | event DeedRegistered(address _by, uint256 _tokenId);
50 | }
51 |
--------------------------------------------------------------------------------
/code/aws/truffle-config.js:
--------------------------------------------------------------------------------
1 | // Install dependencies:
2 | // npm init
3 | // npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
4 |
5 | // Create .env in project root, with keys:
6 | // ROPSTEN_PRIVATE_KEY="123abc"
7 | // MAINNET_PRIVATE_KEY="123abc"
8 |
9 | require('dotenv').config();
10 | const Web3 = require("web3");
11 | const web3 = new Web3();
12 | const WalletProvider = require("truffle-wallet-provider");
13 | const Wallet = require('ethereumjs-wallet');
14 |
15 | var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
16 | var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
17 | var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
18 |
19 | var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
20 | var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
21 | var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
22 |
23 | module.exports = {
24 | networks: {
25 | dev: { // Whatever network our local node connects to
26 | network_id: "*", // Match any network id
27 | host: "localhost",
28 | port: 8545
29 | },
30 | mainnet: { // Provided by Infura, load keys in .env file
31 | network_id: "1",
32 | provider: mainNetProvider,
33 | gas: 4600000,
34 | gasPrice: web3.utils.toWei("20", "gwei")
35 | },
36 | ropsten: { // Provided by Infura, load keys in .env file
37 | network_id: "3",
38 | provider: ropstenProvider,
39 | gas: 4600000,
40 | gasPrice: web3.utils.toWei("20", "gwei")
41 | },
42 | kovan: {
43 | network_id: 42,
44 | host: "localhost", // parity --chain=kovan
45 | port: 8545,
46 | gas: 5000000
47 | },
48 | ganache: { // Ganache local test RPC blockchain
49 | network_id: "5777",
50 | host: "localhost",
51 | port: 7545,
52 | gas: 6721975
53 | },
54 | aws: { // Private network on AWS
55 | network_id: "15",
56 | host: "public-ip-address",
57 | port: 8545,
58 | gas: 6721975
59 | }
60 | }
61 | };
--------------------------------------------------------------------------------
/code/truffle/console/nonce.js:
--------------------------------------------------------------------------------
1 | console.log("getTransactionCount (confirmed)");
2 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f"));
3 |
4 | console.log("getTransactionCount (pending)");
5 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f", "pending"));
6 |
7 | console.log("sendTransaction");
8 | console.log(web3.eth.sendTransaction({from: web3.eth.accounts[0], to: "0xB0920c523d582040f2BCB1bD7FB1c7C1ECEbdB34", value: web3.utils.toWei(0.01, "ether")}));
9 |
10 | console.log("getTransactionCount (confirmed)");
11 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f"));
12 |
13 | console.log("getTransactionCount (pending)");
14 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f", "pending"));
15 |
16 | console.log("sendTransaction");
17 | console.log(web3.eth.sendTransaction({from: web3.eth.accounts[0], to: "0xB0920c523d582040f2BCB1bD7FB1c7C1ECEbdB34", value: web3.utils.toWei(0.01, "ether")}));
18 |
19 | console.log("getTransactionCount (confirmed)");
20 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f"));
21 |
22 | console.log("getTransactionCount (pending)");
23 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f", "pending"));
24 |
25 | console.log("sendTransaction");
26 | console.log(web3.eth.sendTransaction({from: web3.eth.accounts[0], to: "0xB0920c523d582040f2BCB1bD7FB1c7C1ECEbdB34", value: web3.utils.toWei(0.01, "ether")}));
27 |
28 | console.log("getTransactionCount (confirmed)");
29 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f"));
30 |
31 | console.log("getTransactionCount (pending)");
32 | console.log(web3.eth.getTransactionCount("0x9e713963a92c02317a681b9bb3065a8249de124f", "pending"));
33 |
34 | console.log("sendTransaction");
35 | console.log(web3.eth.sendTransaction({from: web3.eth.accounts[0], to: "0xB0920c523d582040f2BCB1bD7FB1c7C1ECEbdB34", value: web3.utils.toWei(0.01, "ether")}));
36 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/src/models/ChatRoom.js:
--------------------------------------------------------------------------------
1 | import Config from '../config'
2 |
3 | export class ChatRoom {
4 | web3 = null
5 | keyID = ''
6 | privateKey = ''
7 | publicKey = ''
8 | conn = null
9 | room = ''
10 | identity = ''
11 |
12 | constructor(){
13 | this.privateKey = Config.WHISPER_SHARED_KEY
14 | }
15 |
16 | async setWeb3(web3){
17 | this.web3 = web3
18 | this.keyID = await this.web3.shh.addPrivateKey(this.privateKey)
19 | this.publicKey = await this.web3.shh.getPublicKey(this.keyID)
20 | }
21 |
22 | getWeb3(){
23 | return this.web3
24 | }
25 |
26 | async getWeb3ConnStatusAction() {
27 | return await this.web3.shh.net.isListening()
28 | }
29 |
30 | async subscribeToTopic(topic, fn) {
31 | this.conn = this.web3.shh.subscribe("messages", {
32 | privateKeyID: this.keyID,
33 | //topics: [this.web3.utils.stringToHex(topic)]
34 | topics: [topic]
35 | }).on('data', fn)
36 | }
37 |
38 | async sendJoinEvent(identity, room, data) {
39 | const messageRaw = {
40 | identity: identity,
41 | type: "join",
42 | data: data
43 | }
44 | return await this.sendRawWhisperMessage(messageRaw, room )
45 | }
46 |
47 | async sendMessageEvent(identity, room, data) {
48 | const messageRaw = {
49 | identity: identity,
50 | type: "msg",
51 | data: data
52 | }
53 | return await this.sendRawWhisperMessage(messageRaw, room )
54 | }
55 |
56 | async sendRawWhisperMessage(msg, topic){
57 | return await this.web3.shh.post({
58 | pubKey: this.publicKey, // encrypts using the sym key ID
59 | ttl: 10,
60 | //topic: this.web3.utils.stringToHex(topic),
61 | topic: topic,
62 | payload: this.web3.utils.stringToHex(JSON.stringify(msg)),
63 | powTime: 60,
64 | powTarget: 0.2
65 | })
66 | }
67 |
68 | }
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "1.0.0",
4 | "description": "Auction Dapp powered by Ethereum",
5 | "author": "iNDicat0r ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "build": "node build/build.js"
11 | },
12 | "dependencies": {
13 | "ethereumjs-util": "^5.1.5",
14 | "moment": "^2.22.0",
15 | "vue": "^2.5.2",
16 | "vue-resource": "^1.5.0",
17 | "vue-router": "^3.0.1",
18 | "vuetify": "^0.17.6",
19 | "web3": "^1.0.0-beta.31",
20 | "web3-shh": "^1.0.0-beta.31"
21 | },
22 | "devDependencies": {
23 | "autoprefixer": "^7.1.2",
24 | "babel-core": "^6.22.1",
25 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
26 | "babel-loader": "^7.1.1",
27 | "babel-plugin-syntax-jsx": "^6.18.0",
28 | "babel-plugin-transform-runtime": "^6.22.0",
29 | "babel-plugin-transform-vue-jsx": "^3.5.0",
30 | "babel-preset-env": "^1.3.2",
31 | "babel-preset-stage-2": "^6.22.0",
32 | "chalk": "^2.0.1",
33 | "copy-webpack-plugin": "^4.0.1",
34 | "css-loader": "^0.28.0",
35 | "extract-text-webpack-plugin": "^3.0.0",
36 | "file-loader": "^1.1.4",
37 | "friendly-errors-webpack-plugin": "^1.6.1",
38 | "html-webpack-plugin": "^2.30.1",
39 | "node-notifier": "^5.1.2",
40 | "optimize-css-assets-webpack-plugin": "^3.2.0",
41 | "ora": "^1.2.0",
42 | "portfinder": "^1.0.13",
43 | "postcss-import": "^11.0.0",
44 | "postcss-loader": "^2.0.8",
45 | "postcss-url": "^7.2.1",
46 | "rimraf": "^2.6.0",
47 | "semver": "^5.3.0",
48 | "shelljs": "^0.7.6",
49 | "uglifyjs-webpack-plugin": "^1.1.1",
50 | "url-loader": "^0.5.8",
51 | "vue-loader": "^13.3.0",
52 | "vue-style-loader": "^3.0.1",
53 | "vue-template-compiler": "^2.5.2",
54 | "webpack": "^3.6.0",
55 | "webpack-bundle-analyzer": "^2.9.0",
56 | "webpack-dev-server": "^2.9.1",
57 | "webpack-merge": "^4.1.0"
58 | },
59 | "engines": {
60 | "node": ">= 6.0.0",
61 | "npm": ">= 3.0.0"
62 | },
63 | "browserslist": [
64 | "> 1%",
65 | "last 2 versions",
66 | "not ie <= 8"
67 | ]
68 | }
69 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.2.8
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 |
24 | /**
25 | * Source Maps
26 | */
27 |
28 | // https://webpack.js.org/configuration/devtool/#development
29 | devtool: 'cheap-module-eval-source-map',
30 |
31 | // If you have problems debugging vue-files in devtools,
32 | // set this to false - it *may* help
33 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
34 | cacheBusting: true,
35 |
36 | cssSourceMap: true,
37 | },
38 |
39 | build: {
40 | // Template for index.html
41 | index: path.resolve(__dirname, '../dist/index.html'),
42 |
43 | // Paths
44 | assetsRoot: path.resolve(__dirname, '../dist'),
45 | assetsSubDirectory: 'static',
46 | assetsPublicPath: '/',
47 |
48 | /**
49 | * Source Maps
50 | */
51 |
52 | productionSourceMap: true,
53 | // https://webpack.js.org/configuration/devtool/#production
54 | devtool: '#source-map',
55 |
56 | // Gzip off by default as many popular static hosts such as
57 | // Surge or Netlify already gzip all static assets for you.
58 | // Before setting to `true`, make sure to:
59 | // npm install --save-dev compression-webpack-plugin
60 | productionGzip: false,
61 | productionGzipExtensions: ['js', 'css'],
62 |
63 | // Run the build command with an extra argument to
64 | // View the bundle analyzer report after build finishes:
65 | // `npm run build --report`
66 | // Set to `true` or `false` to always turn it on or off
67 | bundleAnalyzerReport: process.env.npm_config_report
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 |
12 |
13 | module.exports = {
14 | context: path.resolve(__dirname, '../'),
15 | entry: {
16 | app: './src/main.js'
17 | },
18 | output: {
19 | path: config.build.assetsRoot,
20 | filename: '[name].js',
21 | publicPath: process.env.NODE_ENV === 'production'
22 | ? config.build.assetsPublicPath
23 | : config.dev.assetsPublicPath
24 | },
25 | resolve: {
26 | extensions: ['.js', '.vue', '.json'],
27 | alias: {
28 | 'vue$': 'vue/dist/vue.esm.js',
29 | '@': resolve('src'),
30 | }
31 | },
32 | module: {
33 | rules: [
34 | {
35 | test: /\.vue$/,
36 | loader: 'vue-loader',
37 | options: vueLoaderConfig
38 | },
39 | {
40 | test: /\.js$/,
41 | loader: 'babel-loader',
42 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
43 | },
44 | {
45 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
46 | loader: 'url-loader',
47 | options: {
48 | limit: 10000,
49 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
50 | }
51 | },
52 | {
53 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
54 | loader: 'url-loader',
55 | options: {
56 | limit: 10000,
57 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
58 | }
59 | },
60 | {
61 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
62 | loader: 'url-loader',
63 | options: {
64 | limit: 10000,
65 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
66 | }
67 | }
68 | ]
69 | },
70 | node: {
71 | // prevent webpack from injecting useless setImmediate polyfill because Vue
72 | // source contains it (although only uses it if it's native).
73 | setImmediate: false,
74 | // prevent webpack from injecting mocks to Node native modules
75 | // that does not make sense for the client
76 | dgram: 'empty',
77 | fs: 'empty',
78 | net: 'empty',
79 | tls: 'empty',
80 | child_process: 'empty'
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/test/2_deedrepository.js:
--------------------------------------------------------------------------------
1 | var DeedRepository = artifacts.require("./DeedRepository.sol");
2 | const fs = require('fs');
3 |
4 | contract('DeedRepository', async (accounts) => {
5 |
6 | let instance;
7 | let auctionContractAddress = "";
8 |
9 | beforeEach('setup contract for each test', async function () {
10 | instance = await DeedRepository.deployed();
11 | auctionContractAddress = fs.readFileSync("./test/output.address").toString()
12 | })
13 |
14 | it("It should create an deed repository with UANFT as symbol", async () => {
15 | let symbol = await instance.symbol();
16 | assert.equal(symbol.valueOf(), 'UANFT' , `Deedrepository symbol should be UANFT`);
17 | });
18 |
19 | it("It should register a deed with id: 123456789", async () => {
20 | await instance.registerDeed(accounts[0], 123456789);
21 | let ownerOfDeed = await instance.exists(123456789);
22 | assert.equal(ownerOfDeed.valueOf(), true , `Result should be true`);
23 | });
24 |
25 | it(`It should check owner of 123456789 who is ${accounts[0]}`, async () => {
26 | let ownerOfDeed = await instance.ownerOf(123456789);
27 | assert.equal(ownerOfDeed.valueOf(), accounts[0] , `Owner should be ${accounts[0]}`);
28 | });
29 |
30 | it(`It should check balance of ${accounts[0]}`, async () => {
31 | let balance = await instance.balanceOf(accounts[0]);
32 | assert.equal(balance.valueOf(), 1 , `balance ${balance} should be 1`);
33 | });
34 |
35 | it(`It should check total supply of the repository`, async () => {
36 | let supply = await instance.totalSupply();
37 | assert.equal(supply.valueOf(), 1 , `total supply: ${supply} should be 1`);
38 | });
39 |
40 | it(`It should approve transfer the ownership of 123456789 to the auctionRepository address`, async () => {
41 | await instance.approve(auctionContractAddress, 123456789);
42 | // console.log('this auction address:', auctionAddress, ' deedrepo instance addr', instance.address);
43 | let address = await instance.getApproved(123456789);
44 | assert.equal(address.valueOf(), auctionContractAddress, `${address} should be equal to ${auctionContractAddress}`);
45 | });
46 |
47 | it("It should transfer ownership of deed 123456789 to this contract", async () => {
48 | await instance.transferFrom( accounts[0] ,auctionContractAddress, 123456789, { from: accounts[0]});
49 | let newOwnerAddress = await instance.ownerOf(123456789);
50 | //let success = await instance.isApprovedOrOwner(auctionAddress, 123456789)
51 | assert.equal(newOwnerAddress.valueOf(), auctionContractAddress, `${newOwnerAddress} should be ${auctionContractAddress}`);
52 | });
53 |
54 |
55 | });
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/src/models/DeedRepository.js:
--------------------------------------------------------------------------------
1 | import Config from '../config'
2 |
3 | export class DeedRepository {
4 |
5 | web3 = null
6 | account = ''
7 | contractInstance = null
8 | gas = 4476768
9 |
10 | constructor(){
11 | this.gas = Config.GAS_AMOUNT
12 | }
13 | setWeb3(web3) {
14 | this.web3 = web3
15 | this.contractInstance = this.web3.eth.contract(Config.DEEDREPOSITORY_ABI).at(Config.DEEDREPOSITORY_ADDRESS)
16 | }
17 |
18 | getWeb3() {
19 | return this.web3
20 | }
21 |
22 | setAccount(account){
23 | this.account = account
24 | }
25 |
26 | getCurrentBlock() {
27 | return new Promise((resolve, reject ) => {
28 | this.web3.eth.getBlockNumber((err, blocknumber) => {
29 | if(!err) resolve(blocknumber)
30 | reject(err)
31 | })
32 | })
33 | }
34 |
35 | // getAccounts() {
36 | // return new Promise((resolve, reject ) => {
37 | // this.web3.eth.getAccounts((err, accounts) => {
38 | // if(!err) resolve(accounts)
39 | // reject(err)
40 | // })
41 | // })
42 | // }
43 |
44 | async watchIfCreated(cb) {
45 | const currentBlock = await this.getCurrentBlock()
46 | const eventWatcher = this.contractInstance.DeedRegistered({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
47 | eventWatcher.watch(cb)
48 | }
49 |
50 | async watchIfDeedTransfered(cb) {
51 | const currentBlock = await this.getCurrentBlock()
52 | const eventWatcher = this.contractInstance.Transfer({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
53 | eventWatcher.watch(cb)
54 | }
55 |
56 | exists(deedId) {
57 | return new Promise(async (resolve, reject) => {
58 | this.contractInstance.exists(deedId, {from: this.account, gas: this.gas }, (err, transaction) => {
59 | if(!err) resolve(transaction)
60 | reject(err)
61 | })
62 | })
63 | }
64 |
65 | transferTo(to, deedId) {
66 | return new Promise(async (resolve, reject) => {
67 | this.contractInstance.transferFrom(this.account, to, deedId, {from: this.account, gas: this.gas }, (err, transaction) => {
68 | if(!err) resolve(transaction)
69 | reject(err)
70 | })
71 | })
72 |
73 | }
74 |
75 | create(deedId, deedURI) {
76 | console.log('contractinsatnce', this.contractInstance )
77 | return new Promise(async (resolve, reject) => {
78 | this.contractInstance.registerDeed(deedId, deedURI, {from: this.account, gas: this.gas }, (err, transaction) => {
79 | if(!err)
80 | resolve(transaction)
81 | else
82 | reject(err)
83 | })
84 | })
85 | }
86 | }
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/code/auction_dapp/README.md:
--------------------------------------------------------------------------------
1 | # Decentralized Auction Application on Ethereum
2 |
3 | This project aims to implement basic functionalities of an auction platform using Ethereum.
4 |
5 | ## Requirements
6 |
7 | 
8 |
9 | The application should be decentralized and utilize Ethereum's stack:
10 |
11 | 1. Smart contracts for business logic(auctions, bids, refund and transfer of ownership)
12 | 2. Swarm for data storage(image and metadata)
13 | 3. Whisper for a peer-to-peer messaging(chatrooms)
14 |
15 | ### Deed Repository
16 | Manage non-fungible tokens by implementing an asset/token/deed repository which holds unique asset/token/deed.
17 |
18 | #### ERC: Non-fungible Token Standard #721 (NFT)
19 | See following link:
20 | https://github.com/ethereum/eips/issues/721
21 |
22 | ### Auction Repository
23 |
24 | Auction repository MUST act as an auction house which does the following:
25 |
26 | - Holds asset/token/deed that is to be auctioned(ERC721 Ownership by smart contract)
27 | - Allows users bid on auctions
28 | - Keeps track of auctions/bids/ownership
29 | - Transfers ownership of asset/token/deed to winder
30 | - Transfers Funds to auction creator if auction is ended and there is at least one winner
31 | - Cancels auction and deal with refunds
32 | - UI to interact with the above functionality
33 |
34 | ### Front-end: Vuejs2.x + Vuetify
35 |
36 | The front-end is developed using a reactive UI framework with integration of Vuetify, a Google's Material Design implementation.
37 |
38 | ## Implementation/Data flow
39 |
40 | #### 1. Register an ERC721 Non-Fungible Token with the AuctionDaap Deed Repository
41 |
42 | The idea of a Deed Repository is used across this project to hold any NFT with metadata attached to. A token/deed is registered by giving a unique ID and attaching metadata(TokenURI). The metadata is what makes each token important or valuable.
43 |
44 | #### 2. Transfer Ownership of the NFT to AuctionRepository(Auction house)
45 |
46 | The Auction house needs to verify that a NFT is owned by the auction creator, therefore before the auction is created, the owner should transfer the ownership of the NFT to the AuctionRepository smart contract address.
47 |
48 | #### 3. Create Auction for NFT
49 |
50 | Creating the auction is a simple process of entering auction details such as name, starting price, expiry date etc. The important part is to have the reference between the deed and the auction.
51 |
52 | #### 4. Bid on Auction
53 |
54 | Anyone can bid on an auction except the owner of the auction. Biding means that previous bidders are refunded and new bid is placed. Bid requirements are as follow:
55 | 1. Auction not expired
56 | 2. Bidder is not auction owner
57 | 3. Bid amount is greator than current bid or starting price(if no bid)
58 |
59 | #### 5. Refunds
60 |
61 | If an auction is canceled, the Auction Repository MUST return the ownership of the asset/token/deed back to the auction creator and refund bidders if any.
62 |
63 | #### 6. Bidder Win Auction
64 |
65 | If there is an auction winner, the asset/token/deed is transferred to the bidder and the bid amount is sent to the auction creator.
66 |
67 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/test/1_auctionrepository.js:
--------------------------------------------------------------------------------
1 | var AuctionRepository = artifacts.require("./AuctionRepository.sol");
2 | //var DeedRepository = artifacts.require("./DeedRepository.sol");
3 | const fs = require('fs');
4 |
5 | contract('AuctionRepository', async (accounts) => {
6 |
7 | it("It should check if the auction repository is initialized", async () => {
8 | let instance = await AuctionRepository.deployed();
9 | fs.writeFileSync('./test/output.address', instance.address);
10 | let auctionLength = await instance.getAuctionsCount();
11 | assert.equal(auctionLength.valueOf(), 0, `${auctionLength} auctions instead of 0`);
12 | });
13 |
14 | // it("It should approve transfer of ownership of the 123456789 token", async () => {
15 | // //let instance = await DeedRepository.deployed();
16 | // //let totalSupply = await instance.totalSupply();
17 |
18 | // let auctionInstance = await AuctionRepository.deployed();
19 | // let auctionAddress = auctionInstance.address;
20 | // await instance.approve(auctionAddress, 123456789);
21 |
22 | // // console.log('this auction address:', auctionAddress, ' deedrepo instance addr', instance.address);
23 | // let address = await instance.getApproved(123456789);
24 | // assert.equal(address.valueOf(), auctionAddress, `${address} should be equal to ${auctionAddress}`);
25 | // });
26 |
27 | // it("It should transfer ownership of deed to this contract", async () => {
28 | // let instance = await DeedRepository.deployed();
29 | // let auctionInstance = await AuctionRepository.deployed();
30 | // let auctionAddress = auctionInstance.address;
31 | // await instance.transferFrom( accounts[0] ,auctionAddress, 123456789, { from: accounts[0]});
32 | // let newOwnerAddress = await instance.ownerOf(123456789);
33 | // //let success = await instance.isApprovedOrOwner(auctionAddress, 123456789)
34 | // assert.equal(newOwnerAddress.valueOf(), auctionAddress, `${newOwnerAddress} should be ${auctionAddress}`);
35 | // });
36 |
37 | // it(`It should create an auction under ${accounts[0]} account`, async () => {
38 | // let instance = await AuctionRepository.deployed();
39 | // await instance.createAuction(accounts[0], 123456789, "MYNFT", "meta://", 10, 1533772800, accounts[0] );
40 | // let auctionCount = await instance.getAuctionsCountOfOwner(accounts[0]);
41 | // assert.equal(auctionCount.valueOf(), 1, `auctions of ${accounts[0]} should be 1`);
42 | // });
43 |
44 | // it(`It should bid on the last auction`, async () => {
45 | // let instance = await AuctionRepository.deployed();
46 | // await instance.bidOnAuction(0, 1000);
47 | // let bidsCount = await instance.getBidsCount(0);
48 | // assert.equal(bidsCount.valueOf(), 1, `bids should be 1`);
49 | // });
50 |
51 | // it(`It should bid on the last auction`, async () => {
52 | // let instance = await AuctionRepository.deployed();
53 | // await instance.bidOnAuction(0, 10000 );
54 | // let bidsCount = await instance.getBidsCount(0);
55 | // assert.equal(bidsCount.valueOf(), 2, `bids should be 1`);
56 | // });
57 |
58 |
59 | });
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './App'
3 | import Config from './config'
4 | import router from './router'
5 | import Vuetify from 'vuetify'
6 | import VueResource from 'vue-resource'
7 | import { ChatRoom } from './models/ChatRoom'
8 | import { DeedRepository } from './models/DeedRepository'
9 | import { AuctionRepository } from './models/AuctionRepository'
10 |
11 | // rename to avoid conflict between metamask
12 | // will be used for whisper v5/6
13 | var Web3_1 = require('web3')
14 |
15 | Vue.use(VueResource)
16 | Vue.use(Vuetify)
17 | Vue.config.productionTip = false
18 |
19 | // state management
20 | var store = {
21 | debug: true,
22 | state: {
23 | // metamask state variable
24 | metamask: {
25 | web3DefaultAccount: '',
26 | metamaskInstalled: false,
27 | networkId: '',
28 | },
29 |
30 | // local web3 instance(not metamask)
31 | web3 : null,
32 |
33 | },
34 | networkReady() {
35 | return this.getNetworkId() != '' && this.getMetamaskInstalled() && this.getWeb3DefaultAccount() != ''
36 | },
37 | setNetworkId(networkId) {
38 | this.state.metamask.networkId = networkId
39 | },
40 | getNetworkId() {
41 | return this.state.metamask.networkId
42 | },
43 |
44 | setWeb3DefaultAccount(account) {
45 | this.state.metamask.web3DefaultAccount = account
46 | },
47 | getWeb3DefaultAccount() {
48 | return this.state.metamask.web3DefaultAccount
49 | },
50 |
51 | setMetamaskInstalled(){
52 | this.state.metamask.metamaskInstalled = true
53 | },
54 | getMetamaskInstalled(){
55 | return this.state.metamask.metamaskInstalled
56 | },
57 |
58 | getRandomInt(min, max) {
59 | return Math.floor(Math.random() * (max - min + 1)) + min
60 | }
61 | }
62 |
63 |
64 | Vue.mixin({
65 | created: function () {
66 | // Inject the models to components
67 | this.$chatroomInstance = new ChatRoom()
68 | this.$deedRepoInstance = new DeedRepository()
69 | this.$auctionRepoInstance = new AuctionRepository()
70 |
71 | this.$chatroomInstance.setWeb3(new Web3_1(Config.SHH_ENDPOINT))
72 |
73 | // one instance of web3 available to all components
74 | if (typeof web3 !== 'undefined') {
75 | web3 = new Web3(web3.currentProvider)
76 | this.$auctionRepoInstance.setWeb3(web3)
77 | this.$deedRepoInstance.setWeb3(web3)
78 |
79 | store.setMetamaskInstalled()
80 | web3.version.getNetwork((err, netId) => {
81 | store.setNetworkId(netId)
82 | })
83 | // pull accounts every 2 seconds
84 | setInterval(() => {
85 | web3.eth.getAccounts((err, data) => {
86 | if(data.length > 0) store.setWeb3DefaultAccount(data[0])
87 | })
88 | }, 2000)
89 | }
90 | // inject config to components
91 | this.$config = Config
92 | }
93 | })
94 |
95 |
96 | new Vue({
97 | el: '#app',
98 | data: {
99 | globalState: store,
100 | },
101 | router,
102 | template: ' ',
103 | components: { App },
104 | mounted() {
105 |
106 | }
107 | })
108 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/code/web3js/web3js_demo/web3-contract-basic-interaction-async-await.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * @author Francisco Javier Rojas García
5 | */
6 |
7 | console.log('Mastering Ethereum - web3.js basic interactions using async/await')
8 | console.log('Author: Francisco Javier Rojas García - fjrojasgarcia@gmail.com')
9 |
10 | var Web3 = require('web3');
11 | var fs = require('fs')
12 |
13 | // Prepare your Infura host url
14 | var infura_host = "https://kovan.infura.io"
15 |
16 | // Instantiate web3 provider
17 | var web3 = new Web3(infura_host);
18 |
19 | // Let's do some basic interactions at web3 level
20 | async function basicInterations() {
21 | // Let's see the Protocol Version
22 | var protocolVersion = await web3.eth.getProtocolVersion();
23 | console.log(`Protocol Version: ${protocolVersion}`);
24 |
25 | // Now I'm curious about the current gas price
26 | var gasPrice = await web3.eth.getGasPrice();
27 | console.log(`Gas Price: ${gasPrice}`);
28 |
29 | // And, Whats the last mined block in my chain?
30 | var blockNumber = await web3.eth.getBlockNumber();
31 | console.log(`Block Number: ${blockNumber}`);
32 |
33 | // Now let's dive into some basics actions with a contract
34 | // We will use the contract at;
35 | // https://kovan.etherscan.io/address/0xd0a1e359811322d97991e03f863a0c30c2cf029c#code
36 |
37 | // First things first, let's initialize our contract address
38 | var our_contract_address = "0xd0A1E359811322d97991E03f863a0C30C2cF029C";
39 |
40 | // Let's see its balance
41 | var balance = await web3.eth.getBalance(our_contract_address);
42 | console.log(`Balance of ${our_contract_address}: ${balance}`);
43 |
44 | // Now let's see its byte code
45 | var code = await web3.eth.getCode(our_contract_address);
46 | console.log("Contract code: ----------------------------------------------\n");
47 | console.log(code);
48 | console.log("-------------------------------------------------------------\n");
49 |
50 | // Let's initialize our contract url in Etherescan for Kovan chain
51 | var etherescan_url = `http://kovan.etherscan.io/api?module=contract&action=getabi&address=${our_contract_address}`
52 | console.log(etherescan_url);
53 |
54 | var client = require('node-rest-client-promise').Client();
55 |
56 | var etherescan_response = await client.getPromise(etherescan_url)
57 |
58 | // Leave this two lines for future object analysis
59 | //const util = require('util')
60 | //console.log(util.inspect(etherescan_response, false, null))
61 |
62 | // We get here our contract ABI
63 | our_contract_abi = JSON.parse(etherescan_response.data.result);
64 |
65 | // Let's instantiate our contract object
66 | var our_contract = await new web3.eth.Contract(our_contract_abi, our_contract_address);
67 |
68 | // Let's see our contract address
69 | console.log(`Our Contract address: ${our_contract._address}`);
70 |
71 | // or in this other way
72 | console.log(`Our Contract address in other way: ${our_contract.options.address}`);
73 |
74 | // Now our contract abi
75 | console.log("Our contract abi: " + JSON.stringify(our_contract.options.jsonInterface));
76 |
77 | // This is turning more interesting, let's see what's going with our contract methods
78 | // Now let's see our contract total supply
79 | var totalSupply = await our_contract.methods.totalSupply().call();
80 | console.log(`Total Supply of Our Contract address ${our_contract._address}: ${totalSupply}`);
81 |
82 | // Now let's see our contract public variable name
83 | var name = await our_contract.methods.name().call();
84 | console.log(`Public variable name of our Contract address ${our_contract._address}: ${name}`);
85 |
86 | // Now let's see our contract public variable symbol
87 | var symbol = await our_contract.methods.symbol().call();
88 | console.log(`Public variable symbol of our Contract address ${our_contract._address}: ${symbol}`);
89 | }
90 |
91 | // Let's interact with a node
92 | basicInterations();
93 |
--------------------------------------------------------------------------------
/appdx-shortlinks_cn.asciidoc:
--------------------------------------------------------------------------------
1 | [appendix]
2 | [[short_links]]
3 | == 短链接参考
4 |
5 | 在本书中,我们都使用了短链接。这些短链接在页面上占用的空间更少,并使印刷版的读者更容易将其转录到浏览器中。但是,短链接可能会断开,提供这些服务的公司可能不复存在或阻塞某些链接。下面将完整的链接按在文本中出现的顺序显示。
6 |
7 |
8 | === 智能合约安全性
9 |
10 | [options="header"]
11 | |===
12 | |短链接 | 完整链接
13 | | 2Ogvnng | https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#address-related
14 | | 2EVo70v | https://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern
15 | | 2EQaLCI | http://hackingdistributed.com/2016/06/18/analysis-of-the-dao-exploit/
16 | | 2MOfBPv | https://consensys.github.io/smart-contract-best-practices/known_attacks/#integer-overflow-and-underflow
17 | | 2xvbx1M | https://randomoracle.wordpress.com/2018/04/27/ethereum-solidity-and-integer-overflows-programming-blockchains-like-1970/
18 | | 2CUf7WG | https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
19 | | 2RovrDf | https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html
20 | | 2AAElb8 | https://ethereum.stackexchange.com/questions/3667/difference-between-call-callcode-and-delegatecall
21 | | 2Oi7UlH | https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries
22 | | 2RmueMP | https://solidity.readthedocs.io/en/latest/abi-spec.html#function-selector
23 | | 2Dg7GtW | https://medium.com/chain-cloud-company-blog/parity-multisig-hack-again-b46771eaa838
24 | | 2CUh2KS | https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract
25 | | 2Q589lx | https://blog.positive.com/predicting-random-numbers-in-ethereum-smart-contracts-e5358c6b8620
26 | | 2JtdqRi | https://etherscan.io/address/0x95d34980095380851902ccd9a1fb4c813c2cb639#code
27 | | 2Q58VyX | https://www.reddit.com/r/ethdev/comments/7x5rwr/tricked_by_a_honeypot_contract_or_beaten_by/
28 | | 2yKme14 | https://vessenes.com/the-erc20-short-address-attack-explained/
29 | | 2yFOGRQ | https://medium.com/huzzle/ico-smart-contract-vulnerability-short-address-attack-31ac9177eb6b
30 | | 2CQjBhc | https://www.reddit.com/r/ethereum/comments/6r9nhj/cant_understand_the_erc20_short_address_attack/
31 | | 2Q5VIG9 | https://solidity.readthedocs.io/en/latest/abi-spec.html
32 | | 2Q1ybpQ | https://vessenes.com/the-erc20-short-address-attack-explained/
33 | | 2RnS1vA | http://hackingdistributed.com/2016/06/16/scanning-live-ethereum-contracts-for-bugs/
34 | | 2CSdF7y | https://solidity.readthedocs.io/en/latest/common-patterns.html
35 | | 2OfHalK | https://github.com/etherpot/contract/blob/master/app/contracts/lotto.sol
36 | | 2Jpzf4x | http://aakilfernandes.github.io/blockhashes-are-only-good-for-256-blocks
37 | | 2ACsfi1 | https://www.kingoftheether.com/thrones/kingoftheether/index.html
38 | | 2ESoaub | https://www.kingoftheether.com/postmortem.html
39 | | 2Q6E4lP | https://consensys.github.io/smart-contract-best-practices/known_attacks/#race-conditions
40 | | 2yI5Dv7 | https://github.com/ethereum/wiki/wiki/Ethash
41 | | 2SygqQx | http://hackingdistributed.com/2017/08/28/submarine-sends/
42 | | 2EUlLzb | https://hackernoon.com/front-running-bancor-in-150-lines-of-python-with-ethereum-api-d5e2bfd0d798
43 | | 2Oh8j7R | https://etherscan.io/address/0xf45717552f12ef7cb65e95476f217ea008167ae3
44 | | 2OdUC9C | https://solidity.readthedocs.io/en/latest/units-and-global-variables.html
45 | | 2AAebFr | https://etherscan.io/address/0x0d8775f648430679a709e98d2b0cb6250d2887ef#code
46 | | 2Q1AMA6 | https://applicature.com/blog/history-of-ethereum-security-vulnerabilities-hacks-and-their-fixes
47 | | 2ESWG7t | https://etherscan.io/address/0xe82719202e5965Cf5D9B6673B7503a3b92DE20be#code
48 | | 2ERI0pb | https://medium.com/cryptronics/storage-allocation-exploits-in-ethereum-smart-contracts-16c2aa312743
49 | | 2OgxPtG | https://www.reddit.com/r/ethdev/comments/7wp363/how_does_this_honeypot_work_it_seems_like_a/
50 | | 2OVkSL4 | https://medium.com/coinmonks/an-analysis-of-a-couple-ethereum-honeypot-contracts-5c07c95b0a8d
51 | | 2Ogp2Ia | https://github.com/ethereum/wiki/wiki/Safety#beware-rounding-with-integer-division
52 | | 2SwDnE0 | https://vessenes.com/ethereum-contracts-are-going-to-be-candy-for-hackers/
53 | | 2qm7ocJ | https://vessenes.com/tx-origin-and-ethereum-oh-my/
54 | | 2P3KVA4 | https://medium.com/coinmonks/solidity-tx-origin-attacks-58211ad95514
55 | |===
56 |
57 | === 代币,也称通证
58 |
59 | [options="header"]
60 | |===
61 | |短链接 | 完整链接
62 | | 2CUf7WG | https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
63 | | 2EUYCMR | https://github.com/ConsenSys/Tokens/blob/master/contracts/eip20/EIP20.sol
64 | | 2xPYck6 | https://github.com/OpenZeppelin/openzeppelin-solidity/blob/v1.12.0/contracts/token/ERC20/StandardToken.sol
65 | |===
--------------------------------------------------------------------------------
/code/web3js/web3js_demo/web3-contract-basic-interaction.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * @author Francisco Javier Rojas García
5 | */
6 |
7 | // Take a closer look at the web3 1.0 documentation for calling methods (it's very different from the 0.2x API).
8 | // https://stackoverflow.com/questions/48547268/smart-contract-method-is-not-a-function-in-web3
9 |
10 | console.log('Mastering Ethereum - web3.js basic interactions')
11 | console.log('Author: Francisco Javier Rojas García - fjrojasgarcia@gmail.com')
12 |
13 | const optionDefinitions = [
14 | { name: 'localRPC', alias: 'l', type: Boolean },
15 | { name: 'infuraFileToken', type: String, defaultOption: true }
16 | ]
17 |
18 | const commandLineArgs = require('command-line-args')
19 | const options = commandLineArgs(optionDefinitions)
20 |
21 | var Web3 = require('web3');
22 | var fs = require('fs')
23 |
24 | if (options.infuraFileToken && !options.localRPC) {
25 | console.log(options.infuraFileToken);
26 |
27 | // Loading an Infura Token from a file
28 | var infura_token = fs.readFileSync(options.infuraFileToken, 'utf8');
29 |
30 | // Show your Infura token
31 | console.log(infura_token);
32 |
33 | // Prepare your Infura host url
34 | var infura_host = `https://kovan.infura.io/${infura_token}`
35 |
36 | } else {
37 | console.log('Not argument found for infura token');
38 |
39 | // Prepare your Infura host url
40 | var infura_host = "https://kovan.infura.io"
41 |
42 | }
43 |
44 | // Show your Infura host url for your web3 connection
45 | console.log(infura_host);
46 |
47 | // Instantiate web3 provider
48 | var web3 = new Web3(infura_host);
49 |
50 | // Let's do some basic interactions at web3 level
51 | // Let's see the Protocol Version
52 | web3.eth.getProtocolVersion().then(function(protocolVersion) {
53 | console.log(`Protocol Version: ${protocolVersion}`);
54 | })
55 |
56 | // Now I'm curious about the current gas price
57 | web3.eth.getGasPrice().then(function(gasPrice) {
58 | console.log(`Gas Price: ${gasPrice}`);
59 | })
60 |
61 | // And, Whats the last mined block in my chain?
62 | web3.eth.getBlockNumber().then(function(blockNumber) {
63 | console.log(`Block Number: ${blockNumber}`);
64 | })
65 |
66 | // Now let's dive into some basics actions with a contract
67 | // We will use the contract at;
68 | // https://kovan.etherscan.io/address/0xd0a1e359811322d97991e03f863a0c30c2cf029c#code
69 |
70 | // First things first, let's initialize our contract address
71 | var our_contract_address = "0xd0A1E359811322d97991E03f863a0C30C2cF029C";
72 |
73 | // Let's see its balance
74 | web3.eth.getBalance(our_contract_address).then(function(balance) {
75 | console.log(`Balance of ${our_contract_address}: ${balance}`);
76 | })
77 |
78 | // Now let's see its byte code
79 | web3.eth.getCode(our_contract_address).then(function(code) {
80 | console.log("Contract code: ----------------------------------------------\n");
81 | console.log(code);
82 | console.log("-------------------------------------------------------------\n");
83 | })
84 |
85 | // Let's initialize our contract url in Etherescan for Kovan chain
86 | var etherescan_url = `http://kovan.etherscan.io/api?module=contract&action=getabi&address=${our_contract_address}`
87 | console.log(etherescan_url);
88 |
89 | var client = require('node-rest-client-promise').Client();
90 |
91 | // Now we are going to deal with the contract from web3.js in a non-block fashion (async mode)
92 | client.getPromise(etherescan_url)
93 | .then((client_promise) => {
94 | // Leave this two lines for fure object analisys
95 | //const util = require('util')
96 | //console.log(util.inspect(client_promise, false, null))
97 |
98 | // We get here our contract ABI
99 | our_contract_abi = JSON.parse(client_promise.data.result);
100 |
101 | // And now we create a promise to consume later
102 | return new Promise((resolve, reject) => {
103 | var our_contract = new web3.eth.Contract(our_contract_abi, our_contract_address);
104 | try {
105 | // If all goes well
106 | resolve(our_contract);
107 | } catch (ex) {
108 | // If something goes wrong
109 | reject(ex);
110 | }
111 | });
112 |
113 | })
114 | .then((our_contract) => {
115 | // Let's see our contract address
116 | console.log(`Our Contract address: ${our_contract._address}`);
117 |
118 | // or in this other way
119 | console.log(`Our Contract address in other way: ${our_contract.options.address}`);
120 |
121 | // Now our contract abi
122 | console.log("Our contract abi: " + JSON.stringify(our_contract.options.jsonInterface));
123 |
124 | // This is turning more interesting, let's see what's going with our contract methods
125 | // Now let's see our contract total supply in a callback fashion
126 | our_contract.methods.totalSupply().call(function(err, totalSupply) {
127 | if (!err) {
128 | console.log(`Total Supply with a callback: ${totalSupply}`);
129 | } else {
130 | console.log(err);
131 | }
132 | });
133 |
134 | // Or you can use the returned Promise instead of passing in the callback:
135 | our_contract.methods.totalSupply().call().then(function(totalSupply){
136 | console.log(`Total Supply with a promise: ${totalSupply}`);
137 | }).catch(function(err) {
138 | console.log(err);
139 | });
140 |
141 | })
142 |
--------------------------------------------------------------------------------
/contrib/scaling.asciidoc:
--------------------------------------------------------------------------------
1 | == Scaling
2 |
3 | One the most notable problems public blockchains face is scaling. According to Wikipedia, the definition of scaling in general can be "a computer's or network's ability to function as the number of users increases.". When talking about a blockchain, usage of the system is expressed in transactions. Based on that, we can define scalability in a blockchain as the ability of the network to function as the number of transactions increases. A popular way to measure scalability of a blockchain is measuring how much transactions per second (TPS) it can process.
4 |
5 | ////
6 | Source: https://ethereum.stackexchange.com/a/49600/31518
7 | License: CC-BY
8 | Added by: @meshugah
9 | ////
10 |
11 | Ethereum itself can support around 25 state updates (aka. transactions) per second, compared to around 500 transactions per second PayPal can support
12 | or the millions state updates (tweets, comment, likes etc.) Twitter supports we can clearly see the problem, Ethereum can not support a massive adoption of users
13 | without solving this problem. A great example of this would be the infamous Crypto Kitties flu of December 2017, it showed us exactly what a
14 | small pick in the usage of Ethereum can do to the network, transactions were taking hours to days and the fees were about 40 Gwei -
15 | more than 10 times higher than the typical fee.
16 |
17 | === "The Blockchain Trillema"
18 |
19 | The reason for these scalability issues can be explained using what's called "The Blockchain Trillema".
20 | This is a trillema where (without a decent solution) a blockchain can support only 2 edges of the triangle and needs to compromise on the on third one.
21 | The three edges are:
22 |
23 | * Scalability
24 | * Decentralization
25 | * Security
26 |
27 | We can look at what each combination of 2 out of the 3 may look like.
28 |
29 | Scalability combined with Security - This could be a private blockchain, since the consensus needs to be achieved is only between a small cluster of trusted nodes (or maybe only one)
30 | there is no need for many security features such as distributed consensus that public blockchains need and the communication between a few nodes is much faster than between a big decentralized network.
31 |
32 | Scalability combined with Decentralization - A great example for this could be a public blockchain such as Bitcoin or Ethereum, but with with 0 block confirmations
33 | this may allow instant transactions with the additional benefit of no fees but it is extremely insecure to the point that it is just not very applicable.
34 |
35 | Decentralization and Security - this is certainly where most public blockchains including Bitcoin and Ethereum are at, they are decentralized and secure
36 | but as said before, they do not support strong scaling solutions at the time of writing this.
37 |
38 | The problem with this Trillema is you can't completely win it, you just can't support very high TPS, a huge open network of nodes and be secure all at once.
39 |
40 | With that in mind, we can start exploring the different approaches of scaling the public blockchain without decreasing decentralization or security
41 | it is important to understand, since it is not possible to completely satisfy all 3 at the same time most solutions aim to get to some point in the middle
42 | where they have decent security, decentralization and scalability.
43 |
44 | == Attempts at scaling
45 |
46 | === Casper - Proof of Stake for Ethereum
47 | Proof of Stake is a form of consensus that aims to improve/ replace the current Proof of Work consensus. The idea of Proof of Work consensus algoritm, in its simplest form, is to allow reaching consensus based on a '1 CPU is 1 vote'. Proof of Stake introduces a new voting power distribution idea in a '1 Coin is 1 vote' basis, effectively moving the power of a vote from computational power to a participant's stake in the system.
48 |
49 | Proof of Stake grants the ability to provide a blockchain with "economic finality", thus strengthening it's economical security, reducing centralization risks by making it less rewardable to collude on a majority attack. A benefit to the change Proof-of-Stake is that it makes the protocol easier on the environment by replacing the Proof-of-Work's energy expenditure ,as a result of the struggle for power in the network, with the desire to hold stake in the security of the network.
50 |
51 | Ethereum has officially decided to shift its consensus algorithm from Proof of Work to Proof of stake. The new Proof of Stake algorithm for Ethereum is called Casper - The Friendly GHOST, a playful monicker refering to Casper the Friendly Ghost, where GHOST stands for Greedy Heaviest Observed Sub-Tree. It was decided that the transition to Proof of Stake will be done in 2 phases.
52 | The motivation behind this was to give room to handle unforseen transient effects and to allow for current users of the system to have a smoother transition.
53 |
54 | The first part of the roll-out is a hybrid Proof of Work - Proof of Stake algorithm called Casper the Friendly Finality Gadget (FFG) which aims to provide finality and implicitly reduce energy waste. The second and target update is called Casper, Correct By Construction (CBC), this is a pure Proof of Stake algorithm and will complete Ethereum's transition to Proof of Stake.
55 |
56 | Casper the Friendly Finality Gadget (FFG)
57 |
58 |
59 | Casper Correct by Construction (CBC)
60 |
61 |
62 | Sharding
63 |
64 | Plasma
65 |
66 | Raiden
67 |
68 | Counterfactual State Channels
69 |
70 | Truebit
71 |
72 | Loom Network
73 |
--------------------------------------------------------------------------------
/14consensus_cn.asciidoc:
--------------------------------------------------------------------------------
1 | [[consensus]]
2 | == 共识
3 |
4 | (((“consensus”,id =“ ix_14consensus-asciidoc0”,range =“ startofrange”))) 在本书中,我们一直在讨论“共识规则”,即每个人都必须同意的规则—才能在分散式系统中运行。在计算机科学中,术语 _共识_ 早于区块链,并且涉及更广泛的同步分布式系统中状态的问题,从而使分布式系统中的不同参与者都(最终)都同意一个系统范围的状态。这被称为“达成共识”。
5 |
6 | 当涉及分布式记录保存和验证的核心功能时,需要保证从状态更新中获得的信息是正确。仅仅依靠信任来确保信息的正确性可能会成为问题。这种普遍性的挑战在分步式网络中尤其明显,因为没有中央实体来决定什么是正确的。缺乏中央决策实体是区块链平台的主要吸引力之一,因为由此产生的抵抗审查的能力以及对授权信息访问权限的缺乏依赖。但是,这些好处是要付出代价的:没有受信任的仲裁员,任何分歧,欺骗或区别都需要使用其他手段加以调和。共识算法是用于协调安全性和分布性的机制。
7 |
8 | 在区块链中,共识是系统的关键属性。简而言之,资金有危险!因此,在区块链的背景下,_consensus_ 是关于能够达到一个共同的状态,同时保持去中心化。换句话说,共识旨在产生一个没有统治者的严格规则系统。没有单个人,组织或团体的可以:[“决策”;] 相反,权力和控制分散在广泛的参与者网络中,他们的个人利益通过遵守规则和诚实行事来实现。
9 |
10 | 所有开放式公共区块链都有一个核心原则,就是具有在对抗条件下,无需集中控制就能在分布式网络上达成共识的能力。为了应对这一挑战并保持去中心化的价值,社区继续尝试不同的共识模型。本章探讨了这些共识模型及其对以太坊等支持智能合约的区块链的预期影响。
11 |
12 | [NOTE]
13 | ====
14 | 尽管共识算法是区块链工作方式的重要组成部分,但它们在基础层运行,远低于智能合约的抽象层。换句话说,共识的大多数细节对智能合约的开发者都是隐藏的。类似你不需要了解路由器如何工作才能使用互联网,你也不需要了解共识算法如何工作来使用以太坊。
15 | ====
16 |
17 | === 通过工作量证明达成共识
18 |
19 | ((("consensus","via proof of work")))((("proof of work (PoW)","consensus via")))原始区块链比特币的创建者发明了一种称为 _工作量证明_(POW)的 _共识算法_。可以说,PoW是比特币架构中的最重要的发明。 PoW的俗称是“挖矿”,但这一俗称使得人们对共识的主要目的产生了误解。人们通常认为挖矿的目的是创造新的货币,因为现实世界中的挖矿目的是提取贵金属或其他资源。实际上,挖矿(和所有其他共识模型一样)的真正目的是“保护区块链”,同时分散对系统的控制权并将权利分散到尽可能多的参与者中。挖矿产生的货币奖励是对那些为系统安全做出贡献的参与者的一种激励:达到目的的手段。从这个意义上说,奖励是手段,而分散的安全性是目的。在PoW共识中,还存在相应的“惩罚”,即参与采矿所需的能源成本。如果参与者不遵守规则而试图获得奖励,他们将承担已经在挖矿上花费的资金风险。因此,PoW共识是风险与回报之间的谨慎平衡,驱使参与者出于自身利益诚实地行事。
20 |
21 | 以太坊目前是一个PoW区块链,因为它使用PoW算法并具有相同的激励系统来实现基本目标:在分散控制权的同时保护区块链。以太坊的PoW算法与比特币算法稍有不同,称为 _Ethash_。我们将在<>中介绍。
22 |
23 | === 通过权益证明(PoS)达成共识
24 |
25 | ((("consensus","via proof of stake")))((("proof of stake (PoS)","consensus via")))从历史上看,工作量证明并不是提出的第一个共识算法。在引入工作量证明之前,许多研究人员提出了基于财务权益的共识算法的变体,现在称为权益证明(PoS)。从某种程度上说,工作量证明是作为权益证明的替代方法而发明的。随着比特币的成功,许多区块链都模仿了工作量证明。然而,对共识算法研究的重视也使得人民开始重新研究权益证明,从而极大地推动了该技术的发展。从一开始,以太坊的创始人就希望最终将其共识算法迁移到权益证明中。实际上,以太坊的工作量证明有一个故意的障碍,称为“难度炸弹”,意在逐渐使以太坊的工作量证明挖矿越来越困难,从而迫使向权益证明过渡。
26 |
27 | 在本书出版之时,以太坊仍在使用工作量证明,但正在进行的有关权益证明的替代方案的研究已接近完成。以太坊计划的PoS算法称为 _Casper_。在过去两年中,卡斯珀(Casper)替代Ethash的计划已被推迟了好几次,因此必须采取干预措施以缓解难度炸弹的发生,从而避免强制废除工作量证明。
28 |
29 | 通常而言,PoS算法的工作原理如下。区块链跟踪一组验证者,任何持有区块链基础加密货币(以太坊中为以太币)的人都可以通过发送一种特殊的交易来将其以太币锁定为押金来成为验证者。验证人轮流对下一个有效区块提出建议并投票,每个验证人的投票权重取决于其押金(即权益)的大小。重要的是,如果将验证者押在其上的区块被大多数验证者拒绝,则验证者可能会丢失其押金。相反,对于大多数人接受的每个区块,验证者都会获得与他们所存股份成比例的少量奖励。因此,PoS通过奖励和惩罚系统迫使验证者诚实行事并遵循共识规则。 PoS和PoW之间的主要区别在于PoS中的惩罚是区块链固有的资源(例如,失去作为押金的以太币),而在PoW中,惩罚是外部的资源(例如,在加入验证上花费的资金损失 pass:[ 电力 ])。
30 |
31 | [[ethash]]
32 | === Ethash:以太坊的工作量证明算法
33 |
34 | ((("Buterin, Vitalik","and Dagger algorithm")))((("consensus","Ethash as Ethereum PoW algorithm")))((("Dagger-Hashimoto algorithm")))((("Ethash")))((("proof of work (PoW)","Ethash as Ethereum PoW algorithm")))Ethash是以太坊PoW算法。它使用了Dagger–Hashimoto算法的改进,该算法是Vitalik Buterin的Dagger算法和Thaddeus Dryja的Hashimoto算法的结合。((("DAG (directed acyclic graph)")))((("directed acyclic graph (DAG)")))Ethash取决于大型数据集的生成和分析,称为 _有向无环图_ 简写为“ DAG”)。 DAG的初始大小约为1 GB,并将继续缓慢且线性地增长,每个时期更新一次(30,000块,约125小时)。
35 |
36 | DAG的目的是使Ethash PoW算法依赖于维护大型,频繁访问的数据结构。((("application-specific integrated circuits (ASIC)")))((("ASIC (application-specific integrated circuits)")))((("graphics processing unit (GPU), mining and")))反过来,这是为了使Ethash具有“抗ASIC”性,这意味着制造专用集成电路(ASIC)采矿设备要比显卡(GPU)快几个数量级。以太坊的创始人希望避免在PoW采矿中集中化,因为那些可以使用专门设备并拥有大量预算的人可能会主导矿机基础设施并破坏共识算法的安全性。
37 |
38 | 使用普通商业级别的GPU在以太坊网络上执行PoW意味着世界各地更多的人可以参与挖矿过程。越独立的矿工,采矿权就越分散,这意味着我们可以避免发生类似比特币的情况,即大部分采矿权都集中在少数大型工业采矿业主的手中。使用GPU进行挖矿的不利之处在于,它在2017年导致了全球范围内GPU的短缺,导致其价格飞涨,并受到游戏玩家的强烈抗议。这导致了零售商的购买限制,将购买者限制为每个客户一个或两个GPU。
39 |
40 | 直到最近,ASIC矿工对以太坊网络的威胁基本上还不存在。将ASIC用于以太坊需要设计,制造和销售高度定制的硬件。生产它们需要大量的时间和金钱投资。以太坊开发人员长期以来打算转向PoS共识算法的计划也会使ASIC供应商的长期目标是远离以太坊网络。一旦以太坊转移到PoS,为PoW算法设计的ASIC将变得毫无用处,也就是说,除非矿工可以使用它们来开采其他加密货币。后者的可能性现在已经成为现实,包括PIRL和Ubiq等一系列基于Ethash的共识硬币,以太坊经典承诺在可预见的未来仍将是PoW区块链。这意味着我们可能会看到ASIC挖矿在以太坊网络上仍使用PoW的时候成为能够影响以太坊网络的力量。
41 |
42 | === Casper:以太坊的权益证明算法
43 |
44 | ((("Casper")))((("consensus","Casper as Ethereum PoS algorithm")))((("proof of stake (PoS)","Casper as Ethereum PoS algorithm")))Casper是以太坊的PoS共识算法的建议名称。该算法仍在积极研发中,在本书出版时尚未在以太坊区块链上实现。 ((("Casper CBC")))((("Casper FFG")))Casper正在两个竞争的“方向”中开发:
45 |
46 | * Casper FFG:“好用的决策小工具”
47 | * Casper CBC:“好用的GHOST /按构造校正”
48 |
49 | Casper 的FFG最初被提出来作为一种PoW / PoS混合算法,作为向更稳定的“纯PoS”算法的过渡。 (("Buterin, Vitalik","and Casper")))但是,在2018年6月,负责Casper FFG研究工作的Vitalik Buterin决定“废除”混合模型,以使用纯PoS算法。现在,Casper FFG和Casper CBC都在并行开发。正如Vitalik解释的那样:
50 |
51 | ____
52 | FFG和CBC之间的主要折衷是CBC似乎具有更好的理论特性,但FFG似乎更易于实现。
53 | ____
54 |
55 | 有关Casper历史,正在进行的研究和未来计划的更多信息,请访问以下链接:
56 |
57 | * http://bit.ly/2RO5HAl[Ethereum Casper(权益证明)]
58 | * http://bit.ly/2FlBojb[Casper的历史,第1部分]
59 | * http://bit.ly/2QyHiic[Casper的历史,第2部分]
60 | * http://bit.ly/2JWWFyt[Casper的历史,第3部分]
61 | * http://bit.ly/2FsaExI[Casper的历史,第4部分]
62 | * http://bit.ly/2PPhhOv[Casper的历史,第5部分]
63 |
64 | === 共识原则
65 |
66 | ((("consensus","principles of")))可以通过提出一些关键问题来更清楚地理解共识算法的原理和假设:
67 |
68 | * 谁可以改变过去,如何改变? (这也称为 _不变性_。)
69 | * 谁可以改变未来,如何改变? (这也称为 _最终性_。)
70 | * 进行此类变革的成本是多少?
71 | * 进行此类变革的权力有多分散?
72 | * 谁会知道情况是否已改变,他们是如何知道的?
73 |
74 | 共识算法正在迅速发展,将会有更加创新的方法回答这些问题。
75 |
76 | === 争议与竞争
77 |
78 | ((("consensus","controversy and competition")))此时,你可能会想:为什么我们需要这么多不同的共识算法?哪个更好?后一个问题的答案是过去十年中分布式系统中最令人兴奋的研究中心。一切都归结为您认为“更好”—”的定义。在计算机科学的背景下,这是关于假设,目标和不可避免的权衡取舍。
79 |
80 | 一种非常大的可能是没有算法可以在分布式共识问题的所有维度上完成优化。当一些人认为一种共识算法比其他共识算法“更好”时,你应该开始提出一些问题来搞清这些情况:在什么方面更好?不变性,最终性,分布性,还是成本?至少在目前,这些问题尚无明确答案。此外,共识算法的设计是数十亿美元产业的中心,并引发了巨大的争议和激烈的争论。最终的结果,可能没有一个唯一“正确”的答案,而是针对不同的应用会有不同的答案。
81 |
82 | 整个区块链行业是一个巨大的实验。巨量资金将会投注到这场实验中,在对抗性条件下对各种问题进行测试。最终,历史将回答争议。
83 |
84 | === 本章小结
85 |
86 | 在本书编写完成时,以太坊的共识算法仍在不断发展。随着Casper和其他相关技术的成熟并部署在以太坊上,我们在未来的版本中会添加更多详细信息。本章代表我们这次旅程的结束,完成 _掌握以太坊_。其他参考材料见附录。感谢您阅读本书,并恭喜您成功完成!(((range="endofrange", startref="ix_14consensus-asciidoc0")))
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | new OptimizeCSSPlugin({
56 | cssProcessorOptions: config.build.productionSourceMap
57 | ? { safe: true, map: { inline: false } }
58 | : { safe: true }
59 | }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vendor modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------
/github_contrib.asciidoc:
--------------------------------------------------------------------------------
1 | [[github_contrib]]
2 | === Contributions
3 |
4 | Many contributors offered comments, corrections, and additions to the early-release draft on GitHub.
5 |
6 | Contributions on GitHub were facilitated by two editors who volunteered to project manage, review, edit, merge, and approve pull requests and issues:
7 |
8 | * Francisco Javier Rojas Garcia (fjrojasgarcia)
9 | * Will Binns (wbnns)
10 |
11 | Major contributions were provided on the topics of DApps, ENS, the EVM, fork history, gas, oracles, smart contract security, and Vyper. Additional contributions, which were not included in this first edition due to time and space constraints, can be found in the _contrib_ folder of the GitHub repository. Thousands of smaller contributions throughout the book have improved its quality, legibility, and accuracy. Sincere thanks to all those who contributed!
12 |
13 | Following is an alphabetically sorted list of all the GitHub contributors, including their GitHub IDs in parentheses:
14 |
15 | * Abhishek Shandilya (abhishandy)
16 | * Adam Zaremba (zaremba)
17 | * Adrian Li (adrianmcli)
18 | * Adrian Manning (agemanning)
19 | * Alejandro Santander (ajsantander)
20 | * Alejo Salles (fiiiu)
21 | * Alessandro Coglio (acoglio)
22 | * Alex Manuskin (amanusk)
23 | * Alex Van de Sande (alexvandesande)
24 | * Anthony Lusardi (pyskell)
25 | * Anup Dhakal (anuphunt)
26 | * Assaf Yossifoff (assafy)
27 | * athio92 (athio92)
28 | * Ben Kaufman (ben-kaufman)
29 | * bgaughran (bgaughran)
30 | * Bok Khoo (bokkypoobah)
31 | * Brandon Arvanaghi (arvanaghi)
32 | * Brian Ethier (dbe)
33 | * Bryant Eisenbach (fubuloubu)
34 | * Carl Park (4000D)
35 | * Carlos Cebrecos (ccebrecos)
36 | * Chanan Sack (chanan-sack)
37 | * Charlie Leathers (cleathers)
38 | * Chris Lin (ChrisLinn)
39 | * Chris Remus (chris-remus)
40 | * Christopher Gondek (christophergondek)
41 | * Cornell Blockchain (CornellBlockchain)
42 | - Alex Frolov (sashafrolov)
43 | - Brian Guo (BrianGuo)
44 | - Brian Leffew (bleffew99)
45 | - Giancarlo Pacenza (GPacenza)
46 | - Lucas Switzer (LucasSwitz)
47 | - Ohad Koronyo (ohadh123)
48 | - Richard Sun (richardsfc)
49 | * Cory Solovewicz (CorySolovewicz)
50 | * crypto501 (crypto501)
51 | * Dan Shields (NukeManDan)
52 | * Danger Zhang (safetyth1rd)
53 | * Daniel Jiang (WizardOfAus)
54 | * Daniel McClure (danielmcclure)
55 | * Daniel Peterson (danrpts)
56 | * Dave Potter (dnpotter)
57 | * David Lozano Jarque (davidlj95)
58 | * David McFadzean (macterra)
59 | * Denis Milicevic (D-Nice)
60 | * Dennis Zasnicoff (zasnicoff)
61 | * Diego H. Gurpegui (diegogurpegui)
62 | * Dimitris Tsapakidis (dimitris-t)
63 | * Dzmitry Bachko (dbachko)
64 | * Edward Posnak (edposnak)
65 | * Enrico Cambiaso (auino)
66 | * Ersin Bayraktar (ersinbyrktr)
67 | * Exhausted Mind (exhaustedmind)
68 | * Flash Sheridan (FlashSheridan)
69 | * Franco Abaroa (francoabaroa)
70 | * Franco Daniel Berdun (fMercury)
71 | * Griff Green (GriffGreen)
72 | * Harry Moreno (morenoh149)
73 | * Harshal Patil (ErHarshal)
74 | * Håvard Anda Estensen (estensen)
75 | * Hon Lau (masterlook)
76 | * Hudson Jameson (Souptacular)
77 | * Hyunbin Jeong (gusqls1603)
78 | * Iuri Matias (iurimatias)
79 | * Ivan Molto (ivanmolto)
80 | * Jacques Dafflon (jacquesd)
81 | * Jason Hill (denifednu)
82 | * Javier Rojas (fjrojasgarcia)
83 | * Jaycen Horton (jaycenhorton)
84 | * JB Paul (yjb94)
85 | * jeremyfny (jeremyfny)
86 | * Joel Gugger (guggerjoel)
87 | * John Woods (johnalanwoods)
88 | * Jon Ramvi (ramvi)
89 | * Jonathan Velando (rigzba21)
90 | * jpopxfile (jpopxfile)
91 | * Jules Lainé (fakje)
92 | * Karolin Siebert (karolinkas)
93 | * Kevin Carter (kcar1)
94 | * Kevin Weaver (kevinweaver)
95 | * Krzysztof Nowak (krzysztof)
96 | * Lane Rettig (lrettig)
97 | * Leo Arias (elopio)
98 | * Liang Ma (liangma)
99 | * Łukasz Gołębiewski (lukasz-golebiewski)
100 | * Luke Schoen (ltfschoen)
101 | * Marcelo Creimer (mcreimer)
102 | * Martin Berger (drmartinberger)
103 | * Masi Dawoud (mazewoods)
104 | * Massimiliano Terzi (terzim)
105 | * Matt Peskett (mattpeskett)
106 | * Matthew Sedaghatfar (sedaghatfar)
107 | * mehlawat (mehlawat)
108 | * Michael Freeman (stefek99)
109 | * Miguel Baizan (mbaiigl)
110 | * Mike Pumphrey (bmmpxf)
111 | * Milo Chen (milochen0418)
112 | * Mobin Hosseini (iNDicat0r)
113 | * Nagesh Subrahmanyam (chainhead)
114 | * Nichanan Kesonpat (nichanank)
115 | * Nicholas Maccharoli (Nirma)
116 | * Nick Johnson (arachnid)
117 | * Omar Boukli-Hacene (oboukli)
118 | * Paulo Trezentos (paulotrezentos)
119 | * Pet3rpan (pet3r-pan)
120 | * Peter Kacherginsky (iphelix)
121 | * Pierre-Jean Subervie (pjsub)
122 | * Pong Cheecharern (Pongch)
123 | * Qiao Wang (qiaowang26)
124 | * Raul Andres Garcia (manilabay)
125 | * rattle99 (rattle99)
126 | * robFifth (robFifth)
127 | * Robin Pan (robinpan1)
128 | * Roger Häusermann (haurog)
129 | * Robert Miller (bertmiller)
130 | * Saxon Knight (knight7)
131 | * Sebastian Falbesoner (theStack)
132 | * Sejin Kim (sejjj120)
133 | * Seong-il Lee (modolee)
134 | * sgtn (shogochiai)
135 | * Solomon Victorino (bitsol)
136 | * stefdelec (stefdelec)
137 | * Steve Klise (sklise)
138 | * Sylvain Tissier (SylTi)
139 | * Taylor Masterson (tjmasterson)
140 | * Tim Nugent (timnugent)
141 | * Timothy McCallum (tpmccallum)
142 | * Tommy Cooksey (tcooksey1972)
143 | * Tomoya Ishizaki (zaq1tomo)
144 | * Ulrich Stark (ulrichstark)
145 | * Vignesh Karthikeyan (meshugah)
146 | * westerpants (westerpants)
147 | * Will Binns (wbnns)
148 | * Xavier Lavayssière (xalava)
149 | * Yash Bhutwala (yashbhutwala)
150 | * Yeramin Santana (ysfdev)
151 | * Yukishige Nakajo (nakajo2011)
152 | * Zhen Wang (zmxv)
153 | * ztz (zt2)
154 |
155 |
156 | Without the help offered by everyone listed above, this book would not have been possible. Your contributions demonstrate the power of open source and open culture, and we are eternally grateful for your help. Thank you.
157 |
--------------------------------------------------------------------------------
/code/auction_dapp/frontend/src/models/AuctionRepository.js:
--------------------------------------------------------------------------------
1 | import Config from '../config'
2 |
3 | export class AuctionRepository {
4 |
5 | web3 = null
6 | account = ''
7 | contractInstance = null
8 | gas = 4476768
9 |
10 | constructor(){
11 | this.gas = Config.GAS_AMOUNT
12 | }
13 |
14 | setWeb3(web3) {
15 | this.web3 = web3
16 | this.contractInstance = this.web3.eth.contract(Config.AUCTIONREPOSITORY_ABI).at(Config.AUCTIONREPOSITORY_ADDRESS)
17 | }
18 |
19 | getWeb3() {
20 | return this.web3
21 | }
22 |
23 | setAccount(account){
24 | this.account = account
25 | }
26 |
27 |
28 | getCurrentBlock() {
29 | return new Promise((resolve, reject ) => {
30 | this.web3.eth.getBlockNumber((err, blocknumber) => {
31 | if(!err) resolve(blocknumber)
32 | reject(err)
33 | })
34 | })
35 | }
36 |
37 | async watchIfCreated(cb) {
38 | const currentBlock = await this.getCurrentBlock()
39 | const eventWatcher = this.contractInstance.AuctionCreated({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
40 | eventWatcher.watch(cb)
41 | }
42 |
43 | async watchIfBidSuccess(cb) {
44 | const currentBlock = await this.getCurrentBlock()
45 | const eventWatcher = this.contractInstance.BidSuccess({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
46 | eventWatcher.watch(cb)
47 | }
48 |
49 | async watchIfCanceled(cb) {
50 | const currentBlock = await this.getCurrentBlock()
51 | const eventWatcher = this.contractInstance.AuctionCanceled({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
52 | eventWatcher.watch(cb)
53 | }
54 |
55 | async watchIfFinalized(cb) {
56 | const currentBlock = await this.getCurrentBlock()
57 | const eventWatcher = this.contractInstance.AuctionFinalized({}, {fromBlock: currentBlock - 1, toBlock: 'latest'})
58 | eventWatcher.watch(cb)
59 | }
60 | getCurrentBid(auctionId) {
61 | return new Promise(async (resolve, reject) => {
62 | try {
63 | this.contractInstance.getCurrentBid(auctionId, {from: this.account, gas: this.gas }, (err, transaction) => {
64 | if(!err) resolve(transaction)
65 | reject(err)
66 | })
67 | } catch(e) {
68 | reject(e)
69 | }
70 | })
71 | }
72 |
73 | getBidCount(auctionId) {
74 | return new Promise(async (resolve, reject) => {
75 | try {
76 | this.contractInstance.getBidsCount(auctionId, {from: this.account, gas: this.gas }, (err, transaction) => {
77 | if(!err) resolve(transaction)
78 | reject(err)
79 | })
80 | } catch(e) {
81 | reject(e)
82 | }
83 | })
84 | }
85 |
86 | getCount() {
87 | return new Promise(async (resolve, reject) => {
88 | try {
89 | this.contractInstance.getCount({from: this.account, gas: this.gas }, (err, transaction) => {
90 | if(!err) resolve(transaction)
91 | reject(err)
92 | })
93 | } catch(e) {
94 | reject(e)
95 | }
96 | })
97 | }
98 |
99 | bid(auctionId, price) {
100 | console.log(auctionId, this.web3.utils.toWei(price, 'ether'))
101 | return new Promise(async (resolve, reject) => {
102 | try {
103 | this.contractInstance.bidOnAuction(auctionId, {from: this.account, gas: this.gas, value: this.web3.utils.toWei(price, 'ether') }, (err, transaction) => {
104 | if(!err) resolve(transaction)
105 | reject(err)
106 | })
107 | } catch(e) {
108 | reject(e)
109 | }
110 | })
111 | }
112 |
113 | create(deedId, auctionTitle, metadata, startingPrice, blockDeadline) {
114 | return new Promise(async (resolve, reject) => {
115 | try {
116 |
117 | this.contractInstance.createAuction(Config.DEEDREPOSITORY_ADDRESS, deedId, auctionTitle, metadata, this.web3.utils.toWei(startingPrice, 'ether'), blockDeadline, {from: this.account, gas: this.gas }, (err, transaction) => {
118 | if(!err) resolve(transaction)
119 | reject(err)
120 | })
121 | } catch(e) {
122 | reject(e)
123 | }
124 | })
125 | }
126 |
127 | cancel(auctionId) {
128 | return new Promise(async (resolve, reject) => {
129 | try {
130 | this.contractInstance.cancelAuction(auctionId, {from: this.account, gas: this.gas }, (err, transaction) => {
131 | if(!err) resolve(transaction)
132 | reject(err)
133 | })
134 | } catch(e) {
135 | reject(e)
136 | }
137 | })
138 | }
139 |
140 | finalize(auctionId) {
141 | return new Promise(async (resolve, reject) => {
142 | try {
143 | this.contractInstance.finalizeAuction(auctionId, {from: this.account, gas: this.gas }, (err, transaction) => {
144 | if(!err) resolve(transaction)
145 | reject(err)
146 | })
147 | } catch(e) {
148 | reject(e)
149 | }
150 | })
151 | }
152 |
153 | findById(auctionId) {
154 | return new Promise(async (resolve, reject) => {
155 | try {
156 | this.contractInstance.getAuctionById(auctionId, { from: this.account, gas: this.gas }, (err, transaction) => {
157 | if(!err) resolve(transaction)
158 | reject(err)
159 | })
160 | } catch(e) {
161 | reject(e)
162 | }
163 | })
164 | }
165 |
166 | }
--------------------------------------------------------------------------------
/preface_open_edition_cn.asciidoc:
--------------------------------------------------------------------------------
1 | [preface]
2 | [[preface]]
3 | == 前言
4 |
5 | 这本书是Andreas M. Antonopoulos和Gavin Wood博士领导下的合作。一系列幸运的巧合使这两位作者齐心协力,以开源和创新公共文化的最佳精神激励了数百位撰稿人来共同编写这本书。
6 |
7 | Gavin一直希望在黄皮书(主要是对以太坊协议的技术描述)的基础上进行扩展来写一本书,毕竟原有的技术文档对于很多读者来说还是过于晦涩难懂,而他可以在书中用更加通俗易懂的语言解释以太坊的技术细节,让更多的读者易于理解。
8 |
9 | Andreas在Gavin建立以太坊之初就认识他,是区块链领域的杰出人物。当Gavin制定了写书计划,并找到了出版商的时候,决定找机会与Andreas谈谈。
10 |
11 | Andreas刚刚出版了他的著作 _《精通比特币》_(O'Reilly)的第一版,该书很快成为了比特币和加密货币的权威技术指南。该书一出版,几乎他的读者就开始问他:“你什么时候写《精通以太坊》?” Andreas已经在考虑他的下一个项目,并发现以太坊是一个非常好的技术主题。
12 |
13 | 最后,在2016年5月,Gavin和Andreas碰巧同时在同一座城市。他们聚在一起喝咖啡,聊聊一起写这本书。在由于Andreas和Gavin都是开源精神的奉行者,他们俩都致力于通过知识共享许可协议进行协作来写这本书。值得庆幸的是,发行人O'Reilly Media很高兴与他们达成共识,这样 _《精通以太坊》_ 项目就可以正式启动了。
14 |
15 | === 如何使用这本书
16 |
17 | 这本书既可以作为参考手册,又可以作为对以太坊的从无到有的入门教材。前两章提供了适合新手用户的简要介绍,并且本章中的示例可以由任何具有基础技能的人来完成。这两章将使你更好地掌握基础知识,并允许你使用以太坊的基本工具。 <>及之后的更多内容主要供程序员使用,并包含许多技术主题和编程示例。
18 |
19 | 为了同时用作参考手册和以太坊的详细介绍,本书不可避免地包含了一些重复之处。有些概念(例如 _燃料gas_ )必须尽早引入,以便解释其它概念,但也需要在其各自的部分中进行深入研究。
20 |
21 | 最后,该书的索引使读者可以通过关键字轻松地找到具体的主题和相关部分。
22 |
23 | [[intended_audience_sec]]
24 | === 目标读者
25 |
26 | ((("intended audience")))这本书主要供程序员使用。如果你可以使用编程语言,这本书将教会你智能合约区块链的工作原理,如何使用它们,以及如何使用它们开发智能合约和去中心化应用程序。前几章也适合作为非程序员读者对以太坊有个更深入的了解。
27 |
28 |
29 |
30 | [[conventinons_used_sec]]
31 | === 本书中使用的字符规则
32 |
33 | ((("typographical conventions")))本书中使用以下印刷格式:
34 |
35 | _斜体字_:: 表示新术语,URL,电子邮件地址,文件名和文件扩展名。
36 |
37 | +恒定宽度字体+:: 用于程序列表,以及在段落中用于引用程序元素,例如变量或函数名称,数据库,数据类型,环境变量,语句和关键字。
38 |
39 | **`恒定宽度的粗体字`**:: 显示用户应按字面意义键入的命令或其他文本。
40 |
41 | _++恒定宽度斜体字++_:: 显示应替换为用户提供的值或由上下文确定的值的文本。
42 |
43 |
44 | [TIP]
45 | ====
46 | 此图标表示提示或建议。
47 | ====
48 |
49 | [NOTE]
50 | ====
51 | 此图标表示一般注释。
52 | ====
53 |
54 | [WARNING]
55 | ====
56 | 此图标表示警告或注意。
57 | ====
58 |
59 | [[code_examples_sec]]
60 | === 代码示例
61 |
62 | ((("code examples, obtaining and using")))所有的程序示例都是用 Solidity,Vyper 和 JavaScript写成的,并在类Unix的操作系统的命令行下进行操作。所有代码均位于GitHub代码库 _code_ 子目录下。你可以复制书里面的代码,测试它们,并通过GitHub提交更正: https://github.com/ethereumbook/ethereumbook.
63 |
64 | 所有代码片段都可以在大多数操作系统上进行复制,而只需安装相应语言的编译器,解释器和库即可。必要时,我们提供基本的安装说明以及这些说明的分步示例输出结果。
65 |
66 | 一些代码段和代码输出已重新格式化以供打印。在所有这些情况下,行均由反斜杠( +\+ )字符和换行符分隔。复制示例时,删除这两个字符并再次连接各行,你应该会看到与示例中显示的结果相同的结果。
67 |
68 | 所有代码片段均在可能的情况下使用实际值和计算,因此你可以从示例到示例进行构建,并在编写用于计算相同值的任何代码中看到相同的结果。例如,私钥以及相应的公钥和地址都是真实的。示例中的交易,合约,区块和区块链参考均已写入实际的以太坊区块链,并且记录到了公共账本中,你随时可以在区块链上对这些内容进行复查。
69 |
70 | [[using_code_examples_sec]]
71 | === Using Code Examples
72 |
73 | 本书旨在帮助您完成工作。 一般来说,如果本书提供了示例代码,你可以在你的程序和文档中使用它。 除非您要复制大部分代码,否则您无需联系我们以获得许可。 例如,编写使用本书中几段代码的程序不需要许可。 销售或分发 O'Reilly 书籍示例的 CD-ROM 确实需要获得许可。 通过引用本书和引用示例代码来回答问题不需要许可。 将本书中的大量示例代码合并到您的产品文档中确实需要获得许可。
74 |
75 | ((("attribution"))) 我们感谢,但不要求注明出处。出处通常包括标题,作者,出版者,ISBN和版权。例如:“ __精通以太坊__,由Andreas M. Antonopoulos和Gavin Wood博士撰写。版权所有2019以太坊图书有限公司和Gavin Wood”
76 |
77 | ((("open source licenses")))__精通以太坊__使用的版权许可是Creative Commons Attribution-ShareAlike International License(CC BY SA 4.0)。
78 |
79 |
80 | === 对公司和产品的引用
81 |
82 | 对公司和产品的所有引用均用于教育,演示和参考目的。作者并不认可所提及的任何公司或产品。本书中显示的任何产品,项目或代码段的操作或安全性并未经过我们的测试。使用它们需要你承担风险!
83 |
84 | [[ethereum_sddresses_and_transactions_sec]]
85 | === 本书中的以太坊地址和交易
86 |
87 | ((("blockchain","warnings and cautions")))((("keys and addresses", seealso="cryptography; private keys; public keys")))((("QR codes")))((("transactions","warnings and cautions")))((("warnings and cautions","when using test and example material appearing in book")))本书中使用的大部分以太坊地址,交易,密钥,QR码和区块链数据都是真实的。这意味着你可以浏览区块链,查看作为示例提供的交易,使用自己的脚本或程序等进行检索等操作。
88 |
89 | ((("warnings and cautions","avoid sending money to addresses appearing in book")))但是,请注意,用于构造本书中账户地址的私钥已被“销毁”。这意味着,如果你向这些地址中的任何一个汇款,这笔钱将永远丢失或(更可能)被挪用,因为任何人阅读这本书都可以使用写在书中的私钥来取走账户中的资金。
90 |
91 | [WARNING]
92 | ====
93 | 千万千万不要向本手册中的任何账户地址发送任何交易。你的以太币或者通证将由另一位读者拿走,或永远丢失。
94 | ====
95 |
96 | [[how_to_contact_us_sec]]
97 | === How to Contact Us
98 |
99 | ==== 联系作者Andreas
100 |
101 | 您可以在他的个人网站上联系Andreas M. Antonopoulos:
102 | link:$$https://antonopoulos.com/$$[]
103 |
104 | 在YouTube上订阅Andreas的频道:
105 | link:$$https://www.youtube.com/aantonop$$[]
106 |
107 | 在Facebook上把Andreas加为好友:
108 | link:$$https://www.facebook.com/AndreasMAntonopoulos$$[]
109 |
110 | 在Twitter上关注Andreas:
111 | link:$$https://twitter.com/aantonop$$[]
112 |
113 | 在领英(LinkedIn)上与Andreas联系:
114 | link:$$https://linkedin.com/company/aantonop$$[]
115 |
116 | Andreas也要感谢所有通过每月捐款支持他的工作的赞助人。你可以在Patreon上为Andreas提供支持
117 | link:$$https://patreon.com/aantonop$$[].
118 |
119 |
120 | ==== 联系伍德博士
121 |
122 | 你可以在他的个人网站上联系Gavin Wood博士:
123 | link:$$http://gavwood.com/$$[]
124 |
125 | 在推特上关注Gavin:
126 | link:$$https://twitter.com/gavofyork$$[]
127 |
128 | Gavin通常在Riot.im的Polkadot Watercooler中浏览:
129 | link:$$http://bit.ly/2xciG68$$[]
130 |
131 |
132 | [[acknowledgments_sec]]
133 | === Andreas的致谢
134 |
135 | 我对文字和书籍的热爱归功于我的母亲特蕾莎(Theresa)。在她抚养我长大的房子里,每一堵墙上都摆满了书。尽管我母亲自称有技术恐惧症,她依然在1982年给我买了我的第一台计算机。我的父亲Menelaos是一位土木工程师,他80岁时出版了第一本书,是一位教我逻辑和分析思维,以及培养我对科学和工程学的热爱的人。
136 |
137 | 谢谢大家在整个写在过程中对我的支持。
138 |
139 | === Gavin的致谢
140 |
141 | 我9岁那年,母亲从邻居那里为我购买了我的第一台计算机。没有它,我的技术进步无疑会受到削弱。我还欠她儿时对电的恐惧,必须感谢特雷弗(Trevor)和我的祖父母,他们一次又一次地履行了“看着我把它插上电源”的重任。而且没有他们,计算机将毫无用处。我还必须感谢我一生中拥有的各种教育者,邻居Sean先生(他教我的第一个计算机程序)到我的小学老师Quinn先生,将我对历史的兴趣转移到了编程上面,而我的中学老师们,像Richard Furlong-Brown先生,则使得我把兴趣从橄榄球转移到了编程。
142 |
143 | 我必须感谢我的孩子的母亲Jutta的一贯支持,以及我一生中的许多新老朋友,使我一直保持理智。最后,必须向Aeron Buchanan表示巨大的感谢,没有他,我最近这五年就不可能如此顺利,没有他的时间,支持和指导,本书不可能写的这么好。
144 |
145 |
146 | include::github_contrib.asciidoc[]
147 |
148 | === 资料来源
149 |
150 | 本书引用了各种公开和具有开放版权的资料:
151 |
152 | https://github.com/ethereum/vyper/blob/master/README.md::
153 | The MIT License (MIT)
154 |
155 |
156 | https://vyper.readthedocs.io/en/latest/::
157 | The MIT License (MIT)
158 |
159 |
160 | https://solidity.readthedocs.io/en/v0.4.21/common-patterns.html::
161 | The MIT License (MIT)
162 |
163 | https://arxiv.org/pdf/1802.06038.pdf::
164 | Arxiv Non-Exclusive-Distribution
165 |
166 | https://github.com/ethereum/solidity/blob/release/docs/contracts.rst#inheritance::
167 | The MIT License (MIT)
168 |
169 | https://github.com/trailofbits/evm-opcodes::
170 | Apache 2.0
171 |
172 | https://github.com/ethereum/EIPs/::
173 | Creative Commons CC0
174 |
175 |
176 | https://blog.sigmaprime.io/solidity-security.html::
177 | Creative Commons CC BY 4.0
--------------------------------------------------------------------------------
/appdx-standards-eip-erc_cn.asciidoc:
--------------------------------------------------------------------------------
1 | [appendix]
2 | [[ethereum_standards]]
3 | == 以太坊标准
4 |
5 | [[eips]]
6 | === 以太坊改进提案(EIP)
7 |
8 | ((("EIPs (Ethereum Improvement Proposals)")))((("Ethereum (generally)","EIPs")))((("Ethereum (generally)","standards")))以太坊改进提案的文件存在 https://github.com/ethereum/EIPs/[]. ((("EIPs (Ethereum Improvement Proposals)","workflow")))工作流程图在<>.
9 |
10 | 来自 https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1.md[EIP-1]:
11 |
12 | ____
13 | EIP是以太坊改进提案的缩写。 EIP是一个设计文档,可以向以太坊社区提供信息,内容包括描述一个以太坊的新功能,新功能的流程或环境。 EIP应该提供该功能的简要技术规范以及该功能的原理。 EIP作者负责在社区内建立共识并记录不同意见。
14 | ____
15 |
16 | [[eip_workflow]]
17 | .以太坊改善提案工作流程
18 | image::{abspath}images/eip_workflow.png["以太坊改进提案工作流程"]
19 |
20 | [[eip_table]]
21 | === 最重要的EIP和ERC列表
22 |
23 | .重要的EIP和ERC
24 | [options="header"]
25 | |===
26 | | EIP/ERC# | 标题/说明 | 作者 | 层 | 现状 | 创建版本
27 | | http://bit.ly/2OVq6qa[EIP-1] | EIP目的和准则 | Martin Becze,Hudson Jameson |注解|定稿|
28 | | http://bit.ly/2yJtTNa[EIP-2] |家园版本硬分叉的变化 | Vitalik Buterin |核心|定稿|
29 |
30 | | http://bit.ly/2Jrx93V[EIP-5] | RETURN和CALL的gas使用量| Christian Reitwiessner |核心|草稿|
31 | | http://bit.ly/2OYbc2t[EIP-6] |重命名 +SUICIDE+ 操作码|Hudson Jameson|界面 | 定稿|
32 | | http://bit.ly/2JxdBeN[EIP-7] | `DELEGATECALL` | Vitalik Buterin |核心|定稿|
33 | | http://bit.ly/2Q6Oly6[EIP-8] | devp2p 家园版本的向前兼容性要求|Felix Lange |网络|定稿|
34 | | http://bit.ly/2CUf7WG[EIP-20] | ERC-20通证标准。描述了通证合同可能实现的标准功能,以允许DApp和钱包跨多个接口/ DApp处理通证。方法包括:`totalSupply`,+ balanceOf(address)+,`transfer`,`transferFrom`,`approve`,`allowance`。事件包括:“ Transfer”(在通证传输时触发), pass:[ Approval ](在调用“ approve”时触发)。 | Fabian Vogelsteller,Vitalik Buterin | ERC |定稿|边境版本
35 | | http://bit.ly/2Q6R4YB[EIP-55] |混合大小写校验和地址编码| Vitalik Buterin | ERC |定稿|
36 | | http://bit.ly/2OgE5la[EIP-86] |交易来源和签名的抽象。为“抽象”帐户安全性和允许用户创建“帐户合约”奠定基础,朝着一个模型发展。在该模型中,所有帐户都是可以支付燃料gas费用的合约,用户可以自定义自己的安全模型,用于执行任何所需的签名验证和随机数检查(而不是使用协议内机制,其中ECDSA和默认随机数方案是保护帐户的唯一“标准”方式,当前已硬编码到交易处理中)。 | Vitalik Buterin |核心|递延(将被替换)|君士坦丁堡
37 | | http://bit.ly/2QedSFC[EIP-96] | Blockhash和状态根更改。在状态中存储区块哈希散列值以减少处理“ BLOCKHASH”操作码时协议的复杂性和客户端的复杂实现。扩展了向后扩展块哈希检查的范围,其副作用是在区块编号非常远的区块之间创建直接链接,以促进更高效的初始轻节点同步。 | Vitalik Buterin |核心|推迟|君士坦丁堡
38 | | http://bit.ly/2AC05DM[EIP-100] |将难度调整更改为目标平均出块时间,包括叔块。 | Vitalik Buterin |核心|定稿|大都会拜占庭
39 | | http://bit.ly/2Jr1zDv[EIP-101] |宁静版本中的加密货币和加密抽象。以太坊可以将以太坊和子代币进行类似的处理,从而将以太坊抽象化,进而降低定制策略账户(例如多重签名)所需的间接级别,并通过降低最小共识实现的复杂性来净化底层的以太坊协议。 | Vitalik Buterin |活跃|宁静功能|宁静Casper版本
40 | | http://bit.ly/2Q5sdEv[EIP-105] |二进制分片加合约调用语义。 “分片架构” EIP允许使用二叉树分片机制对以太坊事务进行并行化处理,并为以后的分片方案奠定基础。研究正在进行中;参见 https://github.com/ethereum/sharding[]。 | Vitalik Buterin |活跃|宁静功能|宁静Casper版本
41 | | http://bit.ly/2yG2Dzi[EIP-137] |以太坊域名服务-规范|Nick Johnson | ERC |定稿|
42 | | http://bit.ly/2yJtWZm[EIP-140] |新操作码: +REVERT+ 。添加`REVERT`操作码指令,该指令将停止执行并回滚EVM执行状态的变动,而不会消耗所有提供的燃料gas(相反,合约仅需支付内存)或丢失日志,并向调用方返回指向内存位置的指针,并带有错误代码或消息。 | Alex Beregszaszi,Nikolai Mushegian |核心|定稿|大都会拜占庭版本
43 | | http://bit.ly/2CQMXfe[EIP-141] |指定的无效EVM指令| Alex Beregszaszi |核心|定稿|
44 | | http://bit.ly/2qhKz9Y[EIP-145] | EVM中的按位移位指令 | Alex Beregszaszi,PawełBylica |核心|推迟|
45 | | http://bit.ly/2qhxflQ[EIP-150] | 对IO操作过多的gas成本变化| Vitalik Buterin |核心|定稿|
46 | | http://bit.ly/2CQUgne[EIP-155] |简单的重放攻击防护。重放攻击允许使用EIP-155之前的以太坊节点或客户端进行的任何交易都经过签名,以使其有效并同时在以太坊和以太坊经典链上执行。 | Vitalik Buterin |核心|定稿|家园版本
47 | | http://bit.ly/2JryBmT[EIP-158] |状态结算| Vitalik Buterin |核心|取消|
48 | | http://bit.ly/2CR6VGY[EIP-160] | EXP操作费用增加| Vitalik Buterin |核心|定稿|
49 | | http://bit.ly/2OfU96M[EIP-161] |状态Trie清除(保持不变的替代方法)|Gavin Wood |核心|定稿|
50 | | http://bit.ly/2JxdKil[EIP-162] | ENS哈希初始注册器|Maurelian, Nick Johnson, Alex Van de Sande | ERC |定稿|
51 |
52 | | http://bit.ly/2OgsOkO[EIP-165] | ERC-165标准接口检测|Christian Reitwiessner et al. |界面|草稿|
53 | | http://bit.ly/2OgCWu1[EIP-170] |合约代码大小限制| Vitalik Buterin |核心|定稿|
54 | | http://bit.ly/2ERNv7g[EIP-181] | ENS支持以太坊地址的反向解析|Nick Johnson | ERC |定稿|
55 | | http://bit.ly/2P0wPz5[EIP-190] |以太坊智能合约包装标准| Piper Merriam等。 | ERC |定稿|
56 | | http://bit.ly/2SwNQiz[EIP-196] |椭圆曲线 +alt_bn128+ 上用于加法和标量乘法的预编译合同。此操作是为了在区块gas限制内执行zkSNARK验证所必需的。
57 | |Christian Reitwiessner |核心|定稿|大都会拜占庭
58 | | http://bit.ly/2ETDC9a[EIP-197] |预编译合约,用于在椭圆曲线 +alt_bn128+ 上进行最佳的食物配对检查。与EIP-196结合。
59 | | Vitalik Buterin,Christian Reitwiessner|核心|定稿|大都会拜占庭
60 | | http://bit.ly/2DdTCRN[EIP-198] |大整数模幂。预编译后可使用RSA签名验证和其他加密应用程序。
61 | | Vitalik Buterin |核心|定稿|大都会拜占庭
62 | | http://bit.ly/2qjYJr3[EIP-211] |新的操作码:RETURNDATASIZE和RETURNDATACOPY。增加了对在EVM中返回可变长度值的支持,并具有简单的增加燃料gas的功能,并使用新的操作码RETURNDATASIZE和RETURNDATACOPY对调用操作码进行了最小的更改。处理类似于现有的“ calldata”,即在调用之后,返回数据将保留在虚拟缓冲区内,调用者可以从该缓冲区中将其(或其部分)复制到内存中,并在下一次调用时覆盖该缓冲区。
63 | |Christian Reitwiessner |核心|定稿|大都会拜占庭
64 | | http://bit.ly/2OgV0Eb[EIP-214] |新的操作码:`STATICCALL`。允许对自身或其他合约进行无状态更改的调用,同时不允许在调用过程中(及其子调用,如果存在)对状态进行任何修改,以提高智能合约的安全性,并确保开发人员调用不会产生重入错误。调用将STATIC标志设置为true的子合约以执行子合约,导致在STATIC为true的执行实例中进行状态更改操作的任何尝试均引发异常,并在调用后重置标志返回。 | Vitalik Buterin,, Christian Reitwiessner|核心|定稿|大都会拜占庭版本
65 | | http://bit.ly/2JssHlJ[EIP-225] | Rinkeby测试网使用授权证明PoA,其中仅由受信任的签名者开采区块。 | PéterSzilágyi| | |家园版本
66 | | http://bit.ly/2yPBavd[EIP-234] |将`blockHash`添加到JSON-RPC过滤器选项| Micah Zoltu |界面 | 草稿|
67 |
68 | | http://bit.ly/2yKrBNM[EIP-615] | EVM的子例程和静态跳转 | Greg Colvin,PawełBylica,Christian Reitwiessner |核心|草稿|
69 |
70 | | http://bit.ly/2AzGX99[EIP-616] | EVM的SIMD操作|Greg Colvin |核心|草稿|
71 |
72 | | http://bit.ly/2qjYX1n[EIP-681] |交易请求的URL格式| Daniel A. Nagy |界面|草稿|
73 |
74 | | http://bit.ly/2OYgE5n[EIP-649] |都市难度炸弹延迟和出块奖励减少。将冰河世纪(又名难度炸弹)延迟1年,并将出块奖励从5个以太币降低至3个以太币。 | Afri Schoedon,Vitalik Buterin |核心|定稿|大都会拜占庭
75 | | http://bit.ly/2RoGCvH[EIP-658] |将交易状态代码嵌入交易收据中。将指示成功或失败状态的状态字段获取并嵌入到交易发起者的交易收据中,因为在EIP-140中引入“ REVERT”操作码后,再也无法假定消耗了所有燃料gas后,交易就会失败。
76 | |Nick Johnson|核心|定稿|大都会拜占庭
77 | | http://bit.ly/2Ogwpzs[EIP-706] | DEVp2p快速压缩| PéterSzilágyi|网络|定稿|
78 | | http://bit.ly/2AAkCIP[EIP-721] | ERC-721不可替代通证标准。一种标准API,允许智能合约作为唯一的可交易不可交易通证(NFT)进行操作,可以在标准钱包中进行跟踪,并在交易所作为有价资产进行交易,类似于ERC20。 CryptoKitties是在以太坊生态系统中第一个被广泛采用的数字NFT实现。 | William Entriken,Dieter Shirley,Jacob Evans,Nastassia Sachs |标准|草稿|
79 | | http://bit.ly/2qmuDmJ[EIP-758] |对于已经完成的交易的订阅和过滤服务|Jack Peterson|界面|草稿|
80 | | http://bit.ly/2RnqlHy[EIP-801] | ERC-801 Canary 标准| ligi |界面|草稿|
81 | | http://bit.ly/2DdTKkf[EIP-827] | ERC827通证标准。通证的标准接口ERC20的扩展,其方法允许执行 +transfer+ 和批准内的调用。该标准提供了传输通证的基本功能,并允许通证被批准,以便其他链上第三方可以使用它们。此外,它还允许开发人员执行对转移和批准的调用。 |Augusto Lemble | ERC |草稿|
82 | | http://bit.ly/2Jq2hAM[EIP-930] | ERC930永久存储。 ES(外部存储)合约由具有写入许可权的地址拥有。存储是公共的,这意味着每个人都有读取权限。它将数据存储在映射中,每种类型的变量使用一个映射。使用此合约,开发人员可以根据需要轻松地将存储迁移到另一个合约。 |Augusto Lemble| ERC |草稿|
83 | |===
--------------------------------------------------------------------------------
/appdx-web3js-tutorial_cn.asciidoc:
--------------------------------------------------------------------------------
1 | [appendix]
2 | [[web3js_tutorial]]
3 | == web3.js教程
4 |
5 | === 说明
6 | ((("web3.js","tutorial", id="ix_appdx-web3js-tutorial-asciidoc0", range="startofrange")))本教程基于web3@1.0.0-beta.29 web3.js 。作为对web3.js的一个介绍教程。
7 |
8 | web3.js JavaScript软件库是一个模块集合,这些模块包含针对以太坊生态系统的特定功能,以及实现通用JSON RPC规范的与以太坊兼容的JavaScript API。
9 |
10 | 要运行此脚本,您无需运行自己的本地节点,可以使用 https://infura.io[Infura services]。
11 |
12 | === web3.js以非阻塞(异步)方式进行合同基本操作
13 |
14 | ((("web3.js","contract basic interaction in nonblocked (Async) fashion")))检查你是否安装有效的 +npm+ 版本:
15 |
16 | ++++
17 |
18 | $ npm -v
19 | 5.6.0
20 |
21 | ++++
22 |
23 | 如果还没有,请初始化 +npm+ :
24 |
25 | ++++
26 |
27 | $ npm init
28 |
29 | ++++
30 |
31 | 安装基本的软件配置库:
32 |
33 | ++++
34 |
35 | $ npm i command-line-args
36 | $ npm i web3
37 | $ npm i node-rest-client-promise
38 |
39 | ++++
40 |
41 | 这将把新的软件配置项更新到 _package.json_ 配置文件中。
42 |
43 | ==== Node.js脚本的执行
44 |
45 | ((("web3.js","node.js script execution")))基本执行:
46 |
47 | ++++
48 |
49 | $ node code/web3js/web3-contract-basic-interaction.js
50 |
51 | ++++
52 |
53 | 使用您自己的Infura令牌(在 https://infura.io/[]注册,并将api-key存储在名为__infura_token__的本地文件中):
54 |
55 | ++++
56 |
57 | $ node code/web3js/web3-contract-basic-interaction.js \
58 | --infuraFileToken /path/to/file/with/infura_token
59 |
60 | ++++
61 |
62 | 或者:
63 |
64 | ++++
65 |
66 | $ node code/web3js/web3-contract-basic-interaction.js \
67 | /path/to/file/with/infura_token
68 |
69 | ++++
70 |
71 | 这将使用你自己的令牌读取文件,并将其作为命令行参数传递给实际命令。
72 |
73 | === 查看演示脚本
74 |
75 | ((("web3.js","reviewing demo script")))接下来,让我们审查我们的演示脚本 _web3-contract-basic-interaction_。
76 |
77 | 我们使用 +Web3+ 对象创建一个基本的web3服务提供对象:
78 |
79 | [source,solidity]
80 | ----
81 | var web3 = new Web3(infura_host);
82 | ----
83 |
84 | 然后,我们可以与web3通讯并尝试一些基本功能。让我们看看协议版本:
85 |
86 | [source,solidity]
87 | ----
88 | web3.eth.getProtocolVersion().then(function(protocolVersion) {
89 | console.log(`Protocol Version: ${protocolVersion}`);
90 | })
91 | ----
92 |
93 | 现在让我们看一下当前的燃料gas价格:
94 |
95 | [source,solidity]
96 | ----
97 | web3.eth.getGasPrice().then(function(gasPrice) {
98 | console.log(`Gas Price: ${gasPrice}`);
99 | })
100 | ----
101 |
102 | 当前链中最后一个被开采的区块编号是什么?
103 |
104 | [source,solidity]
105 | ----
106 | web3.eth.getBlockNumber().then(function(blockNumber) {
107 | console.log(`Block Number: ${blockNumber}`);
108 | })
109 | ----
110 |
111 | === 合约的使用
112 |
113 | ((("web3.js","contract interaction", id="ix_appdx-web3js-tutorial-asciidoc1", range="startofrange")))现在让我们学习一些智能合约的基本使用方法。对于这些示例,我们将在Kovan测试网上使用 https://bit.ly/2MPZZLx[+WETH9_+ contract]。
114 |
115 | [role="pagebreak-before"]
116 | 首先,让我们初始化合约地址:
117 |
118 | [source,solidity]
119 | ----
120 | var our_contract_address = "0xd0A1E359811322d97991E03f863a0C30C2cF029C";
121 | ----
122 |
123 | 然后,我们可以查看其帐号余额:
124 |
125 | [source,solidity]
126 | ----
127 | web3.eth.getBalance(our_contract_address).then(function(balance) {
128 | console.log(`Balance of ${our_contract_address}: ${balance}`);
129 | })
130 | ----
131 |
132 | 并查看其二进制代码:
133 |
134 | [source,solidity]
135 | ----
136 | web3.eth.getCode(our_contract_address).then(function(code) {
137 | console.log(code);
138 | })
139 | ----
140 |
141 | 接下来,我们将准备与Etherscan Explorer API进行通讯的环境。
142 |
143 | 让我们在Evanscan Explorer API中为Kovan测试链初始化一个合约URL:
144 |
145 | [source,solidity]
146 | ----
147 | var etherscan_url =
148 | "https://kovan.etherscan.io/api?module=contract&action=getabi&
149 | address=${our_contract_address}"
150 | ----
151 |
152 | 让我们初始化一个REST客户端以与Etherscan API进行通讯:
153 |
154 | [source,solidity]
155 | ----
156 | var client = require('node-rest-client-promise').Client();
157 | ----
158 |
159 | 并得到客户端的promise对象:
160 |
161 | [source,solidity]
162 | ----
163 | client.getPromise(etherscan_url)
164 | ----
165 |
166 | 获得有效的客户端的promise后,我们可以从Etherscan API获得合约的ABI:
167 |
168 | [source,solidity]
169 | ----
170 | .then((client_promise) => {
171 | our_contract_abi = JSON.parse(client_promise.data.result);
172 | ----
173 |
174 | 现在,我们可以创建一个promise合约对象以便之后使用:
175 |
176 | [source,solidity]
177 | ----
178 | return new Promise((resolve, reject) => {
179 | var our_contract = new web3.eth.Contract(our_contract_abi,
180 | our_contract_address);
181 | try {
182 | // If all goes well
183 | resolve(our_contract);
184 | } catch (ex) {
185 | // If something goes wrong
186 | reject(ex);
187 | }
188 | });
189 | })
190 | ----
191 |
192 | 如果我们的合约的promise成功返回,我们可以开始调用它的函数:
193 |
194 | [source,solidity]
195 | ----
196 | .then((our_contract) => {
197 | ----
198 |
199 | 让我们看看我们合约的地址:
200 |
201 | [source,solidity]
202 | ----
203 | console.log(`Our Contract address:
204 | ${our_contract._address}`);
205 | ----
206 |
207 | 或者:
208 |
209 | [source,solidity]
210 | ----
211 | console.log(`Our Contract address in another way:
212 | ${our_contract.options.address}`);
213 | ----
214 |
215 | 现在让我们查询一下合约的ABI:
216 |
217 | [source,solidity]
218 | ----
219 | console.log("Our contract abi: " +
220 | JSON.stringify(our_contract.options.jsonInterface));
221 | ----
222 |
223 | 我们可以使用回调查看智能合约中的通证总量:
224 |
225 | [source,solidity]
226 | ----
227 | our_contract.methods.totalSupply().call(function(err, totalSupply) {
228 | if (!err) {
229 | console.log(`Total Supply with a callback: ${totalSupply}`);
230 | } else {
231 | console.log(err);
232 | }
233 | });
234 | ----
235 |
236 | 或者我们可以使用返回的Promise而不是传入回调函数:(((range="endofrange", startref="ix_appdx-web3js-tutorial-asciidoc1")))
237 |
238 | [source,solidity]
239 | ----
240 | our_contract.methods.totalSupply().call().then(function(totalSupply){
241 | console.log(`Total Supply with a promise: ${totalSupply}`);
242 | }).catch(function(err) {
243 | console.log(err);
244 | });
245 | ----
246 |
247 | === 使用Await命令完成的异步操作
248 |
249 | ((("await construct")))((("web3.js","asynchronous operation with await")))现在,你已经看过基本教程,可以使用异步 +await+ 结构尝试完成相同的操作。查看 http://bit.ly/2ABrFkl[_code/web3js_]中的_web3-contract-basic-interaction-async-await.js_脚本,并将其与本教程进行比较,以了解它们之间的区别。异步等待操作的命令更易于阅读,因为它使异步操作的行为更像是一系列阻塞调用。(((range="endofrange", startref="ix_appdx-web3js-tutorial-asciidoc0")))
--------------------------------------------------------------------------------
/contrib/aws-network-operation.asciidoc:
--------------------------------------------------------------------------------
1 | [[_anchor_operate_private_network]]
2 | == Operating a private Ethereum network
3 |
4 | Once the set-up for private network is completed, the network has the following nodes are launched:
5 |
6 | * Ethereum boot node for other machines to look up for peering.
7 | * Ethereum mining node that does mining.
8 | * Ethereum RPC node that exposes RPC port for programmatic access.
9 | * Ethereum stand alone node that does not mine or expose API.
10 |
11 | [NOTE]
12 | ====
13 | The remainder of this section will use peering of nodes using `bootnodes`.
14 | ====
15 |
16 | For a quick summary on launching a private network, see link:aws-networ-setup.asciidoc#Summary[AWS network set-up summary]. To learn more about setting up the network, see link:aws-network-setup.asciidoc[AWS network set-up].
17 |
18 | Now, the network is ready for deployment of smart contracts. The steps to be followed for deployment of contracts are as follows:
19 |
20 | . Account set-up <<_anchor_account_set_up>>
21 | . Deploy contract <<_anchor_deploy_contract>>
22 | . Interacting with the contract <<_anchor_interacting_with_the_contract>>
23 |
24 | [[_anchor_account_set_up]]
25 | === Account set-up
26 | While account could be set-up on any node, for this section, accounts will be created for mining node and RPC node to store the mining reward and end-point activities only. To create an account, log on to the mining node and run this command.
27 |
28 | [[_code_new_account]]
29 | .Account creation
30 | [source,bash]
31 | ----
32 | geth --datadir eth-priv account new // 1
33 | ----
34 | <1> Note the `datadir` flag; it indicates that, the account is for a private network. Note the generated address. Running this account will prompt for password.
35 |
36 | [NOTE]
37 | ====
38 | *There is no 'Forgot password' option for your account. Therefore, keep your password at a safe place!*
39 | ====
40 |
41 |
42 | [[_anchor_deploy_contract]]
43 | === Deploy contract
44 |
45 | [TIP]
46 | ====
47 | This chapter uses `truffle` for contract development and deployment.
48 | ====
49 |
50 | For this section, we will deploy the `METoken` contract as described in the link:tokens.asciidoc[Tokens] section. Once the contract has been developed and compiled successfully, we will migrate to the private network. A quick introduction to set-up is provided here.
51 |
52 | . Install `truffle`, run `npm install -g truffle`.
53 | . Clone repository `https://github.com/chainhead/MET`
54 | . In the cloned repository, go to `MET/METtoken` and run `npm install` to install dependencies.
55 | . At `MET/METtoken`, run `truffle compile` to compile the contracts.
56 |
57 | To migrate the contract, `truffle` needs to know about the network. This information will be provided in the `truffle-config.js` configuration file. A sample file is provided link:../code/aws/truffle.js[here]. The information is provided via another network, with name as `aws`, added to the array of `networks` shown as an example below.
58 |
59 | [[_code_truffle_config_private_network]]
60 | .Truffle configuration
61 | [source,json]
62 | ----
63 | aws: { // Private network on AWS
64 | network_id: "15", // 1
65 | host: "IP address RPC node", // 2
66 | port: 8545, // 3
67 | gas: 6721975, // 4
68 | from : "0xaddresstopayforgas" // 5
69 | }
70 | ----
71 |
72 | <1> The `network_id` as defined in `genesis.json` document.
73 | <2> The public IP address of the EC2 instance node running `geth` with RPC node exposed.
74 | <3> The RPC port number of the EC2 instance hosting Ethereum RPC node. Default is `8545`.
75 | <4> Gas limit used for deploys. Default is `4712388`.
76 | <5> An account with sufficient ether to pay gas for contract interactions. This will be the address generated at <<_code_new_account>>.
77 |
78 | To deploy the contract with `truffle`, run the command below.
79 | [[_code_deploy_contract]]
80 | .Truffle network migration
81 | [source,bash]
82 | ----
83 | truffle migrate --network aws // 1
84 | Deploying Migrations...
85 | ... 0x3d04e043f82e323fb326a75f6da382e6687be1df4d00f026207f1b8e4d892fe8 // 2
86 |
87 | ----
88 |
89 | <1> The `--network` flag is set to the value of `aws` as defined in `truffle.js` file.
90 | <2> Output of deployment showing the address where the contrat was deployed.
91 |
92 | The contract creation can be seen on the mining node console output also as shown below.
93 | [[_code_deployment_output]]
94 | [source,bash]
95 | ----
96 | INFO [03-26|23:15:55] Submitted contract creation fullhash=0x3d04e043f82e323fb326a75f6da382e6687be1df4d00f026207f1b8e4d892fe8 contract=0xD33b0dCFFA52D2188E22BD01826d063265ec3e83
97 | ----
98 |
99 | [[_anchor_interacting_with_the_contract]]
100 | === Interacting with the contract
101 | To interact with the deployed contract, launch console as shown below. To learn more about the truffle console, see https://truffleframework.com/docs/getting_started/console[here].
102 |
103 | [[_code_launch_console]]
104 | [source,bash]
105 | ----
106 | truffle console --network aws // 1
107 | ----
108 |
109 | <1> The `--network` flag is set to the value of `aws` as defined in `truffle.js` file.
110 |
111 |
112 | ==== Use faucet
113 |
114 | ==== Buy MET
115 |
116 | [[_anchor_operation_summary]]
117 | == Summary
118 | To summarize working with private Ethereum network, here are the steps used:
119 |
120 | . Launch a private Ethereum network as described in link:aws-network-setup.asciidoc[AWS network set-up]
121 | . Once the nodes are launched and configured for genesis on each of the nodes, run the following commands on nodes.
122 |
123 | [[_table_command_summary]]
124 | .Ethereum nodes - Command summary
125 | |==================================================================================================================================
126 | | Node| Command | Remarks
127 | |Boot node | `bootnode --nodekey=bootnode.key` | Generate `bootnode.key` in advance. See <>
128 | |Standalone node | `geth --bootnodes 'enode://' --datadir eth-priv console` | Change `[::]` in `enode://` URI from `bootnode` output above with public IP address of the machine where `bootnode` is running.
129 | |RPC node | `geth --bootnodes 'enode://' --datadir eth-priv --rpc --rpcapi "web3,eth,personal" --rpcaddr "0.0.0.0" --rpccorsdomain "\*" console` | Opens RPC port for contract interaction. *NOTE* the values of `--rpcaddr "0.0.0.0" --rpccorsdomain "\*"` are discouraged!
130 | |Mining node | `geth --bootnodes 'enode://' --datadir eth-priv ---mine -rpc --rpcapi "web3,eth,personal" --rpcaddr "0.0.0.0" --rpccorsdomain "\*"` | Starts mining _and_ opens RPC port. An account should exist before running this command.
131 | |==================================================================================================================================
132 |
--------------------------------------------------------------------------------
/code/auction_dapp/backend/contracts/ERC721/ERC721Token.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.4.18;
2 |
3 | import "./ERC721.sol";
4 | import "./DeprecatedERC721.sol";
5 | import "./ERC721BasicToken.sol";
6 |
7 |
8 | /**
9 | * @title Full ERC721 Token
10 | * This implementation includes all the required and some optional functionality of the ERC721 standard
11 | * Moreover, it includes approve all functionality using operator terminology
12 | * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
13 | */
14 | contract ERC721Token is ERC721, ERC721BasicToken {
15 | // Token name
16 | string internal name_;
17 |
18 | // Token symbol
19 | string internal symbol_;
20 |
21 | // Mapping from owner to list of owned token IDs
22 | mapping (address => uint256[]) internal ownedTokens;
23 |
24 | // Mapping from token ID to index of the owner tokens list
25 | mapping(uint256 => uint256) internal ownedTokensIndex;
26 |
27 | // Array with all token ids, used for enumeration
28 | uint256[] internal allTokens;
29 |
30 | // Mapping from token id to position in the allTokens array
31 | mapping(uint256 => uint256) internal allTokensIndex;
32 |
33 | // Optional mapping for token URIs
34 | mapping(uint256 => string) internal tokenURIs;
35 |
36 | /**
37 | * @dev Constructor function
38 | */
39 | function ERC721Token(string _name, string _symbol) public {
40 | name_ = _name;
41 | symbol_ = _symbol;
42 | }
43 |
44 | /**
45 | * @dev Gets the token name
46 | * @return string representing the token name
47 | */
48 | function name() public view returns (string) {
49 | return name_;
50 | }
51 |
52 | /**
53 | * @dev Gets the token symbol
54 | * @return string representing the token symbol
55 | */
56 | function symbol() public view returns (string) {
57 | return symbol_;
58 | }
59 |
60 | /**
61 | * @dev Returns an URI for a given token ID
62 | * @dev Throws if the token ID does not exist. May return an empty string.
63 | * @param _tokenId uint256 ID of the token to query
64 | */
65 | function tokenURI(uint256 _tokenId) public view returns (string) {
66 | require(exists(_tokenId));
67 | return tokenURIs[_tokenId];
68 | }
69 |
70 | /**
71 | * @dev Gets the token ID at a given index of the tokens list of the requested owner
72 | * @param _owner address owning the tokens list to be accessed
73 | * @param _index uint256 representing the index to be accessed of the requested tokens list
74 | * @return uint256 token ID at the given index of the tokens list owned by the requested address
75 | */
76 | function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256) {
77 | require(_index < balanceOf(_owner));
78 | return ownedTokens[_owner][_index];
79 | }
80 |
81 | /**
82 | * @dev Gets the total amount of tokens stored by the contract
83 | * @return uint256 representing the total amount of tokens
84 | */
85 | function totalSupply() public view returns (uint256) {
86 | return allTokens.length;
87 | }
88 |
89 | /**
90 | * @dev Gets the token ID at a given index of all the tokens in this contract
91 | * @dev Reverts if the index is greater or equal to the total number of tokens
92 | * @param _index uint256 representing the index to be accessed of the tokens list
93 | * @return uint256 token ID at the given index of the tokens list
94 | */
95 | function tokenByIndex(uint256 _index) public view returns (uint256) {
96 | require(_index < totalSupply());
97 | return allTokens[_index];
98 | }
99 |
100 | /**
101 | * @dev Internal function to set the token URI for a given token
102 | * @dev Reverts if the token ID does not exist
103 | * @param _tokenId uint256 ID of the token to set its URI
104 | * @param _uri string URI to assign
105 | */
106 | function _setTokenURI(uint256 _tokenId, string _uri) internal {
107 | require(exists(_tokenId));
108 | tokenURIs[_tokenId] = _uri;
109 | }
110 |
111 | /**
112 | * @dev Internal function to add a token ID to the list of a given address
113 | * @param _to address representing the new owner of the given token ID
114 | * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
115 | */
116 | function addTokenTo(address _to, uint256 _tokenId) internal {
117 | super.addTokenTo(_to, _tokenId);
118 | uint256 length = ownedTokens[_to].length;
119 | ownedTokens[_to].push(_tokenId);
120 | ownedTokensIndex[_tokenId] = length;
121 | }
122 |
123 | /**
124 | * @dev Internal function to remove a token ID from the list of a given address
125 | * @param _from address representing the previous owner of the given token ID
126 | * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
127 | */
128 | function removeTokenFrom(address _from, uint256 _tokenId) internal {
129 | super.removeTokenFrom(_from, _tokenId);
130 |
131 | uint256 tokenIndex = ownedTokensIndex[_tokenId];
132 | uint256 lastTokenIndex = ownedTokens[_from].length.sub(1);
133 | uint256 lastToken = ownedTokens[_from][lastTokenIndex];
134 |
135 | ownedTokens[_from][tokenIndex] = lastToken;
136 | ownedTokens[_from][lastTokenIndex] = 0;
137 | // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to
138 | // be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping
139 | // the lastToken to the first position, and then dropping the element placed in the last position of the list
140 |
141 | ownedTokens[_from].length--;
142 | ownedTokensIndex[_tokenId] = 0;
143 | ownedTokensIndex[lastToken] = tokenIndex;
144 | }
145 |
146 | /**
147 | * @dev Internal function to mint a new token
148 | * @dev Reverts if the given token ID already exists
149 | * @param _to address the beneficiary that will own the minted token
150 | * @param _tokenId uint256 ID of the token to be minted by the msg.sender
151 | */
152 | function _mint(address _to, uint256 _tokenId) internal {
153 | super._mint(_to, _tokenId);
154 |
155 | allTokensIndex[_tokenId] = allTokens.length;
156 | allTokens.push(_tokenId);
157 | }
158 |
159 | /**
160 | * @dev Internal function to burn a specific token
161 | * @dev Reverts if the token does not exist
162 | * @param _owner owner of the token to burn
163 | * @param _tokenId uint256 ID of the token being burned by the msg.sender
164 | */
165 | function _burn(address _owner, uint256 _tokenId) internal {
166 | super._burn(_owner, _tokenId);
167 |
168 | // Clear metadata (if any)
169 | if (bytes(tokenURIs[_tokenId]).length != 0) {
170 | delete tokenURIs[_tokenId];
171 | }
172 |
173 | // Reorg all tokens array
174 | uint256 tokenIndex = allTokensIndex[_tokenId];
175 | uint256 lastTokenIndex = allTokens.length.sub(1);
176 | uint256 lastToken = allTokens[lastTokenIndex];
177 |
178 | allTokens[tokenIndex] = lastToken;
179 | allTokens[lastTokenIndex] = 0;
180 |
181 | allTokens.length--;
182 | allTokensIndex[_tokenId] = 0;
183 | allTokensIndex[lastToken] = tokenIndex;
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------