Creating and Deploying Smart Contracts with Solidity – 用Solidity创建和部署智能合约

最后修改: 2018年 4月 4日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

The ability to run smart contracts is what has made the Ethereum blockchain so popular and disruptive.

运行智能合约的能力是使以太坊区块链如此受欢迎和具有破坏性的原因。

Before we explain what a smart contract is, let’s start with a definition of blockchain:

在我们解释什么是智能合约之前,让我们先来看看区块链的定义。

Blockchain is a public database that keeps a permanent record of digital transactions. It operates as a trustless transactional system, a framework in which individuals can make peer-to-peer transactions without needing to trust a third party or one another.

区块链是一个公共数据库,保持数字交易的永久记录。它作为一个无信任的交易系统运作,是一个个人可以进行点对点交易的框架,而不需要信任第三方或彼此之间。

Let’s see how we can create smart contracts on Ethereum with solidity:

让我们看看如何用solidity在Ethereum上创建智能合约:

2. Ethereum

2.Ethereum

Ethereum is a platform that allows people to write decentralized applications using blockchain technology efficiently.

以太坊是一个平台,允许人们有效地使用区块链技术编写去中心化的应用程序。

A decentralized application (Dapp) is a tool for people and organizations on different sides of an interaction used to come together without any centralized intermediary. Early examples of Dapps include BitTorrent (file sharing) and Bitcoin (currency).

去中心化的应用程序(Dapp)是一种工具,用于在没有任何中心化中介的情况下,让处于互动不同方面的人和组织走到一起。Dapp的早期例子包括BitTorrent(文件共享)和Bitcoin(货币)。

We can describe Ethereum as a blockchain with a built-in programming language.

我们可以把以太坊描述为一个内置编程语言的区块链。

2.1. Ethereum Virtual Machine (EVM)

2.1.以太坊虚拟机(EVM)

From a practical standpoint, the EVM can be thought of as a large, decentralized system containing millions of objects, called accounts, which can maintain an internal database, execute code and talk to each other.

从实际的角度来看,EVM可以被认为是一个大型的、分散的系统,包含数百万个对象,称为accounts,它们可以维护内部数据库,执行代码并相互交谈。

The first type of account is probably the most familiar for the average user who uses the network. Its name is EOA (Externally Owned Account); it is used to transmit value (such as Ether) and is controlled by a private key.

对于使用网络的普通用户来说,第一种类型的账户可能是最熟悉的。它的名字是EOA(外部拥有的账户);它被用来传输价值(如Ether),并由一个私人密钥控制。

On the other hand, there is another type of account which is the contract. Let’s go ahead and see what is this about:

另一方面,还有另一种类型的账户,即合同。让我们继续看看这是什么情况。

3. What Is a Smart Contract?

3.什么是智能合约?

A smart contract is a stand-alone script usually written in Solidity and compiled into binary or JSON and deployed to a specific address on the blockchain. In the same way that we can call a specific URL endpoint of a RESTful API to execute some logic through an HttpRequest, we can similarly execute the deployed smart contract at a specific address by submitting the correct data along with the necessary Ethereum to call the deployed and compiled Solidity function.

一个智能合约是一个独立的脚本,通常用Solidity编写并编译成二进制或JSON,然后部署到区块链上的一个特定地址。就像我们可以通过HttpRequest调用RESTful API的特定URL端点来执行一些逻辑一样,我们同样可以在特定的地址执行部署的智能合约,通过提交正确的数据以及必要的以太坊来调用部署和编译的Solidity函数

From a business standpoint, it means that smart contract functions can be inherently monetized (similar to an AWS Lambda function which allows users to pay per compute cycle rather than per instance). Importantly, smart contract functions don’t have to cost Ethereum to be run.

从商业角度来看,这意味着智能合约功能可以内在地货币化(类似于AWS Lambda功能,它允许用户按计算周期而不是按实例付费)。重要的是,智能合约功能不一定要花费以太坊才能运行。

In simple terms, we can see a smart contract as a collection of code stored in the blockchain network that defines conditions to which all parties using the contract agree upon.

简单来说,我们可以把智能合约看作是存储在区块链网络中的代码集合,它定义了使用该合约的所有各方同意的条件。

This enables developers to create things that haven’t been invented yet. Think about it for a second – there is no need for a middleman, and there is also no counterparty risk. We can create new markets, store registries of debts or promises and rest assure that we have the consensuses of the network that validates the transactions.

这使开发者能够创造出尚未被发明的东西。想一想吧–不需要中间人,也没有对手方风险。我们可以创建新的市场,存储债务或承诺的登记册,并保证我们有验证交易的网络的同意。

Anyone can deploy a smart contract to the decentralized database for a fee proportional to the storage size of the containing code. Nodes wishing to use the smart contract must somehow indicate the result of their participation to the rest of the network.

任何人都可以将智能合约部署到去中心化的数据库中,其费用与包含代码的存储大小成正比。希望使用智能合约的节点必须以某种方式向网络的其他部分表明其参与的结果。

3.1. Solidity

3.1.稳固性

The main language used in Ethereum is Solidity – which is a Javascript-like language developed specifically for writing smart contracts. Solidity is statically typed, supports inheritance, libraries and complex user-defined types among other features.

以太坊使用的主要语言是Solidity – 这是一种专门为编写智能合约而开发的类似Javascript的语言。Solidity是静态类型的,支持继承、库和复杂的用户定义类型以及其他功能。

The solidity compiler turns code into EVM bytecode, which can then be sent to the Ethereum network as a deployment transaction. Such deployments have more substantial transaction fees than smart contract interactions and must be paid by the owner of the contract.

solidity编译器将代码变成EVM字节码,然后可以作为部署交易发送到Ethereum网络。这种部署的交易费用比智能合约的互动更为可观,必须由合约的所有者支付。

4. Creating a Smart Contract With Solidity

4.用Solidity创建一个智能合约

The first line in a solidity contract sets the source code version. This is to ensure that the contract doesn’t suddenly behave differently with a new compiler version.

solidity合约的第一行设置了源代码的版本。这是为了确保合同在新的编译器版本下不会突然出现不同的行为。

pragma solidity ^0.4.0;

For our example, the name of the contract is Greeting and as we can see the creation of it’s similar to a class in Java or another object-oriented programming language:

对于我们的例子,合同的名称是Greeting,我们可以看到它的创建类似于Java或其他面向对象编程语言中的类。

contract Greeting {
    address creator;
    string message;

    // functions that interact with state variables
}

In this example, we declared two states variables: creator and message. In Solidity, we use the data type named address to store addresses of accounts.

在这个例子中,我们声明了两个状态变量。创建者消息。在 Solidity 中,我们使用名为 address 的数据类型来存储账户的地址。

Next, we need to initialize both variables in the constructor.

接下来,我们需要在构造函数中初始化这两个变量。

4.1. Constructor

4.1.构造函数

We declare a constructor by using the function keyword followed by the name of the contract (just like in Java).

我们通过使用function 关键字和契约的名称来声明一个构造函数(就像在Java中)。

The constructor is a special function that is invoked only once when a contract is first deployed to the Ethereum blockchain. We can only declare a single constructor for a contract:

构造函数是一个特殊的函数,在合约首次部署到以太坊区块链时只被调用一次。我们只能为一个合约声明一个构造函数。

function Greeting(string _message) {
    message = _message;
    creator = msg.sender;
}

We also inject the initial string _message as a parameter into the constructor and set it to the message state variable.

我们还将初始字符串_message作为一个参数注入构造函数,并将其设置为message状态变量。

In the second line of the constructor, we initialize the creator variable to a value called msg.sender. The reason why there’s no need for injecting msg into the constructor is because msg is a global variable that provides specific information about the message such as the address of the account sending it.

在构造函数的第二行,我们将creator变量初始化为一个名为msg.sender的值。之所以不需要将msg注入构造函数,是因为msg是一个全局变量,它提供了关于消息的具体信息,如发送消息的账户地址。

We could potentially use this information to implement access control for certain functions.

我们有可能使用这些信息来实现对某些功能的访问控制。

4.2. Setter and Getter Methods

4.2.设置器和获取器方法

Finally, we implement the setter and getter methods for the message:

最后,我们为message实现setter和getter方法:

function greet() constant returns (string) {
    return message;
}

function setGreeting(string _message) {
    message = _message;
}

Invoking the function greet will simply return the currently saved message. We use the constant keyword to specify that this function doesn’t modify the contract state and doesn’t trigger any writes to the blockchain.

调用函数greet将简单地返回当前保存的message。我们使用constant关键字来指定这个函数不会修改合约状态,也不会触发对区块链的任何写入。

We can now change the value of the state in the contract by calling the function setGreeting. Anyone can alter the value just by calling this function. This method doesn’t have a return type but does take a String type as a parameter.

现在我们可以通过调用函数setGreeting来改变合同中的状态值。任何人都可以仅仅通过调用这个函数来改变值。这个方法没有返回类型,但会接收一个String类型作为参数。

Now that we’ve created our first smart contract the next step will be to deploy it into the Ethereum blockchain so everybody can use it. We can use Remix, which’s currently the best online IDE and it’s effortless to use.

现在我们已经创建了我们的第一个智能合约,下一步将是把它部署到以太坊区块链中,以便每个人都能使用它。我们可以使用Remix,它是目前最好的在线IDE,使用起来毫不费力。

5. Interacting With a Smart Contract

5.与智能合约的互动

To interact with a smart contract in the decentralized network (blockchain) we need to have access to one of the clients.

为了与去中心化网络(区块链)中的智能合约互动,我们需要访问其中一个客户端。

There’re two ways to do this:

有两种方法可以做到这一点。

Infura is the most straightforward option, so we’ll request a free access token. Once we sign up, we need to pick the URL of the Rinkeby test network: “https://rinkeby.infura.io/<token>”.

Infura是最直接的选择,所以我们将申请一个免费访问令牌。一旦我们注册,我们需要选择Rinkeby测试网络的URL。“https://rinkeby.infura.io/<token>”.

To be able to transact with the smart contract from Java, we need to use a library called Web3j. Here is the Maven dependency:

为了能够从Java中与智能合约进行交易,我们需要使用一个名为Web3j的库。以下是Maven的依赖性。

<dependency>
    <groupId>org.web3j</groupId>
    <artifactId>core</artifactId>
    <version>3.3.1</version>
</dependency>

And in Gradle:

而在Gradle中。

compile ('org.web3j:core:3.3.1')

Before starting to write code, there are some things that we need to do first.

在开始写代码之前,有一些事情我们需要先做。

5.1. Creating a Wallet

5.1.创建一个钱包

Web3j allow us to use some of its functionality from the command line:

Web3j允许我们从命令行中使用它的一些功能。

  • Wallet creation
  • Wallet password management
  • Transfer of funds from one wallet to another
  • Generate Solidity smart contract function wrappers

Command line tools can be obtained as a zip file/tarball from the releases page of the project repository, under the downloads section, or for OS X users via homebrew:

命令行工具可以从项目库的releases页面的下载部分获得zip文件/arball,或者对于OS X用户,可以通过homebrew获得。

brew tap web3j/web3j
brew install web3j

To generate a new Ethereum wallet we simply type the following on the command line:

要生成一个新的Ethereum钱包,我们只需在命令行中输入以下内容。

$ web3j wallet create

It will ask us for a password and a location where we can save our wallet. The file is in Json format, and the main thing to keep in mind is the Ethereum address.

它会要求我们提供一个密码和一个可以保存钱包的位置。该文件为Json格式,主要需要记住的是以太坊地址。

We’ll use it in the next step to request an Ether.

我们将在下一步使用它来申请一个以太。

5.2. Requesting Ether in the Rinkeby Testnet

5.2.在Rinkeby Testnet中请求使用以太网

We can request free Ether here. To prevent malicious actors from exhausting all available funds, they ask us to provide a public link to one social media post with our Ethereum address.

我们可以申请免费的以太币这里。为了防止恶意行为者耗尽所有可用的资金,他们要求我们提供一个公开的链接,在社交媒体上发布一个以太坊地址。

This is a very simple step, almost instantly they provide the Ether so we can run the tests.

这是一个非常简单的步骤,几乎是瞬间他们就提供了以太币,这样我们就可以运行测试。

5.3. Generating the Smart Contract Wrapper

5.3.生成智能合约封装器

Web3j can auto-generate smart contract wrapper code to deploy and interact with smart contracts without leaving the JVM.

Web3j可以自动生成智能合约包装代码,在不离开JVM的情况下部署智能合约并与之互动。

To generate the wrapper code, we need to compile our smart contract. We can find the instruction to install the compiler here. From there, we type the following on the command line:

为了生成封装代码,我们需要对我们的智能合约进行编译。我们可以在这里找到安装编译器的说明。从那里,我们在命令行中输入以下内容。

$ solc Greeting.sol --bin --abi --optimize -o <output_dir>/

The latter will create two files: Greeting.bin and Greeting.abi. Now, we can generate the wrapper code using web3j’s command line tools:

后者将创建两个文件。Greeting.binGreeting.abi.现在,我们可以使用web3j的命令行工具生成封装代码。

$ web3j solidity generate /path/to/Greeting.bin 
  /path/to/Greeting.abi -o /path/to/src/main/java -p com.your.organisation.name

With this, we’ll now have the Java class to interact with the contract in our main code.

有了这个,我们现在就有了Java类,可以在我们的主代码中与合同互动。

6. Interacting With the Smart Contract

6.与智能合约的互动

In our main class, we start by creating a new web3j instance to connect to remote nodes on the network:

在我们的主类中,我们首先创建一个新的web3j实例来连接到网络上的远程节点。

Web3j web3j = Web3j.build(
  new HttpService("https://rinkeby.infura.io/<your_token>"));

We then need to load our Ethereum wallet file:

然后我们需要加载我们的Ethereum钱包文件。

Credentials credentials = WalletUtils.loadCredentials(
  "<password>",
 "/path/to/<walletfile>");

Now let’s deploy our smart contract:

现在让我们来部署我们的智能合约。

Greeting contract = Greeting.deploy(
  web3j, credentials,
  ManagedTransaction.GAS_PRICE, Contract.GAS_LIMIT,
  "Hello blockchain world!").send();

Deploying the contract may take a while depending the work in the network. Once is deployed, we might want to store the address where the contract was deployed. We can obtain the address this way:

部署合同可能需要一段时间,这取决于网络中的工作情况。一旦部署完毕,我们可能想存储合同部署的地址。我们可以通过这种方式获得该地址。

String contractAddress = contract.getContractAddress();

All the transactions made with the contract can be seen in the url: “https://rinkeby.etherscan.io/address/<contract_address>”.

所有与该合同进行的交易都可以在网址上看到。”https://rinkeby.etherscan.io/address/<contract_address>”。

On the other hand, we can modify the value of the smart contract performing a transaction:

另一方面,我们可以修改执行交易的智能合约的价值。

TransactionReceipt transactionReceipt = contract.setGreeting("Hello again").send();

Finally, if we want to view the new value stored, we can simply write:

最后,如果我们想查看存储的新值,我们可以简单地写。

String newValue = contract.greet().send();

7. Conclusion

7.结论

In this tutorial, we saw that Solidity is a statically-typed programming language designed for developing smart contracts that run on the EVM.

在本教程中,我们看到Solidity是一种静态类型的编程语言,用于开发在EVM上运行的智能合约。

We also created a straightforward contract with this language and saw that it’s very similar to other programming languages.

我们还用这种语言创建了一个简单明了的合同,看到它与其他编程语言非常相似。

The smart contract is just a phrase used to describe computer code that can facilitate the exchange of value. When running on the blockchain, a smart contract becomes a self-operating computer program that automatically executes when specific conditions are met.

智能合约只是一个用来描述能够促进价值交换的计算机代码的短语。在区块链上运行时,智能合约成为一个自我操作的计算机程序,在满足特定条件时自动执行。

We saw in this article that the ability to run code in the blockchain is the main differentiation in Ethereum because it allows developers to build a new type of applications that go way beyond anything we have seen before.

我们在这篇文章中看到,在区块链中运行代码的能力是以太坊的主要差异化,因为它允许开发者建立一种新型的应用程序,远远超出了我们以前所看到的任何东西。

As always, code samples can be found over on GitHub.

一如既往,代码样本可以在GitHub上找到over