#### 准备工作
上一节中已经演示了如何通过`mcat`编译和部署合约,此处演示下怎么使用`mcat`来与合约进行交互。
部署合约后得到合约账户地址 `0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532`。 [合约](/luren5/84e531e75392765efbb7fde250d6c315)的内容比较简单,功能如下:
1、投票发起人可以给其它账户地址进行授权 `giveRightToVote()`
2、被授权的账户可以进行投票 `vote()`
3、最后可以实时查询投票最多的候选项的编号 `winningProposalIndex()` 和名字 `winnerName()`
根据前一节演示可以看到,部署合约的时候初始化了两个候选项`Hillary` 、`Trump` 编号依次是0 和1
#### 授权
授权操作只能是合约创建者来完成(当然这不是固定的,只是此处合约逻辑规定如此),所以此时还是使用`mcat.yaml`里面配置的那个账户来发起这笔交易。我这里有三个账户,第一个账户是合约的创建者,用它来给后两个账户授权
```
> personal.listAccounts
["0x0b9498ca74cd7814fba0c25e2a441c1d5867946a", "0xb01a8b45f7e01651eda132dbd6fb985a7022f171", "0x15cab6f047549b6ed7392feb5c217d3893a6acb6"]
```
可以看到`giveRightToVote(address voter, bytes32 voterName) `方法有两个参数,第一个是被授权账户的地址,第二个是投票人的名字
```
mcat call --addr="0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532" --contract="Ballot" --function="giveRightToVote" --params="0xb01a8b45f7e01651eda132dbd6fb985a7022f171&voter1"
```
调用成功并返回了这笔合约交易的`hash`, 开启挖矿让这笔交易被打包。 然后来验证下授权是否成功。
#### 验证授权是否成功
合约的状态变量`mapping(address => Voter) public voters;` 是用来记录所有已经被授权的地址的。由于它是`public`类型的合约状态变量,所以编译的时候会自动生成对应的`getter`方法`voters(addr)` (在abi里面可以看到),由于它只是读取数据不需要修改账本,所以它是`constant`类型的,此处调用`callConst`来查询
```
mcat callConst --addr="0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532" --contract="Ballot" --function="voters" --params="0xb01a8b45f7e01651eda132dbd6fb985a7022f171"
0xa3ec138d000000000000000000000000b01a8b45f7e01651eda132dbd6fb985a7022f171
0x766f746572310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000059b025e90000000000000000000000000000000000000000000000000000000000000000
```
`callConst` 和 `call` 用法类似,但是前者调的是`eth_call`接口,它只会查询区块链上的数据并即时返回结果,而后者是调用`eth_sendTransaction`接口,它会发起一笔交易(即使有constant关键字)并返回这笔交易的hash。
从返回的结果可以看出,它是一串经过编码的后的字节码,里面包含了`0xb01a8b45f7e01651eda132dbd6fb985a7022f171`voter的相关属性值, 关于怎么解码mcat正在开发在,将在下一个版本中发布。
由上可以看出,确实已经授权成功。如法炮制,给第三个地址授权
```
mcat call --addr="0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532" --contract="Ballot" --function="giveRightToVote" --params="0x15cab6f047549b6ed7392feb5c217d3893a6acb6&voter2"
```
#### 投票
现在我们用第二个地址,来给选项1(从0开始计数) `Trump`投一票
因为这里是用地址二`0xb01a8b45f7e01651eda132dbd6fb985a7022f171`来投票,也就是从这个地址发起一笔交易,所以我们需要修改下 `mcat.yaml`, 把development模式里面的账户地址和密码改成地址二的信息,然后执行`mcat loadConfig`重新加载一下配置
```
```
注意:真实情况下, 投票发起人(地址一)和被授权地址不会在一个节点,也不会是由同一个人掌握(否则自己给自己授权,然后自己再来投票,没有任何意义)。这里由于是演示,所以发起人和被授权地址在同一个节点里,所以需要改下mcat.yaml里面的配置,真实情况它们(授权 和 投票)应该分属于两个应用
```
// mcat.yaml
account: "0xb01a8b45f7e01651eda132dbd6fb985a7022f171"
password: "123456"
// 重新加载
mcat loadConfig
Succeed in loading mcat config.
```
开始投票
```
mcat call --addr="0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532" --contract="Ballot" --function="vote" --params="1"
```
等待打包
#### 查看投票结果
走完以上步骤后,地址`0xb01a8b45f7e01651eda132dbd6fb985a7022f171`给选项1`Trump`投了一票,而选项0还没有被投票,那么此时winnerIndex应该是0,winnerName应该是Trump,来验证一下
```
mcat callConst --addr="0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532" --contract="Ballot" --function="winningProposalIndex"
0x8ec36a3d
0x0000000000000000000000000000000000000000000000000000000000000001
mcat callConst --addr="0xd2548bb40fe57aa9e66aeafbc1f6a44c9d8b9532" --contract="Ballot" --function="winnerName"
0xe2ba53f0
0x5472756d70000000000000000000000000000000000000000000000000000000
```
结果如预期!
#### 小结
以上是纯手工调用mcat的命令来完成一个合约的调用过程,这适用于上线前的 调试,生产环境肯定是需要通过编码来自动化完成这些操作的,mcat也提供了相应的功能来满足需求,将在下一节中演示!
原文地址:/p/29123951