**** 1. 发固定数量的币: 务必务必看这个, 看这个就够了 *** 最新版看这里: (我自己整理的文档) 最新整理的文档, 2019-10-16日, 发币的时候要多加18个0.
**** 2. 发数量不定,可以挖矿,可以销毁:看这个。 http://showmethemoney.sweetysoft.com/image_after_2019_06/1869/%E4%BD%BF%E7%94%A8remix%20%E5%8F%91%E6%94%BE%E5%8F%AF%E4%BB%A5%E6%8C%96%E7%9F%BF%E7%9A%84erc-20%E5%B8%81%E7%A7%8D.doc
这个是老版的文件,不要看: (我整理的文档) (2018年的)
参考: https://github.com/ethereum/mist/issues/2466 中, @rafaelosirs 的回答。
(原文放在最后吧。)
注意: 要记得使用 SafeMath 来发币,所以要参考: https://hackernoon.com/create-your-own-ethereum-token-bfa6302084da
首先是三大段代码:
SafeMath.sol
pragma solidity ^0.4.10; library SafeMath { function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; assert(c / a == b); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; assert(c >= a); return c; } }
ERC-20
pragma solidity ^0.4.10; interface ERC20 { function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); }
YourToken.sol
pragma solidity ^0.4.10; import 'browser/SafeMath.sol'; import 'browser/ERC20.sol'; contract TestMyToken is ERC20 { using SafeMath for uint; string internal _name; string internal _symbol; uint8 internal _decimals; uint256 internal _totalSupply; mapping (address => uint256) internal balances; mapping (address => mapping (address => uint256)) internal allowed; function TestMyToken(string name, string symbol, uint8 decimals, uint256 totalSupply) public { _symbol = symbol; _name = name; _decimals = decimals; _totalSupply = totalSupply; balances[msg.sender] = totalSupply; } function name() public view returns (string) { return _name; } function symbol() public view returns (string) { return _symbol; } function decimals() public view returns (uint8) { return _decimals; } function totalSupply() public view returns (uint256) { return _totalSupply; } function transfer(address _to, uint256 _value) public returns (bool) { require(_to != address(0)); require(_value <= balances[msg.sender]); balances[msg.sender] = SafeMath.sub(balances[msg.sender], _value); balances[_to] = SafeMath.add(balances[_to], _value); Transfer(msg.sender, _to, _value); return true; } function balanceOf(address _owner) public view returns (uint256 balance) { return balances[_owner]; } function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { require(_to != address(0)); require(_value <= balances[_from]); require(_value <= allowed[_from][msg.sender]); balances[_from] = SafeMath.sub(balances[_from], _value); balances[_to] = SafeMath.add(balances[_to], _value); allowed[_from][msg.sender] = SafeMath.sub(allowed[_from][msg.sender], _value); Transfer(_from, _to, _value); return true; } function approve(address _spender, uint256 _value) public returns (bool) { allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); return true; } function allowance(address _owner, address _spender) public view returns (uint256) { return allowed[_owner][_spender]; } function increaseApproval(address _spender, uint _addedValue) public returns (bool) { allowed[msg.sender][_spender] = SafeMath.add(allowed[msg.sender][_spender], _addedValue); Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) { uint oldValue = allowed[msg.sender][_spender]; if (_subtractedValue > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = SafeMath.sub(oldValue, _subtractedValue); } Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } }
以上代码放到 remix 中即可。 然后交易费 先设置成0 gwei, 点击create
然后
下面是正式开始:
If you are in a pinch and have to deploy a contract, you don't need the full node sync, just follow this simple steps instead (i found in a post and help me a lot):
1.Install https://metamask.io/ and 下载meta mask, 并且安装,并且导入到你的账户。
2.打开这个网址Navigate to https://remix.ethereum.org/
3.选择好compiler(默认已经准备好了)
可以看到左侧大图:
放的是代码。
右侧:
4.登录meta mask. 选择网路成测试网络(这一步我没做,直接上生产环境)Login to metmask and choose your network (i would suggest first testing using ropsten test network and using the buy button to get ETH from a free faucet)
5.粘贴你的contract Go back to the compile tab,
Delete the contents of the example contract,
Paste in your contract (it should auto compile).
6.点击“Run”, 然后输入图片中的内容:
Click on the run tab
If you contract have input data you have tu put that data on double quoute (").
点击Create (2018-10-30 这里的按钮现在叫做 Deploy了。 而且Setting也变了样子。 不过记得继续使用对应的compiler version 就可以。 )
Metamask 就会弹出窗口。点击Submit就可以了。
Metamask will open, choose your gas price and click Submit to sign your transaction
这样,我们在 remix 上的工作就做完了。
然后,打开Metamask, 可以看到, contract正在部署当中 ( 2018-10-30 这里也变了。 需要25个确认之后, 才会出现)
点击上图中的 红色圆圈(transaction hash), 可以看到 这次创建contract的详细情况:
创建好之后, 进入到etherscan, 找到这个contract 地址,可以看到下图:
点击红色圆圈,
然后,填写各种内容:
notice: 1 : Contract Name: should be "SuperShopChain", not "Super Shop Chain" !!!!
notice: 2. if not pass, try "Verify Contract Code version 2"
然后, 点击 Verify and Publish 按钮, 大约10秒钟之后,就可以看到这个结果: (红色框框的地方,说明搞好了)
如果不放心的话,可以点击红色圆圈,再看一下。 如下图所示:
Once published. in etherscan go to the contract address and Click on Contract Code tab on etherscan, click Verify and Publish.
Set the name of the contract to the exact name as in remix, Compiler to the same exact version as in remix and set optimization to "No" if you didn't click it on remix in step 3.
然后,update 一下你的token 的信息就可以啦(貌似不需要注册?)
You should now have a published contract, with source code on etherscan.
最后的最后, 在 MetaMask中, 添加这个新造的币。
(如果只是从 etherscan.io中 看得话,看不到token holder. 需要在Metamask中手动添加这个token ,才会看到。
在imtoken中看不到, 需要手动在imtoken上添加repo才行。 见:https://github.com/consenlabs/token-profile)
P.S.
pragma solidity ^0.4.16; interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; } contract TicketGlobalChain { // Public variables of the token string public name; string public symbol; uint8 public decimals = 18; // 18 decimals is the strongly suggested default, avoid changing it 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); // This notifies clients about the amount burnt event Burn(address indexed from, uint256 value); /** * Constrctor function * * Initializes contract with initial supply tokens to the creator of the contract */ function TicketGlobalChain ( uint256 initialSupply, string tokenName, string tokenSymbol ) public { totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens name = tokenName; // Set the name for display purposes symbol = tokenSymbol; // Set the symbol for display purposes } /** * Internal transfer, only can be called by this contract */ function _transfer(address _from, address _to, uint _value) internal { // Prevent transfer to 0x0 address. Use burn() instead require(_to != 0x0); // Check if the sender has enough require(balanceOf[_from] >= _value); // Check for overflows require(balanceOf[_to] + _value > balanceOf[_to]); // Save this for an assertion in the future uint previousBalances = balanceOf[_from] + balanceOf[_to]; // Subtract from the sender balanceOf[_from] -= _value; // Add the same to the recipient balanceOf[_to] += _value; Transfer(_from, _to, _value); // Asserts are used to use static analysis to find bugs in your code. They should never fail assert(balanceOf[_from] + balanceOf[_to] == previousBalances); } /** * Transfer tokens * * Send `_value` tokens to `_to` from your account * * @param _to The address of the recipient * @param _value the amount to send */ function transfer(address _to, uint256 _value) public { _transfer(msg.sender, _to, _value); } /** * Transfer tokens from other address * * Send `_value` tokens to `_to` on behalf of `_from` * * @param _from The address of the sender * @param _to The address of the recipient * @param _value the amount to send */ function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(_value <= allowance[_from][msg.sender]); // Check allowance allowance[_from][msg.sender] -= _value; _transfer(_from, _to, _value); return true; } /** * Set allowance for other address * * Allows `_spender` to spend no more than `_value` tokens on your behalf * * @param _spender The address authorized to spend * @param _value the max amount they can spend */ function approve(address _spender, uint256 _value) public returns (bool success) { allowance[msg.sender][_spender] = _value; return true; } /** * Set allowance for other address and notify * * Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it * * @param _spender The address authorized to spend * @param _value the max amount they can spend * @param _extraData some extra information to send to the approved contract */ function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { spender.receiveApproval(msg.sender, _value, this, _extraData); return true; } } /** * Destroy tokens * * Remove `_value` tokens from the system irreversibly * * @param _value the amount of money to burn */ function burn(uint256 _value) public returns (bool success) { require(balanceOf[msg.sender] >= _value); // Check if the sender has enough balanceOf[msg.sender] -= _value; // Subtract from the sender totalSupply -= _value; // Updates totalSupply Burn(msg.sender, _value); return true; } /** * Destroy tokens from other account * * Remove `_value` tokens from the system irreversibly on behalf of `_from`. * * @param _from the address of the sender * @param _value the amount of money to burn */ function burnFrom(address _from, uint256 _value) public returns (bool success) { require(balanceOf[_from] >= _value); // Check if the targeted balance is enough require(_value <= allowance[_from][msg.sender]); // Check allowance balanceOf[_from] -= _value; // Subtract from the targeted balance allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance totalSupply -= _value; // Update totalSupply Burn(_from, _value); return true; } }