[去 中 心 化]--社会需要进步

互联网之父呼吁软件工程师改造互联网

作者:Eureka

进入钱包,让我们创建一个代币。

如果你急的话,这是最后的代码:

contract tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData); }

contract MyToken { /* Public variables of the token */ string public standard = ‘Token 0.1’; string public name; string public symbol; uint8 public decimals; uint256 public totalSupply;

/* This creates an array with all balances */
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;

/* This generates a public event on the blockchain that will notify clients */
event Transfer(address indexed from, address indexed to, uint256 value);

/* Initializes contract with initial supply tokens to the creator of the contract */
function MyToken(
    uint256 initialSupply,
    string tokenName,
    uint8 decimalUnits,
    string tokenSymbol
    ) {
    balanceOf[msg.sender] = initialSupply;              // Give the creator all initial tokens
    totalSupply = initialSupply;                        // Update total supply
    name = tokenName;                                   // Set the name for display purposes
    symbol = tokenSymbol;                               // Set the symbol for display purposes
    decimals = decimalUnits;                            // Amount of decimals for display purposes
    msg.sender.send(msg.value);                         // Send back any ether sent accidentally
}

/* Send coins */
function transfer(address _to, uint256 _value) {
    if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
    if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
    balanceOf[msg.sender] -= _value;                     // Subtract from the sender
    balanceOf[_to] += _value;                            // Add the same to the recipient
    Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
}

/* Allow another contract to spend some tokens in your behalf */
function approve(address _spender, uint256 _value)
    returns (bool success) {
    allowance[msg.sender][_spender] = _value;
    return true;
}

/* Approve and then comunicate the approved contract in a single tx */
function approveAndCall(address _spender, uint256 _value, bytes _extraData)
    returns (bool success) {
    tokenRecipient spender = tokenRecipient(_spender);
    if (approve(_spender, _value)) {
        spender.receiveApproval(msg.sender, _value, this, _extraData);
        return true;
    }
}        

/* A contract attempts to get the coins */
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
    if (balanceOf[_from] < _value) throw;                 // Check if the sender has enough
    if (balanceOf[_to] + _value < balanceOf[_to]) throw;  // Check for overflows
    if (_value > allowance[_from][msg.sender]) throw;   // Check allowance
    balanceOf[_from] -= _value;                          // Subtract from the sender
    balanceOf[_to] += _value;                            // Add the same to the recipient
    allowance[_from][msg.sender] -= _value;
    Transfer(_from, _to, _value);
    return true;
}

/* This unnamed function is called whenever someone tries to send ether to it */
function () {
    throw;     // Prevents accidental sending of ether
}

}

让我们一步步的说明:

理解代码:

如果按上面步骤。

写入如下:

contract MyToken { /* This creates an array with all balances */ mapping (address => uint256) public balanceOf; }

mapping意味着一个关联数组。将余额和地址相关联。 地址是基本的以太坊16进制格式,余额是整数,范围从0到115quattuorvigintillion 如果你不知道quattuorvigintillion 是多少,它是很多vigintillion(1后63个零或120个零)比你见任何你想用在代币上的币还要多。public 关键字,意味着该变量可以在区块链上被会何人获取。意味着所有余额都是公开的(因为他们需要,为了让客户端显示它们)

如果你现在就发布你的合约,它能工作,但不是很有用:它将是一个能够查询任何地址的币的余额——代是既然没有创建一个币,每人地址都将返回0。所以我们得在开始时创建一些代币。将以下的代码放在最后的花括号之前,仅跟在mapping行之后。

function MyToken() { balanceOf[msg.sender] = 21000000; }

注意到函数 MyToken 同合约 MyToken使用了相同的名字。如果你要重命名一个,你还得重命名令一个:这是特别的,开始函数仅运行有且只有一次。当合约第一次上传到网络。该函数会设置msg.sender 余额,用户21M部署该合约。

21百万是随意的,你可以改成任何数字,还有更好的,作为参数传入,如下:

function MyToken(uint256 initialSupply) { balanceOf[msg.sender] = initialSupply; }

这时,在部署合约的右边栏,我们会看到一个下拉菜单,写着“选一个合约”。选择“MyToken”合约,这时我们看到了“Constructor Parameters”部分。这是可变的参数。因此,我们可以在以后重用这些代码。

当前,你有个函数合约创建了代币的余额。但是没有任何转移它的函数,所有做的都是让它耽在同一账号下。所以我们现在来实现它。在最后的花括号前写入下面的代码: /* Send coins / function transfer(address _to, uint256 _value) { / Add and subtract new balances */ balanceOf[msg.sender] -= _value; balanceOf[_to] += _value; }

这些代码很直白:接收者和值作为参数,不管什么时候有人调用它,它将会减f去 _value 的值,并给 _to 账号增加相应的值。现在,有一个明显的问题:如果有人想要发出比它拥有更多的会发生什么?既然我们不想在这个特定的合约中处理负值。我们只要简单的检查该账号是不是不够,并停止执行。同时还要检查溢出,以防止数值过大使其再次变成零。

要在中间停止执行,你可以用return 和 throw。前者耗费更少的gas,但是让人更头痛,因为任何对合约的改变都将保持 。另一方面,‘throw’将取消所有的合约执行,将交易的任何改变反转,发送者将损失所有ether。但是钱包能检测到throw,并决是显示警告,所以可以阻止任何ether被花费掉。

function transfer(address _to, uint256 _value) { /* Check if sender has balance and for overflows */ if (balanceOf[msg.sender] < _value || balanceOf[_to] + _value < balanceOf[_to]) throw;

/* Add and subtract new balances */
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;

}

现在我们缺少一些该合约的基本信息。将来这个能通过代币注册处理。但是现在,我们直接在合约中添加。

string public name; string public symbol; uint8 public decimals;

现在更新构造函数,允许所有这些变量在开始时设置:

/* Initializes contract with initial supply tokens to the creator of the contract */ function MyToken(uint256 initialSupply, string tokenName, uint8 decimalUnits, string tokenSymbol) { balanceOf[msg.sender] = initialSupply; // Give the creator all initial tokens name = tokenName; // Set the name for display purposes symbol = tokenSymbol; // Set the symbol for display purposes decimals = decimalUnits; // Amount of decimals for display purposes }

最后,我们需要一些叫 事件 的东。这些特殊的空的函数,你调用用来帮助象以太钱包这样的客户端跟踪合约的活动。事件以大小字母开头。将这一行添加到合约开始处:

event Transfer(address indexed from, address indexed to, uint256 value);

然后,将这两行放到transfer函数中:

/* Notify anyone listening that this transfer took place */
Transfer(msg.sender, _to, _value);

好了,你的代币成了!


下面您可根据自己的喜好分别使用“Disqus”或者“多说”进行留言评论: