基於以太坊發布屬於自己的數字貨幣(代幣)完整版


https://blog.csdn.net/JAVA_HHHH/article/details/79771752

 

本文單純從技術角度詳細介紹如何基於以太坊ERC20創建代幣的流程(此案例是部署的eth主網,非測試案例)

 

寫在前面

 

本文所講的代幣是使用以太坊智能合約創建,閱讀本文前,你應該對以太坊、智能合約有所了解,如果你還不了解,建議你先看以太坊是什么。

代幣Token
如果不那么追求精確的定義,代幣就是數字貨幣,比特幣、以太幣就是一個代幣。
利用以太坊的智能合約可以輕松編寫出屬於自己的代幣,代幣可以代表任何可以交易的東西,如:積分、財產、證書等等。

因此不管是出於商業,還是學習很多人想創建一個自己的代幣,先貼一個圖看看創建的代幣是什么樣子。

以我自己發布的BliBli幣 Bcoin為例

訪問地址 :  https://etherscan.io/token/0x73c8da697fe5e145f6269c4c852e59a7328f9371

 

 

 


 今天我們就來詳細講一講怎樣創建一個這樣的代幣。

ERC20 Token
ERC20和代幣一同出現, ERC20是以太坊定義的一個代幣標准。是一種發行代幣合約必須要遵守的協議,該協議規定了幾個參數——發行貨幣的名稱,簡稱,發行量,要支持的函數等,只有支持了該協議才會被以太坊所認同。

erc20標准代碼如下

// https://github.com/ethereum/EIPs/issues/20
contract ERC20 {
function totalSupply() constant returns (uint totalSupply);
function balanceOf(address _owner) constant returns (uint balance);
function transfer(address _to, uint _value) returns (bool success);
function transferFrom(address _from, address _to, uint _value) returns (bool success);
function approve(address _spender, uint _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns (uint remaining);
event Transfer(address indexed _from, address indexed _to, uint _value);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}

totalSupply:  代表的是代幣發行總量    totalSupply():該方法可以返回代幣的總數量

name:  發行代幣的名稱                       dicimals:  發行代幣以后,代幣交易的最小單位

balanceOf(): 該方法返回的是輸入錢包地址后,該錢包的代幣余額

tansferFrom() :從一個地址向另一個地址發送余額

approve(): 允許_spender從你的賬戶轉出_value余額


allowance(): 允許_spender從你的賬戶轉出_value的余額,調用多次會覆蓋可用量。某些DEX功能需要此功能

event Transfer():  token轉移完成后出發

event Approval():  approve(address _spender, uint256 _value)調用后觸發

 

編寫代幣合約:

 

pragma solidity ^0.4.12;

contract IMigrationContract {
function migrate(address addr, uint256 nas) returns (bool success);
}

/* 靈感來自於NAS coin*/
contract SafeMath {


function safeAdd(uint256 x, uint256 y) internal returns(uint256) {
uint256 z = x + y;
assert((z >= x) && (z >= y));
return z;
}

function safeSubtract(uint256 x, uint256 y) internal returns(uint256) {
assert(x >= y);
uint256 z = x - y;
return z;
}

function safeMult(uint256 x, uint256 y) internal returns(uint256) {
uint256 z = x * y;
assert((x == 0)||(z/x == y));
return z;
}

}

contract Token {
uint256 public totalSupply;
function balanceOf(address _owner) constant returns (uint256 balance);
function transfer(address _to, uint256 _value) returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
function approve(address _spender, uint256 _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}


/* ERC 20 token */
contract StandardToken is Token {

function transfer(address _to, uint256 _value) returns (bool success) {
if (balances[msg.sender] >= _value && _value > 0) {
balances[msg.sender] -= _value;
balances[_to] += _value;
Transfer(msg.sender, _to, _value);
return true;
} else {
return false;
}
}

function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
} else {
return false;
}
}

function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}

function approve(address _spender, uint256 _value) returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}

function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}

mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
}

contract BliBliToken is StandardToken, SafeMath {

// metadata
string public constant name = "BliBli";
string public constant symbol = "BCoin";
uint256 public constant decimals = 18;
string public version = "1.0";

// contracts
address public ethFundDeposit; // ETH存放地址
address public newContractAddr; // token更新地址

// crowdsale parameters
bool public isFunding; // 狀態切換到true
uint256 public fundingStartBlock;
uint256 public fundingStopBlock;

uint256 public currentSupply; // 正在售賣中的tokens數量
uint256 public tokenRaised = 0; // 總的售賣數量token
uint256 public tokenMigrated = 0; // 總的已經交易的 token
uint256 public tokenExchangeRate = 625; // 625 BILIBILI 兌換 1 ETH

// events
event AllocateToken(address indexed _to, uint256 _value); // 分配的私有交易token;
event IssueToken(address indexed _to, uint256 _value); // 公開發行售賣的token;
event IncreaseSupply(uint256 _value);
event DecreaseSupply(uint256 _value);
event Migrate(address indexed _to, uint256 _value);

// 轉換
function formatDecimals(uint256 _value) internal returns (uint256 ) {
return _value * 10 ** decimals;
}

// constructor
function BliBliToken(
address _ethFundDeposit,
uint256 _currentSupply)
{
ethFundDeposit = _ethFundDeposit;

isFunding = false; //通過控制預CrowdS ale狀態
fundingStartBlock = 0;
fundingStopBlock = 0;

currentSupply = formatDecimals(_currentSupply);
totalSupply = formatDecimals(10000000);
balances[msg.sender] = totalSupply;
if(currentSupply > totalSupply) throw;
}

modifier isOwner() { require(msg.sender == ethFundDeposit); _; }

/// 設置token匯率
function setTokenExchangeRate(uint256 _tokenExchangeRate) isOwner external {
if (_tokenExchangeRate == 0) throw;
if (_tokenExchangeRate == tokenExchangeRate) throw;

tokenExchangeRate = _tokenExchangeRate;
}

/// @dev 超發token處理
function increaseSupply (uint256 _value) isOwner external {
uint256 value = formatDecimals(_value);
if (value + currentSupply > totalSupply) throw;
currentSupply = safeAdd(currentSupply, value);
IncreaseSupply(value);
}

/// @dev 被盜token處理
function decreaseSupply (uint256 _value) isOwner external {
uint256 value = formatDecimals(_value);
if (value + tokenRaised > currentSupply) throw;

currentSupply = safeSubtract(currentSupply, value);
DecreaseSupply(value);
}

/// 啟動區塊檢測 異常的處理
function startFunding (uint256 _fundingStartBlock, uint256 _fundingStopBlock) isOwner external {
if (isFunding) throw;
if (_fundingStartBlock >= _fundingStopBlock) throw;
if (block.number >= _fundingStartBlock) throw;

fundingStartBlock = _fundingStartBlock;
fundingStopBlock = _fundingStopBlock;
isFunding = true;
}

/// 關閉區塊異常處理
function stopFunding() isOwner external {
if (!isFunding) throw;
isFunding = false;
}

/// 開發了一個新的合同來接收token(或者更新token)
function setMigrateContract(address _newContractAddr) isOwner external {
if (_newContractAddr == newContractAddr) throw;
newContractAddr = _newContractAddr;
}

/// 設置新的所有者地址
function changeOwner(address _newFundDeposit) isOwner() external {
if (_newFundDeposit == address(0x0)) throw;
ethFundDeposit = _newFundDeposit;
}

///轉移token到新的合約
function migrate() external {
if(isFunding) throw;
if(newContractAddr == address(0x0)) throw;

uint256 tokens = balances[msg.sender];
if (tokens == 0) throw;

balances[msg.sender] = 0;
tokenMigrated = safeAdd(tokenMigrated, tokens);

IMigrationContract newContract = IMigrationContract(newContractAddr);
if (!newContract.migrate(msg.sender, tokens)) throw;

Migrate(msg.sender, tokens); // log it
}

/// 轉賬ETH 到BILIBILI團隊
function transferETH() isOwner external {
if (this.balance == 0) throw;
if (!ethFundDeposit.send(this.balance)) throw;
}

/// 將BILIBILI token分配到預處理地址。
function allocateToken (address _addr, uint256 _eth) isOwner external {
if (_eth == 0) throw;
if (_addr == address(0x0)) throw;

uint256 tokens = safeMult(formatDecimals(_eth), tokenExchangeRate);
if (tokens + tokenRaised > currentSupply) throw;

tokenRaised = safeAdd(tokenRaised, tokens);
balances[_addr] += tokens;

AllocateToken(_addr, tokens); // 記錄token日志
}

/// 購買token
function () payable {
if (!isFunding) throw;
if (msg.value == 0) throw;

if (block.number < fundingStartBlock) throw;
if (block.number > fundingStopBlock) throw;

uint256 tokens = safeMult(msg.value, tokenExchangeRate);
if (tokens + tokenRaised > currentSupply) throw;

tokenRaised = safeAdd(tokenRaised, tokens);
balances[msg.sender] += tokens;

IssueToken(msg.sender, tokens); //記錄日志
}
}
以上的代幣合約,是參考以太坊已經ICO過,並且產生價值的代幣合約參考而來,完整比且功能強大,此合約創建的代幣,具有“交易”,“轉賬”,“異常檢測”,“更改代幣持有人”,“設置匯率”,“被盜處理”,“超發代幣”等功能。

(解釋下:在以太坊的世界中,硬通貨就是ETH-以太幣,相當於現實世界中的黃金,我們發布的代幣,就相當於各國發行的需要 與黃金掛鈎兌換比率的貨幣,國家對貨幣擁有控制權,只要合約功能進行擴展,創造代幣的人也會對代幣擁有控制權。)

(對於挖礦的誤解:不少小哥哥小姐姐認為挖礦就是挖幣,其實挖礦是挖區塊,區塊是干嘛的,是用來打包交易的,是存儲數據的,代幣是不用挖的,當你挖到了區塊,代幣是給你的獎勵,在發行量一定的情況下,代幣會越來越少,所以挖到區塊的獎勵會變少。那獎勵少了為什么還要挖礦呢,因為你的任何一筆交易都需要記錄,一個區塊的大小也就幾M,存儲不了那么多交易信息,所以要持續挖區塊來記錄你的交易,同時交易的手續費,會獎勵給挖出區塊的人。)

 

部署合約:

    

部署合約有多種方式      1 geth 編譯代碼 ---部署合約

                                     2 用ethereum wallet錢包部署合約

                                    3 最簡單直觀的部署合約方式:  MetaMask和Remix Solidity IDE 部署合約

   我們按照 MetaMask和Remix Solidity IDE 來進行部署合約。

 1: 創建錢包帳號。MetaMask是錢包的一種,在chrome瀏覽器中,安裝MetaMask插件即可,安裝完成后,右上角會出現一個“狐狸頭”的標志,點擊該標志,打開錢包,第一步,創建賬戶,(創建賬戶只需要輸入面密碼即可,名稱創建后可以隨便改,該賬戶就是一個hash值,如何給自己創建的賬戶沖以太幣,可以上https://otcbtc.com/sign_up網站,按照操作買以太幣,然后轉賬到自己創建的賬戶)創建成功后,記住密碼還有產生的幾個隨機單詞(一定要記錄下來)。如下:

 

   2:打開 Remix Solidity IDE 訪問地址: http://remix.ethereum.org/#optimize=false&version=soljson-v0.4.21+commit.dfe3193c.js   界面如下 

 

 

 

3:  拷貝“編寫代幣合約”后邊的代碼到Remix Solidity IDE中按照如下編譯

 

4: create 發布  如下

 

 

5 create后,產生hash值,拷貝hash值,在錢包中添加token

 

 

 

 

 

OK,如上所示,第一個屬於你的真正意義上的去中心化數字貨幣就誕生了。正式網絡和測試網絡部署方法一樣,不需要買eth就是了。

如果是測試網絡,如何獲得ETH?   進入 https://gitter.im/kovan-testnet/faucet  下方直接發送你的賬戶地址(hash值)即可,一般五分鍾到賬,會得到五個測試網絡用的ETH幣。

 

 

6(如果部署的是eth主網,非測試網,執行該步驟,測試網絡可以不理會)

發布了代幣以后,如果以后進行ico,那么需要發布源碼公開。步驟如下

   ①  拷貝部署成功的合約地址(hash),到  https://etherscan.io/   右上角搜索hash

   ②  按照如下圖進行verify AND publish

           打開如下頁面第一步

 

 

         打開如下頁面第二部

 

 

 

 

          打開如下頁面第三部

 

 

 

 

 

 

 

  ok  現在的代幣就比較完整了,差ico了

 

 

代幣轉賬:

   1  metamask錢包轉賬:  如下

 

   輸入地址和代幣數量

 

 

 

 

2  網頁錢包轉賬:  如下  https://www.myetherwallet.com/#send-transaction

    登錄賬戶:

 

 

  轉賬交易

 


---------------------
作者:JAVA_HHHH
來源:CSDN
原文:https://blog.csdn.net/JAVA_HHHH/article/details/79771752
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM