这一篇分析一下metacoin的合约代码。
智能合约是一组数据和代码的集合,合约部署到链上以后会产生一个地址,外部通过该地址调用合约代码来改变或者查询合约的数据(状态)。
metacoin合约是用Solidity语言编写的,通过solc编译成字节码,然后在发生外部访问时被以太坊虚拟机EVM执行。
Solidity是一种跟Java很类似的语言,所以代码读起来也不怎么费劲。我们先看一下MetaCoin.sol的代码,一行一行地看:
pragma solidity ^0.4.18;
第一行是声明Solidity的版本,保证代码的兼容性。
import "./ConvertLib.sol";
这一行通过import关键字导入外部类库ConvertLib。
contract MetaCoin {
mapping (address => uint) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
... ...
}
Truffle要求合约的名次必须和文件名一致,并且只能使用contract和library这两个关键字。紧接着声明了两个全局变量:
● balances:用于存储所有账户的余额。这个变量是mapping类型,其实就理解为HashMap,key是address类型,value是uint类型。address类型大小是160bit,用于存储账户地址或者合约地址。
● Transfer:这是一个event类型的变量,该事件会在sendCoin()方法中被触发。客户端可以通过watch()方法来监听区块链上触发的事件,用于跟踪交易。
function MetaCoin() public {
balances[tx.origin] = 10000;
}
接下来就是合约的构造函数了,合约的构造函数只会在创建合约时被调用一次,之后就永远不会被调用了(可以理解为new了一个全局的单例对象)。tx是一个全局变量,表示当前的transaction,也就是创建合约的这个transaction。所以执行这个构造函数就是往合约的创始人账号里打了10000个MetaCoin。
function sendCoin(address receiver, uint amount) public returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Transfer(msg.sender, receiver, amount);
return true;
}
接下来看sendCoin()函数:参数是接收人地址以及发送代币的数量,返回是否发送成功。Solidity的语法比较有意思,跟Java相比,Solidity的权限修饰符以及返回值都是写在右边的。。。
第一步就是判断发送人是否有足够的余额。msg也是一个全局变量,msg.sender就是这次调用发起人的地址。这些全局变量可以获取和当前transaction相关的一些区块链属性,完整列表参见:
http://solidity.readthedocs.io/en/develop/units-and-global-variables.html
接下来的2行很好理解,发送账号余额减少,接收账号余额增加。紧接着下一行就是触发Transfer事件,从而外部监听者可以收到通知。
function getBalanceInEth(address addr) public view returns(uint){
return ConvertLib.convert(getBalance(addr),2);
}
function getBalance(address addr) public view returns(uint) {
return balances[addr];
}
最后两个函数是查询接口,返回MetaCoin余额以及转换成ETH的余额。这里用到刚开始导入的ConvertLib类库,那我们就来看看这个ConvertLib.sol:
pragma solidity ^0.4.4;
library ConvertLib{
function convert(uint amount,uint conversionRate) public pure returns (uint convertedAmount)
{
return amount * conversionRate;
}
}
代码非常简单,就是把余额乘上一个转换率,之前传的转换率是2,也就是说一个MetaCoin值2个ETH。
最后我们看下合约编译后的输出:
编译结果是用JSON的形式组织的,包含了EVM字节码以及供外部调用的ABI格式:
至此,metacoin的合约代码就分析完了,是不是很简单呢?下一篇分析一下metacoin的测试代码。
欢迎关注飞久微信公众号,一起探讨更多技术问题: