Introduction to Ethereum - Part 4
Bhaskar S | 01/05/2018 |
Overview
In this article, we finally put together a decent Smart Contract to demonstrate the simple vehicle buying use-case (involving the buyer, the dealer, and the dmv) that we laid out in our first introductory article Introduction to Blockchain.
The following are the aspects involved in demonstrating our use-case:
For this demonstration, the cost of the vehicle is assumed to be 4000000000000000000 wei's (or 4 ethers). This is the amount owed to the dealer by the buyer
Also, the processing fees to register the vehicle for getting a license number is assumed to be 1000000000000000000 wei's (or 1 ether). This is the amount owed to the motor vehicle agency (dmv) by the buyer
The dmv will deploy a Smart Contract that registers a new vehicle and assign a license number once the processing fees is paid
When a buyer expresses an intent to buy a vehicle, the dealer will create a Smart Contract representing a deal with the buyer for the desired vehicle (vin) at a particular cost plus some processing fees
When the buyer initiates a transaction by making a payment on the contract deployed by the dealer, the logic in the invoked method pays the dealer the cost of the vehicle, and then automatically initiates a transaction on the contract deployed by the dmv to register the vehicle (after paying the processing fees)
Hands-on with Smart Contracts using Solidity
In the previous article Part 3 of this series, we introduced the concept of defining multiple contract(s) in a single .sol file, as well as the use of a modifier contract to enforce constraint check(s) prior to executing a function.
Since we need to ensure the buyer has included enough ethers to cover for the cost of the vehicle as well as the processing fees, we will extract the modifier contract into a separate .sol file, so that it can be commonly applied to any Smart Contract (either from the dmv or the dealer).
The following is the extracted and enhanced Solidity contract code called AmountOwed2.sol located in the directory /home/polarsparc/Ethereum/src:
Since the Smart Contract deployed by the dealer (vehicle purchase) needs to interact with the Smart Contract deployed by the dmv (for vehicle registration), we will create an abstract contract defining the interface of the dmv contract. An abstract contract is a Solidty contract that defines the functions without any implementation details. This is similar to interfaces in commonly used object-oriented programming languages like Java, C++, etc.
The following is the abstract Solidity contract code for the dmv called IDmvRegister.sol located in the directory /home/polarsparc/Ethereum/src:
The following is the concrete Solidity contract code for the dmv called DmvRegister.sol located in the directory /home/polarsparc/Ethereum/src:
Let us explain some of the important keywords used in the DmvRegister.sol file shown above.
The keyword import followed by a path to a .sol file includes the contents of the specified file into the current scope. This is similar to the import statement in Javascript.
The keyword struct is used to define a complex data type, similar to the one from the C programming language. In our use-case, we define a custom data type called OwnerLicense to encapsulate a boolean flag indicating if the vehicle is registered, the license number and the owner of the vehicle.
The contract DmvRegister supports multiple inheritence by implementing one interface IDmvRegister and extending a contract AmountOwed2.
The keyword mapping is used to define a data structure that is similar to a hash-table from the Java programming language. The left-hand side of symbol => defines the type of the key, while the right-hand side defines the type of the value. In our use-case, the key is of type uint representing the vin number and the value is of type OwnerLicense. One important difference compared to a hash-table in Java is that every key value exists and is initialized to the default value of the value type. For example, for a new key with value 1111, the corresponding mapped value would be a default value of OwnerLicense with a false for registered, zero for license, and 0x0 for owner. In other words, the mapped value will never be null like in Java.
The method transfer on an address transfers the specified value to the balance on the invoked address. In our use-case, we are transferring the processing fees to the dmv.
An instance of the contract DmvRegister will be deployed by the dmv, such that the dealer contract can transfer ethers on behalf of the buyer to fulfill the processing fees of registering the vehicle by invoking the method registerVehicle().
The following is the concrete Solidity contract code for the dealer called Vehicle3.sol located in the directory /home/polarsparc/Ethereum/src:
The method value on a payable function of a contract allows one to transfer some ethers to the balance of the contract address.
Similarly, the method gas on a payable function of a contract allows one to pay for the gas used in processing of that function.
As is evident from the contract code above, one can chain the methods value and gas when invoking the payable function registerVehicle on the dmv contract. Also, notice the arguments for the invoked function come at the last in the chain.
In the constructor of the dealer contract Vehicle3, an instance of the dmv contract object is created by passing the contract address of the dmv contract to the abstract contract interface IDmvRegister.
An instance of the contract Vehicle3 will be deployed by the dealer when the buyer intends to buy a vehicle at a certain price (includes the cost of the vehicle plus the cost of processing the registration of the vehicle with the dmv). When the buyer sends a transaction message (with the payment in ethers) to the payable method buyVehicle(), the contract is executed and the deal is closed. This encompasses registering the vehicle with the dmv.
For convenience, we have enhanced the custom Javascript utility script with some helper variable(s) and a function to extract and display information on account balances. The following is the custom Javascript script called UtilScripts.js located in the directory /home/polarsparc/Ethereum/bin:
The following are the steps to demonstrate the simple vehicle buying use-case (involving a buyer, a dealer, and the dmv):
Step - 01 |
Compile DmvRegister.sol using the Solidity compiler to generate a Javascript file (with .js file extension) with both the abi as well as the bytecode by executing the following command:
$ echo "var dmvregister=`solc --optimize --combined-json abi,bin,interface src/DmvRegister.sol`" > bin/DmvRegister.js
The above command will generate the desired Javascript file called DmvRegister.js located in directory /home/polarsparc/Ethereum/bin encoded as JSON.
Step - 02 |
Compile Vehicle3.sol using the Solidity compiler to generate a Javascript file (with .js file extension) with both the abi as well as the bytecode by executing the following command:
$ echo "var vehicle3=`solc --optimize --combined-json abi,bin,interface src/Vehicle3.sol`" > bin/Vehicle3.js
The above command will generate the desired Javascript file called Vehicle3.js located in directory /home/polarsparc/Ethereum/bin encoded as JSON.
Step - 03 |
Load the three Javascript files UtilScripts.js, DmvRegister.js and Vehicle3.js by executing the following commands one at a time in the Javascript shell prompt:
> loadScript("./bin/UtilScripts.js")
> loadScript("./bin/DmvRegister.js")
> loadScript("./bin/Vehicle3.js")
Step - 04 |
Check to ensure the variable dmvregister is initialized by executing the following command in the Javascript shell prompt:
> dmvregister
The following would be the typical output:
{ contracts: { src/AmountOwed2.sol:AmountOwed2: { abi: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"flag\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"context\",\"type\":\"address\"}],\"name\":\"AmountEvt\",\"type\":\"event\"}]", bin: "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00a165627a7a723058201ad282abd92f245df43f5c30716a945b232176ef484eb7ae18c8a01395dd33160029" }, src/DmvRegister.sol:DmvRegister: { abi: "[{\"constant\":true,\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"}],\"name\":\"getLicense\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"},{\"name\":\"buyer\",\"type\":\"address\"}],\"name\":\"registerVehicle\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getFees\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"fees\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"flag\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"vin\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"license\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"fees\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"buyer\",\"type\":\"address\"}],\"name\":\"RegisteredEvt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"flag\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"context\",\"type\":\"address\"}],\"name\":\"AmountEvt\",\"type\":\"event\"}]", bin: "6060604052341561000f57600080fd5b6040516020806104b18339810160405280805160656000908155600182905560028054600160a060020a03191633600160a060020a03161790559092507fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e691508080848160405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a1506103f6806100bb6000396000f3006060604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b2dd1212811461005b578063cca10a2114610083578063db8d55f11461009c575b600080fd5b341561006657600080fd5b6100716004356100af565b60405190815260200160405180910390f35b61009a600435600160a060020a03602435166100c4565b005b34156100a757600080fd5b6100716103c4565b60009081526003602052604090206001015490565b60018054600254600092600160a060020a03909116907fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c903484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1348290101561014057600080fd5b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60023484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16000858152600360205260409020805490935060ff161515610300577fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e66001868560010154348860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a16002838101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038781169190911790915560008054600180880191909155865460ff19168117875581548101909155915491549116906108fc81150290604051600060405180830381858888f19350505050151561029457600080fd5b7fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e6600286856001015460015434038860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a1610364565b7fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e66003868560010154348860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a15b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60033484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a15050505050565b600154905600a165627a7a72305820fbca4691cd855134e337de1865b5bb119ca255ace4c88782cc2c65f85552c9820029" }, src/IDmvRegister.sol:IDmvRegister: { abi: "[{\"constant\":true,\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"}],\"name\":\"getLicense\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"},{\"name\":\"buyer\",\"type\":\"address\"}],\"name\":\"registerVehicle\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getFees\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", bin: "" } }, version: "0.4.19+commit.c4cbbb05.Linux.g++" }
Step - 05 |
Create a contract object called dmvregister_contract by executing the following command in the Javascript shell prompt:
> var dmvregister_contract = eth.contract(JSON.parse(dmvregister.contracts['src/DmvRegister.sol:DmvRegister'].abi))
Check to ensure the variable dmvregister_contract is initialized by executing the following command in the Javascript shell prompt:
> dmvregister_contract
The following would be the typical output:
{ abi: [{ constant: true, inputs: [{...}], name: "getLicense", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [{...}, {...}], name: "registerVehicle", outputs: [], payable: true, stateMutability: "payable", type: "function" }, { constant: true, inputs: [], name: "getFees", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { inputs: [{...}], payable: false, stateMutability: "nonpayable", type: "constructor" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}, {...}], name: "RegisteredEvt", type: "event" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "AmountEvt", type: "event" }], eth: { accounts: ["0xef17ec5df3116dea3b7abaf1ff3045639453cc76", "0x35ddac855e0029676f489dafca9ab405a348317c", "0x46bf8994c8702919434271d89bcad8abec915612", "0x518a6377a3863201aef3310da41f3448d959a310"], blockNumber: 0, coinbase: "0xef17ec5df3116dea3b7abaf1ff3045639453cc76", compile: { lll: function(), serpent: function(), solidity: function() }, defaultAccount: undefined, defaultBlock: "latest", gasPrice: 18000000000, hashrate: 0, mining: false, pendingTransactions: [], protocolVersion: "0x3f", syncing: false, call: function(), contract: function(abi), estimateGas: function(), filter: function(options, callback, filterCreationErrorCallback), getAccounts: function(callback), getBalance: function(), getBlock: function(), getBlockNumber: function(callback), getBlockTransactionCount: function(), getBlockUncleCount: function(), getCode: function(), getCoinbase: function(callback), getCompilers: function(), getGasPrice: function(callback), getHashrate: function(callback), getMining: function(callback), getPendingTransactions: function(callback), getProtocolVersion: function(callback), getRawTransaction: function(), getRawTransactionFromBlock: function(), getStorageAt: function(), getSyncing: function(callback), getTransaction: function(), getTransactionCount: function(), getTransactionFromBlock: function(), getTransactionReceipt: function(), getUncle: function(), getWork: function(), iban: function(iban), icapNamereg: function(), isSyncing: function(callback), namereg: function(), resend: function(), sendIBANTransaction: function(), sendRawTransaction: function(), sendTransaction: function(), sign: function(), signTransaction: function(), submitTransaction: function(), submitWork: function() }, at: function(address, callback), getData: function(), new: function() }
Step - 06 |
Create a variable called dmvregister_contract_txn to represent the contract transaction object, encapsulating the address of the dmv, the bytecode of the dmv contract, and a gas price. Execute the following expression in the Javascript shell as shown below:
> var dmvregister_contract_txn = { from: dmv, data: '0x'+dmvregister.contracts['src/DmvRegister.sol:DmvRegister'].bin, gas: gas }
Check to ensure the variable dmvregister_contract_txn is initialized by executing the following command in the Javascript shell prompt:
> dmvregister_contract_txn
The following would be the typical output:
{ data: "0x6060604052341561000f57600080fd5b6040516020806104b18339810160405280805160656000908155600182905560028054600160a060020a03191633600160a060020a03161790559092507fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e691508080848160405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a1506103f6806100bb6000396000f3006060604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b2dd1212811461005b578063cca10a2114610083578063db8d55f11461009c575b600080fd5b341561006657600080fd5b6100716004356100af565b60405190815260200160405180910390f35b61009a600435600160a060020a03602435166100c4565b005b34156100a757600080fd5b6100716103c4565b60009081526003602052604090206001015490565b60018054600254600092600160a060020a03909116907fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c903484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1348290101561014057600080fd5b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60023484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16000858152600360205260409020805490935060ff161515610300577fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e66001868560010154348860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a16002838101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038781169190911790915560008054600180880191909155865460ff19168117875581548101909155915491549116906108fc81150290604051600060405180830381858888f19350505050151561029457600080fd5b7fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e6600286856001015460015434038860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a1610364565b7fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e66003868560010154348860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a15b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60033484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a15050505050565b600154905600a165627a7a72305820fbca4691cd855134e337de1865b5bb119ca255ace4c88782cc2c65f85552c9820029", from: "0x518a6377a3863201aef3310da41f3448d959a310", gas: 1000000 }
Step - 07 |
Now we are ready to deploy our Smart Contract for the dmv called DmvRegister into our private Ethereum network.
Since the contract will be deployed by the dmv account, we need to unlock the dmv account before proceeding further.
To unlock the dmv account, execute the following command in the Javascript shell prompt:
> personal.unlockAccount(dmv)
This will prompt us for the password for the dmv account. The following would be the typical output:
Unlock account 0x518a6377a3863201aef3310da41f3448d959a310 Passphrase: dmv true
Create a contract instance object called dmvregister_contract_inst, by calling the new method on the contract object dmvregister_contract, passing a constructor argument for the processing fees (fees) and the contract transaction object dmvregister_contract_txn. Execute the following command in the Javascript shell prompt:
> var dmvregister_contract_inst = dmvregister_contract.new(fees, dmvregister_contract_txn)
Check to ensure the variable dmvregister_contract_inst is initialized by executing the following command in the Javascript shell prompt:
> dmvregister_contract_inst
The following would be the typical output:
{ abi: [{ constant: true, inputs: [{...}], name: "getLicense", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [{...}, {...}], name: "registerVehicle", outputs: [], payable: true, stateMutability: "payable", type: "function" }, { constant: true, inputs: [], name: "getFees", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { inputs: [{...}], payable: false, stateMutability: "nonpayable", type: "constructor" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}, {...}], name: "RegisteredEvt", type: "event" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "AmountEvt", type: "event" }], address: undefined, transactionHash: "0x67bb538323962381c32195c94d67f3d8a6c39caa074d12319e5dfb6ba4b79d42" }
Step - 08 |
The above contract instance creation command will generate an Ethereum transaction that needs to be mined for the contract to be deployed into the private Blockchain network.
To check all the pending transactions, execute the following command in the Javascript shell prompt:
> eth.pendingTransactions
The following would be the typical output:
[{ blockHash: null, blockNumber: null, from: "0x518a6377a3863201aef3310da41f3448d959a310", gas: 1000000, gasPrice: 18000000000, hash: "0x67bb538323962381c32195c94d67f3d8a6c39caa074d12319e5dfb6ba4b79d42", input: "0x6060604052341561000f57600080fd5b6040516020806104b18339810160405280805160656000908155600182905560028054600160a060020a03191633600160a060020a03161790559092507fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e691508080848160405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a1506103f6806100bb6000396000f3006060604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663b2dd1212811461005b578063cca10a2114610083578063db8d55f11461009c575b600080fd5b341561006657600080fd5b6100716004356100af565b60405190815260200160405180910390f35b61009a600435600160a060020a03602435166100c4565b005b34156100a757600080fd5b6100716103c4565b60009081526003602052604090206001015490565b60018054600254600092600160a060020a03909116907fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c903484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1348290101561014057600080fd5b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60023484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16000858152600360205260409020805490935060ff161515610300577fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e66001868560010154348860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a16002838101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a038781169190911790915560008054600180880191909155865460ff19168117875581548101909155915491549116906108fc81150290604051600060405180830381858888f19350505050151561029457600080fd5b7fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e6600286856001015460015434038860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a1610364565b7fd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e66003868560010154348860405194855260208501939093526040808501929092526060840152600160a060020a03909116608083015260a0909101905180910390a15b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60033484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a15050505050565b600154905600a165627a7a72305820fbca4691cd855134e337de1865b5bb119ca255ace4c88782cc2c65f85552c98200290000000000000000000000000000000000000000000000000de0b6b3a7640000", nonce: 0, r: "0xbe24f8bd858f488a010aec0ca8e2790fa6baa7e9bd62fa8387f5a4e3827c23d3", s: "0x72038ff9a3ab3608f897d3c5e6fbd0603fb8205cee3962dc10eebda862712d05", to: null, transactionIndex: 0, v: "0x4d", value: 0 }]
Before we start the miner, we will display the account balances. To display account balances using the Javascript utility function showBalances, execute the following command in the Javascript shell prompt:
> showBalances()
The following would be the typical output:
---> eth.accounts[0]: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76 balance: 20 ether ---> eth.accounts[1]: 0x35ddac855e0029676f489dafca9ab405a348317c balance: 10 ether ---> eth.accounts[2]: 0x46bf8994c8702919434271d89bcad8abec915612 balance: 5 ether ---> eth.accounts[3]: 0x518a6377a3863201aef3310da41f3448d959a310 balance: 3 ether undefined
To start the miner with one thread, execute the following command in the Javascript shell prompt:
> miner.start(1)
Wait a few seconds (about 10 to 15 seconds) for the contract deployment transaction to be mined. The end result is that the contract will be deployed into our private Blockchain network.
Once the transaction is mined, we can stop the miner. Execute the following command in the Javascript shell prompt:
> miner.stop()
To retrieve the transaction details for the dmv contract deployment, execute the following command in the Javascript shell prompt:
> eth.getTransactionReceipt(dmvregister_contract_inst.transactionHash)
The following would be the typical output:
{ blockHash: "0xe3cd14751c51ef81cc3ae18d8ef8d4c0e00f892aef6d59c5f97640f85dc99e9d", blockNumber: 1, contractAddress: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", cumulativeGasUsed: 397004, from: "0x518a6377a3863201aef3310da41f3448d959a310", gasUsed: 397004, logs: [{ address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", blockHash: "0xe3cd14751c51ef81cc3ae18d8ef8d4c0e00f892aef6d59c5f97640f85dc99e9d", blockNumber: 1, data: "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000", logIndex: 0, removed: false, topics: ["0xd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e6"], transactionHash: "0x67bb538323962381c32195c94d67f3d8a6c39caa074d12319e5dfb6ba4b79d42", transactionIndex: 0 }], logsBloom: "0x00000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000002000010000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x2dc7ff0518bed8b62f821263e35e7b79ce21458c4ea3710108a95021d21f50d0", to: null, transactionHash: "0x67bb538323962381c32195c94d67f3d8a6c39caa074d12319e5dfb6ba4b79d42", transactionIndex: 0 }
The presence of a value for the contractAddress (0x1727b37a8a3334d62b5f669423a74517d18b9aeb) from the Output.8 indicates that the contract has been successfully deployed to our private Blockchain network.
Once again, let us display account balances using the Javascript utility function showBalances. Execute the following command in the Javascript shell prompt:
Before proceeding further, we will once again display the account balances. To display account balances using the Javascript utility function showBalances, execute the following command in the Javascript shell prompt:
> showBalances()
The following would be the typical output:
---> eth.accounts[0]: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76 balance: 45.007146072 ether ---> eth.accounts[1]: 0x35ddac855e0029676f489dafca9ab405a348317c balance: 10 ether ---> eth.accounts[2]: 0x46bf8994c8702919434271d89bcad8abec915612 balance: 5 ether ---> eth.accounts[3]: 0x518a6377a3863201aef3310da41f3448d959a310 balance: 2.992853928 ether undefined
Since the dmv deployed the contract DmvRegister into our private Blockchain, as expected, the dmv account incurred a small processing fees in the form of gas.
Step - 09 |
Define a variable called dmvregister_contract_addr that is initialized with the value of the deployed dmv contract address. Execute the following statement in the Javascript shell as shown below:
> var dmvregister_contract_addr = eth.getTransactionReceipt(dmvregister_contract_inst.transactionHash).contractAddress
To check the value of the contract transaction object variable dmvregister_contract_addr, execute the following command in the Javascript shell prompt:
Check to ensure the variable dmvregister_contract_addr is initialized by executing the following command in the Javascript shell prompt:
> dmvregister_contract_addr
The following would be the typical output:
"0x1727b37a8a3334d62b5f669423a74517d18b9aeb"
To interact (invoke functions) with the deployed DmvRegister contract, we need an instance of the contract. To create an instance of the DmvRegister contract, invoke the at method on the contract object dmvregister_contract, passing in the value of the variable dmvregister_contract_addr as an argument. Execute the following command in the Javascript shell prompt:
> var dmvregister_obj = dmvregister_contract.at(dmvregister_contract_addr)
To check the value of the contract instance variable dmvregister_obj, execute the following command in the Javascript shell prompt:
> dmvregister_obj
The following would be the typical output:
{ abi: [{ constant: true, inputs: [{...}], name: "getLicense", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [{...}, {...}], name: "registerVehicle", outputs: [], payable: true, stateMutability: "payable", type: "function" }, { constant: true, inputs: [], name: "getFees", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { inputs: [{...}], payable: false, stateMutability: "nonpayable", type: "constructor" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}, {...}], name: "RegisteredEvt", type: "event" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "AmountEvt", type: "event" }], address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", transactionHash: null, AmountEvt: function(), RegisteredEvt: function(), allEvents: function(), getFees: function(), getLicense: function(), registerVehicle: function() }
Step - 10 |
The buyer walks into the auto dealership and expresses an intent to buy a vehicle. The dealer will create and deploy a Smart Contract representing the sale with the buyer for the desired vehicle (vin) at an agreed upon total cost (cost of the vehicle + the processing fees for vehicle registration at the dmv).
Check to ensure the variable vehicle3 is initialized by executing the following command in the Javascript shell prompt:
> vehicle3
The following would be the typical output:
{ contracts: { src/AmountOwed2.sol:AmountOwed2: { abi: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"flag\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"context\",\"type\":\"address\"}],\"name\":\"AmountEvt\",\"type\":\"event\"}]", bin: "60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00a165627a7a723058201ad282abd92f245df43f5c30716a945b232176ef484eb7ae18c8a01395dd33160029" }, src/IDmvRegister.sol:IDmvRegister: { abi: "[{\"constant\":true,\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"}],\"name\":\"getLicense\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"},{\"name\":\"buyer\",\"type\":\"address\"}],\"name\":\"registerVehicle\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getFees\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]", bin: "" }, src/Vehicle3.sol:Vehicle3: { abi: "[{\"constant\":true,\"inputs\":[],\"name\":\"getStatus\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getDealer\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"buyVehicle\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getCost\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getVin\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"vin\",\"type\":\"uint256\"},{\"name\":\"cost\",\"type\":\"uint256\"},{\"name\":\"fees\",\"type\":\"uint256\"},{\"name\":\"buyer\",\"type\":\"address\"},{\"name\":\"dmvcon\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"flag\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"vin\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"buyer\",\"type\":\"address\"}],\"name\":\"BoughtEvt\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"flag\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"name\":\"context\",\"type\":\"address\"}],\"name\":\"AmountEvt\",\"type\":\"event\"}]", bin: "6060604052341561000f57600080fd5b60405160a0806106a1833981016040528080519190602001805191906020018051919060200180519190602001805160008781556001879055600286905560038054600160a060020a03878116600160a060020a03199283161792839055600480543383169084161760a060020a60ff021916905560058054909216858216179091559294507f95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf9350909188918391166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1505050505061059b806101066000396000f3006060604052600436106100775763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634e69d560811461007c578063893d20e8146100b35780639cf6d1af146100e2578063a4e72902146100f5578063bd3e19d4146100ff578063bf20f94014610124575b600080fd5b341561008757600080fd5b61008f610137565b6040518082600181111561009f57fe5b60ff16815260200191505060405180910390f35b34156100be57600080fd5b6100c6610158565b604051600160a060020a03909116815260200160405180910390f35b34156100ed57600080fd5b6100c6610167565b6100fd610176565b005b341561010a57600080fd5b610112610543565b60405190815260200160405180910390f35b341561012f57600080fd5b610112610549565b60045474010000000000000000000000000000000000000000900460ff1690565b600354600160a060020a031690565b600454600160a060020a031690565b60008060025460015401600460009054906101000a9004600160a060020a03167fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60013484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a134829010156101fd57600080fd5b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60023484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1600354620f4240945034935033600160a060020a039081169116141561048c57600054600354600080516020610550833981519152916001918690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16004805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001790819055600154600160a060020a039091169080156108fc0290604051600060405180830381858888f19350505050151561033a57600080fd5b600154600054600354919094039360008051602061055083398151915291600291908690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1600554600054600354600160a060020a039283169263cca10a219288928892166040517c010000000000000000000000000000000000000000000000000000000063ffffffff87160281526004810192909252600160a060020a031660248201526044016000604051808303818589803b151561041657600080fd5b88f1151561042357600080fd5b50506002546000546003805492909803976000805160206105508339815191529550935091508690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16104e4565b600054600354600080516020610550833981519152916004913490600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a15b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60033484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a150505050565b60015490565b60005490560095220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bfa165627a7a7230582031c62c3945703dc4333755b805a2120992c21af05e4cd84644a9e2b77c733b860029" } }, version: "0.4.19+commit.c4cbbb05.Linux.g++" }
Step - 11 |
Create a contract object called vehicle3_contract by executing the following command in the Javascript shell prompt:
> var vehicle3_contract = eth.contract(JSON.parse(vehicle3.contracts['src/Vehicle3.sol:Vehicle3'].abi))
Check to ensure the variable vehicle3_contract is initialized by executing the following command in the Javascript shell prompt:
> vehicle3_contract
The following would be the typical output:
{ abi: [{ constant: true, inputs: [], name: "getStatus", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getOwner", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getDealer", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [], name: "buyVehicle", outputs: [], payable: true, stateMutability: "payable", type: "function" }, { constant: true, inputs: [], name: "getCost", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getVin", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { inputs: [{...}, {...}, {...}, {...}, {...}], payable: false, stateMutability: "nonpayable", type: "constructor" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "BoughtEvt", type: "event" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "AmountEvt", type: "event" }], eth: { accounts: ["0xef17ec5df3116dea3b7abaf1ff3045639453cc76", "0x35ddac855e0029676f489dafca9ab405a348317c", "0x46bf8994c8702919434271d89bcad8abec915612", "0x518a6377a3863201aef3310da41f3448d959a310"], blockNumber: 0, coinbase: "0xef17ec5df3116dea3b7abaf1ff3045639453cc76", compile: { lll: function(), serpent: function(), solidity: function() }, defaultAccount: undefined, defaultBlock: "latest", gasPrice: 18000000000, hashrate: 0, mining: false, pendingTransactions: [], protocolVersion: "0x3f", syncing: false, call: function(), contract: function(abi), estimateGas: function(), filter: function(options, callback, filterCreationErrorCallback), getAccounts: function(callback), getBalance: function(), getBlock: function(), getBlockNumber: function(callback), getBlockTransactionCount: function(), getBlockUncleCount: function(), getCode: function(), getCoinbase: function(callback), getCompilers: function(), getGasPrice: function(callback), getHashrate: function(callback), getMining: function(callback), getPendingTransactions: function(callback), getProtocolVersion: function(callback), getRawTransaction: function(), getRawTransactionFromBlock: function(), getStorageAt: function(), getSyncing: function(callback), getTransaction: function(), getTransactionCount: function(), getTransactionFromBlock: function(), getTransactionReceipt: function(), getUncle: function(), getWork: function(), iban: function(iban), icapNamereg: function(), isSyncing: function(callback), namereg: function(), resend: function(), sendIBANTransaction: function(), sendRawTransaction: function(), sendTransaction: function(), sign: function(), signTransaction: function(), submitTransaction: function(), submitWork: function() }, at: function(address, callback), getData: function(), new: function() }
Step - 12 |
Create a variable called vehicle3_contract_txn to represent the contract transaction object, encapsulating the address of the dealer, the bytecode of the vehicle contract, and a gas price. Execute the following expression in the Javascript shell as shown below:
> var vehicle3_contract_txn = { from: dealer, data: '0x'+vehicle3.contracts['src/Vehicle3.sol:Vehicle3'].bin, gas: gas }
Check to ensure the variable vehicle3_contract_txn is initialized by executing the following command in the Javascript shell prompt:
> vehicle3_contract_txn
The following would be the typical output:
{ data: "0x6060604052341561000f57600080fd5b60405160a0806106a1833981016040528080519190602001805191906020018051919060200180519190602001805160008781556001879055600286905560038054600160a060020a03878116600160a060020a03199283161792839055600480543383169084161760a060020a60ff021916905560058054909216858216179091559294507f95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf9350909188918391166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1505050505061059b806101066000396000f3006060604052600436106100775763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634e69d560811461007c578063893d20e8146100b35780639cf6d1af146100e2578063a4e72902146100f5578063bd3e19d4146100ff578063bf20f94014610124575b600080fd5b341561008757600080fd5b61008f610137565b6040518082600181111561009f57fe5b60ff16815260200191505060405180910390f35b34156100be57600080fd5b6100c6610158565b604051600160a060020a03909116815260200160405180910390f35b34156100ed57600080fd5b6100c6610167565b6100fd610176565b005b341561010a57600080fd5b610112610543565b60405190815260200160405180910390f35b341561012f57600080fd5b610112610549565b60045474010000000000000000000000000000000000000000900460ff1690565b600354600160a060020a031690565b600454600160a060020a031690565b60008060025460015401600460009054906101000a9004600160a060020a03167fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60013484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a134829010156101fd57600080fd5b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60023484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1600354620f4240945034935033600160a060020a039081169116141561048c57600054600354600080516020610550833981519152916001918690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16004805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001790819055600154600160a060020a039091169080156108fc0290604051600060405180830381858888f19350505050151561033a57600080fd5b600154600054600354919094039360008051602061055083398151915291600291908690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1600554600054600354600160a060020a039283169263cca10a219288928892166040517c010000000000000000000000000000000000000000000000000000000063ffffffff87160281526004810192909252600160a060020a031660248201526044016000604051808303818589803b151561041657600080fd5b88f1151561042357600080fd5b50506002546000546003805492909803976000805160206105508339815191529550935091508690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16104e4565b600054600354600080516020610550833981519152916004913490600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a15b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60033484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a150505050565b60015490565b60005490560095220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bfa165627a7a7230582031c62c3945703dc4333755b805a2120992c21af05e4cd84644a9e2b77c733b860029", from: "0x46bf8994c8702919434271d89bcad8abec915612", gas: 1000000 }
Step - 13 |
Now we are ready to deploy our Smart Contract for the vehicle called Vehicle3 into our private Ethereum network.
Since the contract will be deployed by the dealer account, we need to unlock the dealer account before proceeding further.
To unlock the dealer account, execute the following command in the Javascript shell prompt:
> personal.unlockAccount(dealer)
This will prompt us for the password for the dmv account. The following would be the typical output:
Unlock account 0x46bf8994c8702919434271d89bcad8abec915612 Passphrase: dealer true
Create a contract instance object called vehicle3_contract_inst, by calling the new method on the contract object vehicle3_contract, passing a constructor argument for the vin number (vin), the cost of the vehicle (cost), the processing fees (fees), the account address of the buyer (buyer), the contract address of the dmv Smart Contract (dmvregister_contract_addr), and the contract transaction object vehicle3_contract_txn. Execute the following command in the Javascript shell prompt:
> var vehicle3_contract_inst = vehicle3_contract.new(vin, cost, fees, buyer, dmvregister_contract_addr, vehicle3_contract_txn)
Check to ensure the variable vehicle3_contract_inst is initialized by executing the following command in the Javascript shell prompt:
> vehicle3_contract_inst
The following would be the typical output:
{ abi: [{ constant: true, inputs: [], name: "getStatus", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getOwner", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getDealer", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [], name: "buyVehicle", outputs: [], payable: true, stateMutability: "payable", type: "function" }, { constant: true, inputs: [], name: "getCost", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getVin", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { inputs: [{...}, {...}, {...}, {...}, {...}], payable: false, stateMutability: "nonpayable", type: "constructor" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "BoughtEvt", type: "event" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "AmountEvt", type: "event" }], address: undefined, transactionHash: "0xd5dd939c3d03315a627fe226ede625f85a4d5fdc2023cd4b1defbe1995285748" }
Step - 14 |
The above contract instance creation command will generate an Ethereum transaction that needs to be mined for the contract to be deployed into the private Blockchain network.
To check all the pending transactions, execute the following command in the Javascript shell prompt:
> eth.pendingTransactions
The following would be the typical output:
[{ blockHash: null, blockNumber: null, from: "0x46bf8994c8702919434271d89bcad8abec915612", gas: 1000000, gasPrice: 18000000000, hash: "0xd5dd939c3d03315a627fe226ede625f85a4d5fdc2023cd4b1defbe1995285748", input: "0x6060604052341561000f57600080fd5b60405160a0806106a1833981016040528080519190602001805191906020018051919060200180519190602001805160008781556001879055600286905560038054600160a060020a03878116600160a060020a03199283161792839055600480543383169084161760a060020a60ff021916905560058054909216858216179091559294507f95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf9350909188918391166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1505050505061059b806101066000396000f3006060604052600436106100775763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416634e69d560811461007c578063893d20e8146100b35780639cf6d1af146100e2578063a4e72902146100f5578063bd3e19d4146100ff578063bf20f94014610124575b600080fd5b341561008757600080fd5b61008f610137565b6040518082600181111561009f57fe5b60ff16815260200191505060405180910390f35b34156100be57600080fd5b6100c6610158565b604051600160a060020a03909116815260200160405180910390f35b34156100ed57600080fd5b6100c6610167565b6100fd610176565b005b341561010a57600080fd5b610112610543565b60405190815260200160405180910390f35b341561012f57600080fd5b610112610549565b60045474010000000000000000000000000000000000000000900460ff1690565b600354600160a060020a031690565b600454600160a060020a031690565b60008060025460015401600460009054906101000a9004600160a060020a03167fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60013484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a134829010156101fd57600080fd5b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60023484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1600354620f4240945034935033600160a060020a039081169116141561048c57600054600354600080516020610550833981519152916001918690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16004805474ff00000000000000000000000000000000000000001916740100000000000000000000000000000000000000001790819055600154600160a060020a039091169080156108fc0290604051600060405180830381858888f19350505050151561033a57600080fd5b600154600054600354919094039360008051602061055083398151915291600291908690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a1600554600054600354600160a060020a039283169263cca10a219288928892166040517c010000000000000000000000000000000000000000000000000000000063ffffffff87160281526004810192909252600160a060020a031660248201526044016000604051808303818589803b151561041657600080fd5b88f1151561042357600080fd5b50506002546000546003805492909803976000805160206105508339815191529550935091508690600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a16104e4565b600054600354600080516020610550833981519152916004913490600160a060020a03166040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a15b7fa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c60033484846040519384526020840192909252604080840191909152600160a060020a0390911660608301526080909101905180910390a150505050565b60015490565b60005490560095220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bfa165627a7a7230582031c62c3945703dc4333755b805a2120992c21af05e4cd84644a9e2b77c733b86002900000000000000000000000000000000000000000000000000000000499602d20000000000000000000000000000000000000000000000003782dace9d9000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c0000000000000000000000001727b37a8a3334d62b5f669423a74517d18b9aeb", nonce: 0, r: "0x7a63a6413f3b2ccdba4fcb9446e2a23e6de1a4151d89ed0fb6367c5ba0a72928", s: "0x25f2b828c2a04b2d429efa26f5010d333dd55064958c2940a8018bae12a1694b", to: null, transactionIndex: 0, v: "0x4d", value: 0 }]
To start the miner with one thread, execute the following command in the Javascript shell prompt:
> miner.start(1)
Wait a few seconds (about 10 to 15 seconds) for the contract deployment transaction to be mined. The end result is that the contract will be deployed into our private Blockchain network.
Once the transaction is mined, we can stop the miner. Execute the following command in the Javascript shell prompt:
> miner.stop()
To retrieve the transaction details for the dmv contract deployment, execute the following command in the Javascript shell prompt:
> eth.getTransactionReceipt(vehicle3_contract_inst.transactionHash)
The following would be the typical output:
{ blockHash: "0x195f42065b8784552a306a5623f1fa608ecfc389c2b4b2a08aabdf4eefe5d52b", blockNumber: 6, contractAddress: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", cumulativeGasUsed: 572400, from: "0x46bf8994c8702919434271d89bcad8abec915612", gasUsed: 572400, logs: [{ address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x195f42065b8784552a306a5623f1fa608ecfc389c2b4b2a08aabdf4eefe5d52b", blockNumber: 6, data: "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000499602d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c", logIndex: 0, removed: false, topics: ["0x95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf"], transactionHash: "0xd5dd939c3d03315a627fe226ede625f85a4d5fdc2023cd4b1defbe1995285748", transactionIndex: 0 }], logsBloom: "0x00000000000100000001000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000002000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x8474c4b84ca25450047f39ad6ee6b23337a8ed73dc6215e3ede705bc01060dda", to: null, transactionHash: "0xd5dd939c3d03315a627fe226ede625f85a4d5fdc2023cd4b1defbe1995285748", transactionIndex: 0 }
The presence of a value for the contractAddress (0xfa332003301955dd8526f0ef3aa7c670bda5f4fa) from the Output.17 indicates that the contract has been successfully deployed to our private Blockchain network.
Once again, let us display account balances using the Javascript utility function showBalances. Execute the following command in the Javascript shell prompt:
Before proceeding further, we will once again display the account balances. To display account balances using the Javascript utility function showBalances, execute the following command in the Javascript shell prompt:
> showBalances()
The following would be the typical output:
---> eth.accounts[0]: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76 balance: 90.017449272 ether ---> eth.accounts[1]: 0x35ddac855e0029676f489dafca9ab405a348317c balance: 10 ether ---> eth.accounts[2]: 0x46bf8994c8702919434271d89bcad8abec915612 balance: 4.9896968 ether ---> eth.accounts[3]: 0x518a6377a3863201aef3310da41f3448d959a310 balance: 2.992853928 ether undefined
Since the dealer deployed the contract Vehicle3 into our private Blockchain, as expected, the dealer account incurred a small processing fees in the form of gas.
Step - 15 |
Define a variable called vehicle3_contract_addr that is initialized with the value of the deployed vehicle contract address. Execute the following statement in the Javascript shell as shown below:
> var vehicle3_contract_addr = eth.getTransactionReceipt(vehicle3_contract_inst.transactionHash).contractAddress
To check the value of the contract transaction object variable vehicle3_contract_addr, execute the following command in the Javascript shell prompt:
Check to ensure the variable vehicle3_contract_addr is initialized by executing the following command in the Javascript shell prompt:
> vehicle3_contract_addr
The following would be the typical output:
"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa"
Step - 16 |
To interact (invoke functions) with the deployed Vehicle3 contract, we need an instance of the contract. To create an instance of the Vehicle3 contract, invoke the at method on the contract object vehicle3_contract, passing in the value of the variable vehicle3_contract_addr as an argument. Execute the following command in the Javascript shell prompt:
> var vehicle3_obj = vehicle3_contract.at(vehicle3_contract_addr)
To check the value of the contract instance variable vehicle3_obj, execute the following command in the Javascript shell prompt:
> vehicle3_obj
The following would be the typical output:
{ abi: [{ constant: true, inputs: [], name: "getStatus", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getOwner", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getDealer", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: false, inputs: [], name: "buyVehicle", outputs: [], payable: true, stateMutability: "payable", type: "function" }, { constant: true, inputs: [], name: "getCost", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { constant: true, inputs: [], name: "getVin", outputs: [{...}], payable: false, stateMutability: "view", type: "function" }, { inputs: [{...}, {...}, {...}, {...}, {...}], payable: false, stateMutability: "nonpayable", type: "constructor" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "BoughtEvt", type: "event" }, { anonymous: false, inputs: [{...}, {...}, {...}, {...}], name: "AmountEvt", type: "event" }], address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", transactionHash: null, AmountEvt: function(), BoughtEvt: function(), allEvents: function(), buyVehicle: function(), getCost: function(), getDealer: function(), getOwner: function(), getStatus: function(), getVin: function() }
Before proceeding further, let us verify the license number associated with the vehicle vin number. Remember, that the buyer has not yet initiated any transaction on the deployed vehicle contract, and hence there should not be any valid license number associated with the vin. Invoke the getLicense method on the dmv contract instance dmvregister_obj by executing the following command in the Javascript shell prompt:
> dmvregister_obj.getLicense(vin)
The following would be the typical output:
0
From the Output.22 above, it is clear that there is no valid license number assigned to the specified vin yet.
Step - 17 |
The buyer will send a transaction message to invoke the method buyVehicle on the object vehicle3_obj, along with a payment covering the total cost for the vehicle (cost + fees).
Define a variable called buyer_txn to represent the transaction message that encapsulates the address of the buyer (buyer), the total cost of the vehicle (total), and the gas price (gas). Execute the following statement in the Javascript shell as shown below:
> var buyer_txn = { from: buyer, value: total, gas: gas }
To check the value of the variable buyer_txn, execute the following command in the Javascript shell prompt:
> buyer_txn
The following would be the typical output:
{ from: "0x35ddac855e0029676f489dafca9ab405a348317c", gas: 1000000, value: 5000000000000000000 }
Since the buyer is initiating the transaction, we need to unlock the buyer account before proceeding further.
To unlock the buyer account, execute the following command in the Javascript shell prompt:
> personal.unlockAccount(buyer)
This will prompt us for the password for the buyer account. The following would be the typical output:
Unlock account 0x35ddac855e0029676f489dafca9ab405a348317c Passphrase: buyer true
The buyer will activate the contract by calling the sendTransaction method on the object vehicle3_obj.buyVehicle. Execute the following command in the Javascript shell prompt:
> var buyer_txn_hash = vehicle3_obj.buyVehicle.sendTransaction(buyer_txn)
Check the value of the variable buyer_txn_hash that represents the transaction hash by executing the following command in the Javascript shell prompt:
> buyer_txn_hash
The following would be the typical output:
"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396"
The transaction created by the buyer needs to be mined in order to trigger the method invocation on the deployed contract on our private Blockchain network.
To check all the pending transactions, execute the following command in the Javascript shell prompt:
> eth.pendingTransactions
The following would be the typical output:
[{ blockHash: null, blockNumber: null, from: "0x35ddac855e0029676f489dafca9ab405a348317c", gas: 1000000, gasPrice: 18000000000, hash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", input: "0xa4e72902", nonce: 0, r: "0x73c53ba5375edc4e13c39d88e1001a4a3ed924710382432d80d85b71726666bf", s: "0x142f1483e475c06432ba25dab883bdf7cdd21abe663e15810a0d6f9a83eceb04", to: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", transactionIndex: 0, v: "0x4d", value: 5000000000000000000 }]
To start the miner with one thread, execute the following command in the Javascript shell prompt:
> miner.start(1)
Wait a few seconds (about 10 to 15 seconds) for the buyer transaction message to be mined. The end result is that the contract method vehicle3_obj.buyVehicle will be invoked, executing the logic in the method.
Once the transaction is mined, we can stop the miner. Execute the following command in the Javascript shell prompt:
> miner.stop()
To retrieve the transaction details for the buyer contract execution, execute the following command in the Javascript shell prompt:
> eth.getTransactionReceipt(buyer_txn_hash)
The following would be the typical output:
{ blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, contractAddress: null, cumulativeGasUsed: 144400, from: "0x35ddac855e0029676f489dafca9ab405a348317c", gasUsed: 144400, logs: [{ address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000046bf8994c8702919434271d89bcad8abec915612", logIndex: 0, removed: false, topics: ["0xa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000046bf8994c8702919434271d89bcad8abec915612", logIndex: 1, removed: false, topics: ["0xa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000499602d20000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c", logIndex: 2, removed: false, topics: ["0x95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000499602d20000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c", logIndex: 3, removed: false, topics: ["0x95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000518a6377a3863201aef3310da41f3448d959a310", logIndex: 4, removed: false, topics: ["0xa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000518a6377a3863201aef3310da41f3448d959a310", logIndex: 5, removed: false, topics: ["0xa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000499602d200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c", logIndex: 6, removed: false, topics: ["0xd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e6"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000499602d20000000000000000000000000000000000000000000000000000000000000065000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c", logIndex: 7, removed: false, topics: ["0xd48742c718bff6639d660fdc7ee2490144cec186cbc6e2672aad33b0d7c7f1e6"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0x1727b37a8a3334d62b5f669423a74517d18b9aeb", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000518a6377a3863201aef3310da41f3448d959a310", logIndex: 8, removed: false, topics: ["0xa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000499602d2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035ddac855e0029676f489dafca9ab405a348317c", logIndex: 9, removed: false, topics: ["0x95220c63110cc8cabcb0e392391cb923d89015bec2afbb6e668d8f463dd8c9bf"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }, { address: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", blockHash: "0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99", blockNumber: 15, data: "0x00000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000004563918244f400000000000000000000000000000000000000000000000000004563918244f4000000000000000000000000000046bf8994c8702919434271d89bcad8abec915612", logIndex: 10, removed: false, topics: ["0xa6eeda949aa9e928463d0850d41fb5d526023dabcf145aeca26f46853246cf2c"], transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }], logsBloom: "0x00000000000100000201000000000000000000000000000000000020000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000002000010000000000000000000000000000000000000000000000208000000000000000002000000000000000000000000000001000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", root: "0x3bba2970db1e2b7ab52b03e434ad1b29a9da80e965ff7e9409f95f480b04c601", to: "0xfa332003301955dd8526f0ef3aa7c670bda5f4fa", transactionHash: "0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396", transactionIndex: 0 }
Once again, let us display account balances using the Javascript utility function showBalances. Execute the following command in the Javascript shell prompt:
Before proceeding further, we will once again display the account balances. To display account balances using the Javascript utility function showBalances, execute the following command in the Javascript shell prompt:
> showBalances()
The following would be the typical output:
---> eth.accounts[0]: 0xef17ec5df3116dea3b7abaf1ff3045639453cc76 balance: 105.020048472 ether ---> eth.accounts[1]: 0x35ddac855e0029676f489dafca9ab405a348317c balance: 4.9974008 ether ---> eth.accounts[2]: 0x46bf8994c8702919434271d89bcad8abec915612 balance: 8.9896968 ether ---> eth.accounts[3]: 0x518a6377a3863201aef3310da41f3448d959a310 balance: 3.992853928 ether undefined
Comparing Output.26 to Output.18, we see the account balance of the dealer has increased by 4 ethers and the account balance of the dmv has increased by an ether.
Once again, let us verify the license number associated with the vehicle vin number. Invoke the getLicense method on the dmv contract instance dmvregister_obj by executing the following command in the Javascript shell prompt:
> dmvregister_obj.getLicense(vin)
The following would be the typical output:
101
BINGO !!! This time around, from the Output.29 above, we see a valid license number assigned to the specified vin number.
Step - 18 |
To display all the events emitted during the invocation of the method vehicle3_obj.buyVehicle, we need to create an instance of the allEvents filter. We then invoke the watch method on the filter instance, specifying a callback function to display the event details.
To create a filter instance for all events, execute the following command in the Javascript shell prompt:
> var vehicle3_events = vehicle3_obj.allEvents({fromBlock: 0, toBlock: 'latest'})
We want to scan the transaction log(s) for all the mined blocks, and hence the fromBlock of 0 to the toBlock of latest.
To start the display of event(s) from the transaction log(s), execute the following command in the Javascript shell prompt:
> var dummy = vehicle3_events.watch(function (error, result) { console.log("=> " + JSON.stringify(result)); })
The following would be the typical output:
=> {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"buyer":"0x35ddac855e0029676f489dafca9ab405a348317c","flag":"0","value":"0","vin":"1234567890"},"blockHash":"0x195f42065b8784552a306a5623f1fa608ecfc389c2b4b2a08aabdf4eefe5d52b","blockNumber":6,"event":"BoughtEvt","logIndex":0,"removed":false,"transactionHash":"0xd5dd939c3d03315a627fe226ede625f85a4d5fdc2023cd4b1defbe1995285748","transactionIndex":0} => {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"amount":"5000000000000000000","context":"0x46bf8994c8702919434271d89bcad8abec915612","flag":"1","value":"5000000000000000000"},"blockHash":"0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99","blockNumber":15,"event":"AmountEvt","logIndex":0,"removed":false,"transactionHash":"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396","transactionIndex":0} => {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"amount":"5000000000000000000","context":"0x46bf8994c8702919434271d89bcad8abec915612","flag":"2","value":"5000000000000000000"},"blockHash":"0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99","blockNumber":15,"event":"AmountEvt","logIndex":1,"removed":false,"transactionHash":"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396","transactionIndex":0} => {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"buyer":"0x35ddac855e0029676f489dafca9ab405a348317c","flag":"1","value":"5000000000000000000","vin":"1234567890"},"blockHash":"0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99","blockNumber":15,"event":"BoughtEvt","logIndex":2,"removed":false,"transactionHash":"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396","transactionIndex":0} => {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"buyer":"0x35ddac855e0029676f489dafca9ab405a348317c","flag":"2","value":"1000000000000000000","vin":"1234567890"},"blockHash":"0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99","blockNumber":15,"event":"BoughtEvt","logIndex":3,"removed":false,"transactionHash":"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396","transactionIndex":0} => {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"buyer":"0x35ddac855e0029676f489dafca9ab405a348317c","flag":"3","value":"0","vin":"1234567890"},"blockHash":"0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99","blockNumber":15,"event":"BoughtEvt","logIndex":9,"removed":false,"transactionHash":"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396","transactionIndex":0} => {"address":"0xfa332003301955dd8526f0ef3aa7c670bda5f4fa","args":{"amount":"5000000000000000000","context":"0x46bf8994c8702919434271d89bcad8abec915612","flag":"3","value":"5000000000000000000"},"blockHash":"0x9449fd8223aeebe8548f534b8f104fac759725e5fad7a60e61f3ae78452b8e99","blockNumber":15,"event":"AmountEvt","logIndex":10,"removed":false,"transactionHash":"0x7c5b7485d4ff37f2eea7853f65d60ea266e3375121b1d66a08bfc2d224ecb396","transactionIndex":0} undefined
To stop the event watcher, execute the following command in the Javascript shell prompt:
> vehicle3_events.stopWatching()
YIPEE !!! We have successfully demonstrated the end-to-end use-case for the simple vehicle buying use-case (involving the buyer, the dealer, and the dmv) as laid out in our first introductory article.
References