Eth101: Solidity语言学习-1:Hello,World!

in #solidity7 years ago (edited)

taichi-boxing.jpg
Solidity是以太坊用来编写智能合约的高级语言,语法类似于Java,需要编译。

安装

如果你只是想尝试一个使用Solidity的小合约,你不需要安装任何东西,只要访问 基于浏览器的Solidity。
或者使用npm(不知道?搜一下,或者看看《Eth101:以太坊开发环境部署》)安装:
npm install solc

Hello, World

先看看hello world,直观了解一下:

pragma solidity ^0.4.18;
contract hello {
    string greeting;

    function hello(string _greeting) public {
        greeting = _greeting;
    }

function say() constant public returns (string) {
        return greeting;
    }
}

第一行:pragma一句,表示这段代码可以在solidity编译器0.4.18版本以上(0.5.0以下,因为有大改)执行。
第二行:contract,直接理解成class,没毛病!
这里声明了一个字符串成员greeting,还有两个方法hello()和say()。
Solidity是图灵完备的语言,简单理解就是C、Java这些高级语言有的,什么变量类型、无限循环等等,咱基本上都有。实际上,Solidity有很多语言的影子,比如合同声明,跟Java的类相似;同时对结构体的声明、对内存的操作等等,又接近于C,甚至还内嵌了汇编语言Assembly的一些语句,就是说,使用这门语言可以将内存操作写得很深入。
下面是一个完整的例子(看不懂不要紧)。

一个完整的例子:投票

设想一个针对提案进行投票的例子,提案有若干个,每人一票,投票给其中一个提案,也可以委托给他人。

/// @title Voting with delegation.
/// @title 授权投票
   contract Ballot
   {
      // 这里声明了复杂类型
        // 将会在被后面的参数使用
          // 代表一个独立的投票人。
       struct Voter
       {
           uint weight; // 累积的权重。
           bool voted;  // 如果为真,则表示该投票人已经投票。
           address delegate; // 委托的投票代表
           uint vote;   // 投票选择的提案索引号
       }

      // 这是一个独立提案的类型
       struct Proposal
       {
           bytes32 name;   // 短名称(32字节)
           uint voteCount; // 累计获得的票数
       }
   address public chairperson;
 //这里声明一个状态变量,保存每个独立地址的`Voter` 结构
   mapping(address => Voter) public voters;
   //一个存储`Proposal`结构的动态数组
   Proposal[] public proposals;

   // 创建一个新的投票用于选出一个提案名`proposalNames`.
   function Ballot(bytes32[] proposalNames)
   {
       chairperson = msg.sender;
       voters[chairperson].weight = 1;

       //对提供的每一个提案名称,创建一个新的提案
       //对象添加到数组末尾
       for (uint i = 0; i < proposalNames.length; i++)
           //`Proposal({...})` 创建了一个临时的提案对象,
           //`proposal.push(...)`添加到了提案数组`proposals`末尾。
           proposals.push(Proposal({
               name: proposalNames[i],
               voteCount: 0
           }));
   }

    //给投票人`voter`参加投票的投票权,
   //只能由投票主持人`chairperson`调用。
   function giveRightToVote(address voter)
   {
       if (msg.sender != chairperson || voters[voter].voted)
           //`throw`会终止和撤销所有的状态和以太改变。
          //如果函数调用无效,这通常是一个好的选择。
          //但是需要注意,这会消耗提供的所有gas。
           throw;
       voters[voter].weight = 1;
   }

   // 委托你的投票权到一个投票代表 `to`。
   function delegate(address to)
   {
       // 指定引用
       Voter sender = voters[msg.sender];
       if (sender.voted)
           throw;

       //当投票代表`to`也委托给别人时,寻找到最终的投票代表
       while (voters[to].delegate != address(0) &&
              voters[to].delegate != msg.sender)
           to = voters[to].delegate;
       // 当最终投票代表等于调用者,是不被允许的。
       if (to == msg.sender)
           throw;
       //因为`sender`是一个引用,
       //这里实际修改了`voters[msg.sender].voted`
       sender.voted = true;
       sender.delegate = to;
       Voter delegate = voters[to];
       if (delegate.voted)
           //如果委托的投票代表已经投票了,直接修改票数
           proposals[delegate.vote].voteCount += sender.weight;
       else
           //如果投票代表还没有投票,则修改其投票权重。
           delegate.weight += sender.weight;
   }

   ///投出你的选票(包括委托给你的选票)
   ///给 `proposals[proposal].name`。
   function vote(uint proposal)
   {
       Voter sender = voters[msg.sender];
       if (sender.voted) throw;
       sender.voted = true;
       sender.vote = proposal;
       //如果`proposal`索引超出了给定的提案数组范围
       //将会自动抛出异常,并撤销所有的改变。
       if (proposal >= proposals.length) throw;
       proposals[proposal].voteCount += sender.weight;
   }

  ///@dev 根据当前所有的投票计算出当前的胜出提案
   function winningProposal() constant
           returns (uint winningProposal)
   {
       uint winningVoteCount = 0;
       for (uint p = 0; p < proposals.length; p++)
       {
           if (proposals[p].voteCount > winningVoteCount)
           {
               winningVoteCount = proposals[p].voteCount;
               winningProposal = p;
           }
       }
   }
}

如果你看懂了上面的投票合约,恭喜你,你已经了解了Solidity语言的大部分;如果你一些地方没看懂,不要紧,我们继续下面的学习。

回到未来-11.png