解读简单的Solidity代币合约


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
pragma solidity ^0.5.1;
 
// 定义代币合约
contract Coin {
 
    // 定义一个公共的地址类型变量,名为minter(铸币者),只有TA才能生成代币
    address public minter;
 
    // 定义一个映射关系,类似于key-value的关系,保存了某个地址下代币数量的一个关系
    mapping (address => uint) public balances;
   
    // 交易发生的消息事件
    event Sent(address from, address to, uint amount);
   
    // 构造函数,只会在合约部署的时候执行一次。谁部署了合约,谁就是铸币者
    constructor() public{
        minter = msg.sender;
    }
   
    // 铸币功能
    function mint(address receiver, uint amount) public {
        // 如果调用此方法的不是铸币者,那么就会直接退出。
        if (msg.sender != minter) return;
        // 铸币者给接收者(receiver)的账户上添加代币,保存在balances中
        balances[receiver] += amount;
    }
   
    // 转账功能
    function send(address receiver, uint amount) public {
        // 检测调用此方法的账户,是否有足够的余额可以进行转账交易
        if (balances[msg.sender] < amount) return;
        // 先扣除转账者的代币
        balances[msg.sender] -= amount;
        // 再给接收者增加相应的代币数
        balances[receiver] += amount;
        // 发送交易成功的消息推送
        emit Sent(msg.sender, receiver, amount);
    }
}

此合约定义了Coin,并在构造函数中确定了合约的部署者即为当前代币合约的铸币者。

我们这样来理解,假设有:

账户A:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4

账户B:0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2

账户C:0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db

如果通过账户A部署了Coin合约,那么账户A就为该合约里的铸币者。此时也会生成一个合约的地址,这是区分不同合约的一个标识,这里可以类比为Java中实例对象的内存地址。(意思是:相同的一套合约代码,不同的账户部署了该合约,得到的合约地址是不一样的,生成的代币也是不一样的,而且是不互通,不能相互转账的。即使是相同的账户多次去部署同样的一份合约代码,也会生成不同的合约地址。这也就解释了为什么合约一旦发布,就不能修改的问题,因为合约已经存到区块链上了,区块链上的内容是不能修改的。)

此时,账户A可以调用mint() 方法进行铸币,铸币可以给自己,也可以给他人。即:mint方法的receiver参数,可以是A自己的账户地址,也可以是他人的地址。

如果账户B和C去调用了mint()方法,会在铸币者校验那里通不过,直接返回。

账户A、B、C都能调用send() 方法,只要有足够的余额,就可以给接收者进行代币转账。

Remix上操作截图