区块链学堂(第八课):合约页面&部署合约+代币Token合约详解+Transaction

陈琳 发布在 竞争币 1 3698

Mist 中的合约页面

点击Mist页面中的Contracts,可以看到合约页面

p1

点击按钮 Deploy New Contract 按钮,可以部署一个新的合约,我们点击该按钮, 会看到的上方界面如下:

p2

  • 在From中我们可以选择一个账户,Main Account/account 1, 选择哪个账户,那么那个账户就是该合约的创建者。
    那么在构造函数中的msg.sender也就是谁,而同样的变量owner也就是那个账户的地址。

    contract Token {
    ...
    address public owner;
    function Token() {
      owner = msg.sender;
      ...
    }
    
  • Amount这里指的是支付给该智能合约的以太币,之前说过,在以太坊中的架构中,智能合约被看作一个特殊的账户,因此智能合约也能和其他账户一样进行交易,可以接受以太币,也可以付出以太币。
    这样的特性,在我们的金融化应用中非常有用,例如众筹合约等。
  • 当然目前是一个代币合约,因此这里不需要给智能合约支付任何以太币。
Mist下半部分界面
  • 在代码界面,我们贴上下方的代码,
pragma solidity 0.4.8;
contract Token {
  mapping (address => uint) public balancesOf;
  address public owner;
  function Token() {
    owner = msg.sender;
    balancesOf[msg.sender] = 10000;
  }

  function transfer(address _to, uint _value) {
    if (balancesOf[msg.sender] < _value) throw; //避免转移出去的代币超过当前的存货
    if (balancesOf[_to] + _value < balancesOf[_to]) throw; //避免自己调用自己,或者递归调用
    balancesOf[msg.sender] -= _value;
    balancesOf[_to] += _value;
  }

  function mint(uint _amount) {
    balancesOf[owner] += _amount;
  }
}

所看到的结果如下:

p3

  • 如上图中2所示,只要我们将合约代码贴上去,如果编译通过的话,我们就会看到Mist自动读取出来了我们需要Deploy的合约名称。即Contract Token.
  • 注意:合约的首字母需要为大写,尤其是在多个合约的时候,程序会优先认为首字母为大写的是主合约

  • 如上图3中所示,我们可以设置合约的部署速度。之前说过合约是一个特殊账户,而任何账户之间的transaction都需要消耗Gas, Gas由合约本身决定,而每百万gas的以太币则由Oracle来决定,价格越贵速度越快优先级越高,价格越便宜速度越慢优先级越低。
  • 消耗Gas就是消耗以太币,因此用任何账户来部署合约,都必须要输入密码。
  • 以上概念都是重复之前所说的,之后不再复述

Deploy页面解析
  • 点击下方的Deploy按钮,我们可以看到弹出的这个页面

p4

  • 合约是特殊的账户,deploy合约在以太坊底层就是一个账户到另一个账户的一个Transaction
  • 记得一定要修改下Provide maximum fee 里面的Gas数量。因为一个合约除了部署之外,还需要执行构造函数,并部署数据,Gas不足的话,会导致部署失败。

p5

  • Raw Data就是合约代码的编译后的bytecode, 输入密码,并点击Send Transaction 便可完成合约部署
部署完毕后的合约页面是这样的

p6

为什么合约没有第一时间出来呢,因为任何合约是一个特殊账户,任何特殊账户之间的Transaction都需要挖矿挖出来,并得到各个区块的确认。

过了一段时间之后,我们可以看到合约出现了。

p6

至此我们已经完成了合约的部署,下章中我们将详细阐述一下Token合约的各个函数和变量

—————————————————————————-

代币合约代码如下:

pragma solidity 0.4.8;
contract Token {
  mapping (address => uint) public balancesOf;
  address public owner;
  function Token() {
    owner = msg.sender;
    balancesOf[msg.sender] = 10000;
  }

  function transfer(address _to, uint _value) {
    if (balancesOf[msg.sender] < _value) throw; //避免转移出去的代币超过当前的存货
    if (balancesOf[_to] + _value < balancesOf[_to]) throw; //避免自己调用自己,或者递归调用
    balancesOf[msg.sender] -= _value;
    balancesOf[_to] += _value;
  }

  function mint(uint _amount) {
    balancesOf[owner] += _amount;
  }
}
  • 从上面的代码中我们可以看到,总共有两个属性balancesOf 和owner
  • 另外还有两个方法mint()和 transfer()

智能合约的属性balancesOf & owner

我们在合约界面点开Token合约。

  • 可以看到左侧是该合约两个属性balancesOf & owner
    p8
  • 构造函数中写了代码owner=msg.sender,因此谁创建合约,owner这个变量就是msg.sender。此处owner=account1 也就是account 1创建了本合约。
  • balancesOf[msg.sender] = 10000; 所以owner在数组balancesOf中的值就是10000
  • 同理的balancesOf[Main Account] 就应该为0,我们从geth中可以轻松得到eth.accounts[0] & eth.accounts[1]的地址。
> eth.accounts
["0x48ad44beba68a981e103d28b2bd5777ef21ba0e3", "0x66f44c178a2337e40355bd4b5442229cda24f803"]

然后查看变量balancesOf["0x48ad44beba68a981e103d28b2bd5777ef21ba0e3"] 如图所示:
p9

智能合约的方法 mint()

  • 方法 mint() 中的代码是 balancesOf[owner] += _amount;, 因此无论输入多少,增加值都只会增加到balancesOf[owner]的数据上去。
  • 我们选择右侧的方法Mint, 设置amount = 1000, 如下图所示

p10

  • 点击Execute按钮, 如下图所示

p11

  • 带锁icon的是以太坊普通账户,而带合约的是智能合约账户。之前说过智能合约也是一个特殊的账户。
  • 同样执行任何transaction都需要gas,谁执行谁承担gas,在上面选择中,我们选择了main account那么相应的gas就由main account承担
  • raw data: 是代表传递给该合约的具体数据,这个里面的包含了一个短地址, 代表执行function mint(),还有一个传递的数据1000,也就是16进制0x3e8.
  • 输入密码后,点击send transaction,然后等待一段挖矿的时间之后,结果如下图所示, 可以看到balancesOf[owner] 增加了1000;

p12

智能合约的方法 transfer()

  • 方法transfer() 中的核心代码是
    balancesOf[msg.sender] -= _value;
    balancesOf[_to] += _value;
    

    也就是说msg.sender的账户会减少一定数额,而_to会增加一定数额
    因此我们调用transfer密码,并设置如下

p13

  • 点击execute后,输入账号密码,执行该方法transfer()
  • 执行的结果如下:balancesOf[account1]=10700balancesOf[main account]=300
  • 如下图所示:

p14

p15

至此我们已经介绍了Mist中的账户页面,合约页面,以及部署合约和合约的属性和方法

下一章我们将重点介绍一下以太坊的另一个核心:Transaction

—————————————————————

Mist中的基本概念回顾

以太坊账户体系
  • 一种是普通的以太坊账户,这类账户由一对公钥和私钥组成。公钥就是该账号的地址,是可以公开的。秘钥是密码的一段加密hash值。私钥一定要保存妥当,一旦遗失,就无法证明 你是你 这个难题。
  • 一种是合约账户,一种特殊的账户,由代码所组成的账户。这种账户也可以像普通账户一样接收以太币,或者发放以太币,同时还可以通过EVM来执行智能合约里面的方法,从而实现商业应用。

** 这些账户我们在前面章节的实际操作中已经有了较深的理解。

Transactions
  • 账户和账户之间的交易,都是通过Transactions来执行的,例如eth.accounts[0] 要发送100以太币给eth.accounts[1], 这个时候所执行的Transaction如下所示

p16

  • 又比如我们执行Token合约中的mint()方法,从区块链底层看来就是从msg.sender智能合约地址,发送一个transaction, 只不过这个transaction的地址是智能合约的地址,同时还带上了一个RawData罢了。如图所示:

p17

Blocks

Blocks也就是区块,区块链区块链,顾名思义,就是由区块链接起来的一个分布式数据库。任何账户之间的变动,都必须被新挖出的Blocks计入他们的账本,且被多个区块所认可,那么此时这个交易才算真正生效。否则是无效的。

普通账户之间以太币转移的Transaction

我们可以重复一遍4.2中的操作,从Main Account再转100 以太币到Account 1. 然后立刻打开Main Account的页面,我们看到的Latest Transactions是这样的。

p18

  • 过了一段时间之后变成了下图所示:

  • 点击该Transaction可以看到Transaction的细节

p20

可以很清晰的看到对于一个Transactions来说,他也有自己的地址,也需要被挖矿挖掘出来并记账,并被多个区块所确认。

智能合约调用的Transaction

我们可以打开Token合约,重新调用token合约中的mint()方法,然后打开transaction,查看细节如图:

p21

  • 从上图我们可以很清晰的看到调用智能合约,
  • 就是给智能合约的地址发送transaction
  • 除此之外,还需要给到rawdata, 从而实现调用智能合约中的方法的功能,例如mint()
Transaction的概念很重要,有的时候我们发现调用某个智能合约功能不生效时候,我们需要多去看看Transaction就可以知道到底执行情况如何。
发文时比特币标准价格 买价:¥7041.00 卖价:¥6787.00
作者:陈琳(以太中文网创始人) 版权声明: by nc" sa 作者保留权利。文章为作者独立观点,不代表巴比特立场。

评论:1

您需要登录后才可以回复 登录|注册

    Amount这里指的是支付给该智能合约的以太币,之前说过,在以太坊中的架构中,智能合约被看作一个特殊的账户,因此智能合约也能和其他账户一样进行交易,可以接受以太币,也可以付出以太币。

    +1
    +1
    我要点评