一夜身价暴涨千倍,程序员如何发布自己的 ICO?
点击上方“CSDN”,选择“置顶公众号”
关键时刻,第一时间送达!
本文来自作者 余博伦 在 GitChat 上分享 「韭菜种植与收割:发布你自己的 ICO」,仅供学习交流。封面图来自视觉中国。
【作者按】没有任何门槛的ICO为何割韭菜无数?万字长文带你一睹ICO技术的全貌,让你也能发token卖token,然而学会以后如何选择还是要从心呐~
人性本恶,技术无罪!
你可曾想梭哈全部存款,参与 ICO,一夜身价暴涨千倍,获得财富自由,从此走上人生巅峰?
ICO 是借用 IPO 生造出来的一种概念,同样具有非常相似的募资机制,但 IPO 有着严格的上市流程、政策监管,如下图所示。
即便如此,参与 IPO 仍然有着相当大的风险,且为股市带来了相当大的不稳定因素。而与 ICO 比起来简直就是小巫见大巫了。
一家公司想要进行 IPO 起码要达到能够上市的标准,而想发布 ICO 你只要有一个好听的 idea 就足够了。并且严重缺乏监管,虽然各国政府都在不断发出声明,但截至本分享写作前,也没有正式出台比较明朗的有关规定。
这也导致无数的空气项目披着虚拟货币和区块链的高科技壳,到处招摇撞骗割韭菜,有过之无不及的还搞什么 AI+ 区块链,IOT+ 区块链,技术名词堆积越多的项目,死得往往越快。
甚至一些有头有脸的大公司,也忍不住打打擦边球,收割一波,炒作炒作,股价就能翻几个涨停。
可就像马老爷子说的:
如果有 10% 的利润,它就保证到处被使用;有 20% 的利润,它就活跃起来;有 50% 的利润,它就铤而走险;为了 100% 的利润,它就敢践踏一切人间法律;有 300% 的利润,它就敢犯任何罪行,甚至绞首的危险。
即便如此,仍然有很多人跃跃欲试不信邪。这一场 Chat 就手把手教你为 ICO 做好所有技术面上的准备。在和大家一起点亮新技能的同时,也揭一揭所谓 ICO 的老底。
内容概要
目前市场上 99% 的项目 ICO 都是基于以太坊(Ethereum)智能合约(Smart Contracts)技术发布的 token(ERC20 Token)。
本次分享也是基于这一套技术栈,介绍内容包括以下几个方面。
本地开发环境构建
以太坊智能合约开发
本地开发环境发布
线上测试网络发布
主网络发布
ERC20 Token 合约开发
ICO Crowdsale 合约开发
补充说明与权限控制
合约的发布及调试
Dapp 开发
web3.js 的使用
Metamask 简介
truffle-contract 的使用
ICO 前端应用开发
Dapp 部署
IPNS
Nginx 反向代理
IPFS 简介
发布应用
域名解析
使用到的技术栈包括:
Truffle:http://truffleframework.com
[Ganache:http://truffleframework.com/ganache
Metamask:https://metamask.io
Solidity:http://solidity.readthedocs.io/en/develop
openzeppelin:https://openzeppelin.org
Infura:https://infura.io
web3.js:https://web3js.readthedocs.io/en/1.0/index.html
truffle-contract:https://github.com/trufflesuite/truffle-contract
ipfs:https://ipfs.io
对读者的基本要求有:
了解编程
会 JavaScript
本地开发环境构建
以太坊官方提供的 Mist (https://github.com/ethereum/mist/releases) 和 Ethereum-Wallet (https://github.com/ethereum/mist/releases)。
其中 Mist 是一个可以用来访问 Dapp 的浏览器,Ethereum-Wallet 是 Mist 的一个独立发布版本,也算是浏览器,但只能用来访问以太坊钱包这个应用。
在网络同步过程中或多或少都会遇到问题,而且目前网络拥堵,完整节点过大,同步完成相当困难。但事实上我们进行以太坊开发时并不需要同步完整的节点,也可以选择使用相应的模拟开发环境。
Truffle (http://truffleframework.com) 框架为你提供本地进行智能合约开发的所有依赖支持,使你可以在本地进行智能合约及 Dapp 的开发、编译、发布。安装非常简单,只需要:
npm install -g truffle
Ganache (http://truffleframework.com/ganache) 也是 Truffle 框架中提供的一个应用,可以在你的本地开启模拟一个以太坊节点,让你能够将开发好的智能合约发布至本地测试节点中运行调试。
安装也非常简单,官网下载即可,双击打开运行。
不过这里有一个隐藏的坑,如果你使用的是 Windows 系统的话,Ganache 提供的是后缀名为 .appx
的 Windows 应用商店版安装包。你需要打开 Windows 设置 -> 系统 -> 针对开发人员 -> 选择 “旁加载应用” 这个选项。
确认之后就可以双击 Ganache.appx
进行安装了,假如系统仍然无法识别这一后缀名,你可以手动打开 powershell
输入如下命令进行安装。
Add-AppxPackage .Ganache.appx
至此本地开发智能合约及 Dapp 的环境就算安装完成了,Truffle 官方提供了许多示例教程以及应用脚手架(truffle box),其中就包括教你开发以太坊宠物商 (http://truffleframework.com/tutorials/pet-shop) 的教程等内容。
在此不再赘述,感兴趣的同学自己动手可以试试。
以太坊智能合约开发
首先使用 Truffle 初始化我们的项目,命令如下。
mkdir my-icocd my-ico npm init -y truffle init
脚本运行完成之后 Truffle 会自动为我们的项目创建一系列文件夹和文件,如下图所示。
这里有一个隐藏的坑,如果你使用 Windows 命令行的话,需要删掉 truffle.js
文件,否则在项目目录执行 truffle 相关命令时,CMD 会混淆 truffle
与 truffle.js
文件。
因此,你应该将配置写在 truffle-config.js
文件当中。
ERC20 Token 合约开发
现在我们的项目目录大概是这个样子:
contracts/
Migrations.sol
migrations/
1_initial_migration.js
test/
package.json
truffle-config.js 或 truffle.js
我们在编写智能合约时,需要在 contracts
目录下新建相应的智能合约文件。
在以太坊开发智能合约的编程语言叫做 Solidity (https://goo.gl/hCHh3w)。它是一种在语法上非常类似 JavaScript 的语言,其后缀名为 .sol
。
例如在这里我们可以创建一个名为 GitCoin.sol
的文件,命令如下。
// *nix touch GitCoin.sol // win copy NUL > GitCoin.sol
ERC20(Ethereum Request for Comments NO.20)(https://goo.gl/aX4x5F) 是官方发行的 token 标准。
如果你希望你发布的 token 能够在以太坊网络上流通、上市交易所、支持以太坊钱包,在开发 token 的合约时就必须遵从这一规范。
ERC20 规定了合约中的一系列变量、方法、事件,你可以参考官网教程 Create your own CRYPTO-CURRENCY with Ethereum (https://www.ethereum.org/token) 当中的示例代码:
pragma solidity ^0.4.16; interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }contract TokenERC20 { // 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 TokenERC20( 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
- 上一篇: php yield 个人小解
- 下一篇: php5.5新特性之yield理解