目前幾乎全部用於艾希歐籌集資金的代幣,都是基於一樣的技術:以太坊ERC-20標準。 所以這些代幣實際上就是實現了ERC20標準的智能合約。在下文中,咱們將全面剖析ERC20 標準規範,並給出一個ERC20代幣合約的完整實現代碼。此外,在下文中咱們將不加區分地使用 __通證__和__代幣__來表示遵循ERC20規範的智能合約,雖然前者徹底涵蓋了後者的範圍。git
若是你但願立刻開始學習以太坊智能合約和應用開發,能夠訪問匯智網提供的出色的在線互動教程:github
ERC20是Fabian Vogelsteller在2015年底提出的以太坊改進建議,它是許多流行的合約都在遵循的標準。 ERC20使通證智能合約的行爲很是相似於傳統的加密貨幣,例如在不一樣帳戶之間發送和接收、 查看通證總供應量或者查看某個地址可用的通證餘額,就像比特幣或以太幣同樣。這相似於用以太坊錢包 發送和接收以太幣、查看流通中的以太幣總量、查看特定錢包的貨幣餘額等。app
ERC20定義了一些標準的接口函數:balanceOf 、 totalSupply 、transfer 、transferFrom 、approve和allowance 。 以及一些可選的字段,例如通證名稱、符號以及小數保留位數等。你能夠在github 查看ERC-20全文。函數
下面的代碼聲明一個簡明的ERC20智能合約:學習
contract ERC20 { function totalSupply() constant returns (uint theTotalSupply); 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); }
合約中每一個字段的描述及示例以下。ui
儘管與比特幣同樣,通證供給總量能夠很容易地固定下來,但此函數容許合約實例計算 並返回存在於流通中的通證總量。this
contract MyERCToken { //在本示例中,通證供給量是固定的,但也能夠將其設定爲可修改的 uint256 _totalSupply = 1000000; function totalSupply() constant returns (uint256 theTotalSupply) { //函數聲明中已經定義了返回變量theTotalSupply theTotalSupply = _totalSupply; return theTotalSupply; } }
該函數容許智能合約返回指定帳戶地址的通證餘額。 該函數接受一個地址做爲參數, 因此任何地址的通證餘額都是公開的。加密
contract MyERCToken { //建立映射表來記錄帳戶餘額 mapping(address => uint256) balances; // Owner of this contract //合約擁有者 address public owner; function balanceOf(address _owner) constant returns (uint256 balance) { //返回指定地址的通證餘額 return balances[_owner]; } }
此函數的調用方受權給定的地址能夠從其地址中提款。3d
在這裏,以及後面的代碼片斷中,你可能會看到一個變量msg 。 這是由外部應用程序(如錢包)提供 的隱含字段,以便更好地與合約進行交互。 以太坊虛擬機(EVM)容許咱們使用該字段來存儲和處理 由外部應用程序提供的數據。code
在這個例子中, msg.sender是合約方法調用方的地址。
contract MyERCToken { //建立映射表記錄通證持有者、被受權者以及受權數量 mapping(address => mapping (address => uint256)) allowed; function approve(address _spender, uint256 _amount) returns (bool success) { allowed[msg.sender][_spender] = _amount; //當受權時觸發Approval事件 Approval(msg.sender, _spender, _amount); return true; } }
該函數讓調用方將指定數量的通證發送到另外一個地址,就像加密貨幣交易同樣。
contract MyERCToken { mapping(address => uint256) balances; //返回值爲true時,表示轉帳成功 function transfer(address _to, uint256 _amount) returns (bool success) { //若是發送方有足夠的資金而且發送數量非0 ,則發送給指定地址 if (balances[msg.sender] >= _amount && _amount > 0 && balances[_to] + _amount > balances[_to]) { balances[msg.sender] -= _amount; balances[_to] += _amount; //觸發Transfer事件 Transfer(msg.sender, _to, _amount); return true; } else { return false; } } }
該函數容許智能合約自動執行轉帳流程並表明全部者發送給定數量的通證。
看到這的時候你可能會有點困惑:爲何有了transfer(),還須要transferFrom()?。
回一下在平常生活中,經過轉帳來支付帳單的狀況。 一般你須要本身去辦轉帳匯款來支付帳單,這 就像使用transfer() :你須要本身執行,沒有其餘人的幫助。
在另外一種狀況下,你能夠與銀行簽定自動代支付協議。 這就像使用transferFrom() : 銀行的機器會自動以你的名義進行轉帳支持。 有了這個函數,合約就能夠表明你自動 發送通證到另外一個地址,而無需你的干預。
contract MyERCToken { mapping(address => uint256) balances; function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) { if (balances[_from] >= _amount && allowed[_from][msg.sender] >= _amount && _amount > 0 && balances[_to] + _amount > balances[_to]) { balances[_from] -= _amount; balances[_to] += _amount; Transfer(_from, _to, _amount); return true; } else { return false; } } }
name
是一個可選字段,但許多流行的通證都定義了這個字段,以便像Mist和MyEtherWallet 這樣的錢包可以識別它們:
contract MyERCToken { string public constant name = "My Custom ERC20 Token"; }
symbol
是另外一個用於標識通證的可選字段,一般採用三到四個字母的縮寫,就像BTC、ETH、AUG或SJCX同樣,
contract MyERCToken { string public constant symbol = "MET"; }
這是一個可選字段,用於肯定通證數量的小數位數。 最多見的小數位數是18。
contract MyERCToken { uint8 public constant decimals = 18; }
這個ERC20通證的源代碼能夠在Github找到。
ERC20標準開闢了一套新的智能合約,能夠像比特幣或以太坊同樣建立和分發,並且, 這些代幣能夠在交易所託管,像其餘資產同樣進行交易,所以投資者也能夠輕鬆地購買和出售這些代幣。