Ethereum Smart Contract Development Part 4: Implementing Hello World Smart Contract

The original text was published in: Ethereum Smart Contract Development Part 4: Implementing Hello World Smart Contract

When most developers learn a language, they start by outputting a Hello World . Let's also start by implementing a Hello World contract as an entry point and start entering the world of smart contracts.

Environmental preparation

Install node and npm . The installation process of node and npm is not described in detail here. This article depends on the environment version:

Node : v8.9.0 Npm: 5.5.1

In your code directory, create a folder named smartcontract , and create the following two files package.json , Hello.sol .

smartcontract ├── Hello.sol └── package.json

In the package.json file, add the following dependency package configuration:

{
  "name": "smartcontract",
  "version": "0.0.1",
  "dependencies": {
    "fs": "0.0.1-security",
    "solc": "^0.4.21",
    "web3": "^0.20.0"
  }
}

The fs module is used for file-related operations. The solc module is a compiler. The web3 module is a toolkit provided by Ethereum and is mainly used for communication with contracts.

Next, execute npm install to download the relevant dependency packages.

Write contract code

Once the environment is ready, you can start writing contract code. Open the Hello.sol file and write the code as follows:

//pragma关键字:版本申明。
//用来指示编译器将代码编译成特定版本,以免引起兼容性问题
//此处不支持0.4.0之前的编译器,也不支持0.5.0之后的编译器(条件为 ^)
pragma solidity ^0.4.0;

//contract关键字:合约申明
//和Java、PHP中的class类似
//此处是申明一个名为Hello的合约
contract Hello {

    //public: 函数访问属性(后续文章为详细阐述)
    //returns (string): 定义返回值类型为string
    function say(string name) public returns (string) {
        return name;
    }
}

The code is simple. It realizes the operation of returning the contract as it is to whatever string the user enters.

Next, we need to write the contract deployment script.

Write a contract deployment script

In the smartcontract directory, create a new file named deploy.js . code show as below:

//设置web3连接
var Web3 = require('web3');
//http://localhost:7545 为Ganache提供的节点链接
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
//读取合约
var fs = require('fs');
var contractCode = fs.readFileSync('Hello.sol').toString();
//编译合约代码
var solc = require('solc');
var compileCode = solc.compile(contractCode);

console.log(compileCode);

//获取合约abi和字节码
var abi = JSON.parse(compileCode.contracts[':Hello'].interface);
var byteCode = compileCode.contracts[':Hello'].bytecode;
//创建合约对象
var VotingContract = web3.eth.contract(abi);
//部署合约,并返回部署对象
var deployedContract = VotingContract.new({
    data:byteCode,
    from:web3.eth.accounts[0],  //部署合约的外部账户地址
    gas:750000        //部署合约的矿工费
});
console.log(deployedContract);

I added simple comments to the code. Explain the concept of abi here.

The full name of abi is Application Binary Interface, which is the application binary interface. Simply put, it is the external interface description of the contract.

It should be noted that the miner fee gas is 750000. A certain amount of gas is charged for each transaction execution (packaged by miners) on Ethereum. The purpose of gas is to limit the amount of work required to execute a transaction, while paying for execution. When the EVM executes the transaction, the gas will be gradually consumed according to certain rules. No matter where the execution is, once the gas is exhausted, an out of gas exception will be triggered. All state modifications made by the current calling frame will be rolled back. If the execution ends and there is gas remaining, the gas will be returned to the sending account. Therefore, if an out of gas exception is thrown during deployment, we can increase the gas value appropriately.

deploy

In the current directory, execute the node deploy.js command. We print out the compileCode variable in the deployment script, just take a cursory look:

{ contracts:
   { ':Hello':
      { assembly: [Object],
        bytecode: '6060604052341561000f57600080fd5b61016c8061001e6000396000f300606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d5c6130114610046575b600080fd5b341561005157600080fd5b6100a1600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190505061011c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100e15780820151818401526020810190506100c6565b50505050905090810190601f16801561010e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61012461012c565b819050919050565b6020604051908101604052806000815250905600a165627a7a72305820ff14cafd1df21e1edf19eff7598bc82a98940cc0fe045d6107d04bb224014f990029',
        functionHashes: [Object],
        gasEstimates: [Object],
        interface: '[{"constant":false,"inputs":[{"name":"name","type":"string"}],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]',
        metadata: '{"compiler":{"version":"0.4.21+commit.dfe3193c"},"language":"Solidity","output":{"abi":[{"constant":false,"inputs":[{"name":"name","type":"string"}],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"}],"devdoc":{"methods":{}},"userdoc":{"methods":{}}},"settings":{"compilationTarget":{"":"Hello"},"evmVersion":"byzantium","libraries":{},"optimizer":{"enabled":false,"runs":200},"remappings":[]},"sources":{"":{"keccak256":"0x2e3dd18fbfbd17bb4f866b1bfbb38082172a0bb58d9396b63bab04e67d9d8e08","urls":["bzzr://d1aae746dfab03e712d8a3cb76b7d4b5bf60f48fafbffa04dfa8a2d53ad5d0ca"]}},"version":1}',
        opcodes: 'PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH2 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x16C DUP1 PUSH2 0x1E PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x41 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0xD5C61301 EQ PUSH2 0x46 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE ISZERO PUSH2 0x51 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0xA1 PUSH1 0x4 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP3 ADD DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP1 PUSH1 0x1F ADD PUSH1 0x20 DUP1 SWAP2 DIV MUL PUSH1 0x20 ADD PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 SWAP4 SWAP3 SWAP2 SWAP1 DUP2 DUP2 MSTORE PUSH1 0x20 ADD DUP4 DUP4 DUP1 DUP3 DUP5 CALLDATACOPY DUP3 ADD SWAP2 POP POP POP POP POP POP SWAP2 SWAP1 POP POP PUSH2 0x11C JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP1 PUSH1 0x20 ADD DUP3 DUP2 SUB DUP3 MSTORE DUP4 DUP2 DUP2 MLOAD DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP DUP1 MLOAD SWAP1 PUSH1 0x20 ADD SWAP1 DUP1 DUP4 DUP4 PUSH1 0x0 JUMPDEST DUP4 DUP2 LT ISZERO PUSH2 0xE1 JUMPI DUP1 DUP3 ADD MLOAD DUP2 DUP5 ADD MSTORE PUSH1 0x20 DUP2 ADD SWAP1 POP PUSH2 0xC6 JUMP JUMPDEST POP POP POP POP SWAP1 POP SWAP1 DUP2 ADD SWAP1 PUSH1 0x1F AND DUP1 ISZERO PUSH2 0x10E JUMPI DUP1 DUP3 SUB DUP1 MLOAD PUSH1 0x1 DUP4 PUSH1 0x20 SUB PUSH2 0x100 EXP SUB NOT AND DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP JUMPDEST POP SWAP3 POP POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0x124 PUSH2 0x12C JUMP JUMPDEST DUP2 SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x20 PUSH1 0x40 MLOAD SWAP1 DUP2 ADD PUSH1 0x40 MSTORE DUP1 PUSH1 0x0 DUP2 MSTORE POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 SELFDESTRUCT EQ 0xca REVERT SAR CALLCODE 0x1e 0x1e 0xdf NOT 0xef 0xf7 MSIZE DUP12 0xc8 0x2a SWAP9 SWAP5 0xc 0xc0 INVALID DIV 0x5d PUSH2 0x7D0 0x4b 0xb2 0x24 ADD 0x4f SWAP10 STOP 0x29 ',
        runtimeBytecode: '606060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063d5c6130114610046575b600080fd5b341561005157600080fd5b6100a1600480803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509190505061011c565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100e15780820151818401526020810190506100c6565b50505050905090810190601f16801561010e5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61012461012c565b819050919050565b6020604051908101604052806000815250905600a165627a7a72305820ff14cafd1df21e1edf19eff7598bc82a98940cc0fe045d6107d04bb224014f990029',
        srcmap: '25:102:0:-;;;;;;;;;;;;;;;;;',
        srcmapRuntime: '25:102:0:-;;;;;;;;;;;;;;;;;;;;;;;;47:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;47:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89:6;;:::i;:::-;114:4;107:11;;47:78;;;:::o;25:102::-;;;;;;;;;;;;;;;:::o' } },
  errors:
   [ ':5:5: Warning: Function state mutability can be restricted to pure\n    function say(string name) public returns (string) {\n    ^ (Relevant source part starts here and spans across multiple lines).\n' ],
  sourceList: [ '' ],
  sources: { '': { AST: [Object] } } }

Open Ganache's LOGS panel, you can see the transaction log generated by the deployment:

transaction

The arrow points to the contract address after successful deployment: 0xbf474d24ba8b19811db5deb51137ddccbe3ff288 (the address after deployment may be different for everyone). We record it, which will be used in the contract calling code later. At the same time, you can also open the ACCOUNTS panel to observe the changes in the account balance.

contract call

After the contract is deployed successfully, we write a piece of code to call the say() method in the contract to check the effect. In the smartcontract directory, create a new file named run.js with the following code:

//设置web3连接
var Web3 = require('web3');
//http://localhost:7545 为Ganache提供的节点链接
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:7545'));
//读取合约
var fs = require('fs');
var contractCode = fs.readFileSync('Hello.sol').toString();
//编译合约代码
var solc = require('solc');
var compileCode = solc.compile(contractCode);
//获取合约abi和字节码
var abi = JSON.parse(compileCode.contracts[':Hello'].interface);
var byteCode = compileCode.contracts[':Hello'].bytecode;
//创建合约对象
var VotingContract = web3.eth.contract(abi);
//0xbf474d24ba8b19811db5deb51137ddccbe3ff288为合约部署地址
var contractInstance = VotingContract.at("0xbf474d24ba8b19811db5deb51137ddccbe3ff288");

var result = contractInstance.say.call('Hello world');
console.log(result);

Let's execute the node run.js command, and you can see that Hello world is output in the terminal .

At this point, the process of coding -> compiling -> deploying -> calling the first smart contract is complete. It is recommended that you do it by hand to deepen your understanding.

Throwing bricks and attracting jade

If we define the Hello string in the contract in advance , how to concatenate the string with the name variable?

Please look forward to the next explanation.

Smart contract development QQ group: 753778670

Smart contract development QQ group


There are currently several sets of video courses on blockchain practice (video + source code), if you need it, you can add me on WeChat (kuangwenjie) and send me a private message (paid):

  • "Blockchain" from zero construction of Ethereum (Ethereum) smart contracts to actual projects
  • Development of a decentralized Ebay blockchain project based on Ethereum & IPFS
  • HyperLedger Fabric

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324421499&siteId=291194637