ERC20代幣合約標準解析及程式碼實現
目前幾乎所有用於艾希歐籌集資金的代幣,都是基於同樣的技術:以太坊ERC-20標準。
因此這些代幣實際上就是實現了ERC20標準的智慧合約。在下文中,我們將全面剖析ERC20
標準規範,並給出一個ERC20代幣合約的完整實現程式碼。此外,在下文中我們將不加區分地使用
通證和代幣來表示遵循ERC20規範的智慧合約,雖然前者完全涵蓋了後者的範圍。
ERC20是Fabian Vogelsteller在2015年末提出的以太坊改進建議,它是許多流行的合約都在遵循的標準。
ERC20使通證智慧合約的行為非常類似於傳統的加密貨幣,例如在不同賬戶之間傳送和接收、
檢視通證總供應量或者檢視某個地址可用的通證餘額,就像比特幣或以太幣一樣。這類似於用以太坊錢包
傳送和接收以太幣、檢視流通中的以太幣總量、檢視特定錢包的貨幣餘額等。
ERC20介面
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);
}
合約中每個欄位的描述及示例如下。
totalSupply()
儘管與比特幣一樣,通證供給總量可以很容易地固定下來,但此函式允許合約例項計算
並返回存在於流通中的通證總量。
contract MyERCToken {
//在本示例中,通證供給量是固定的,但也可以將其設定為可修改的
uint256 _totalSupply = 1000000;
function totalSupply() constant returns (uint256 theTotalSupply) {
//函式宣告中已經定義了返回變數theTotalSupply
theTotalSupply = _totalSupply;
return theTotalSupply;
}
}
balanceOf()
該函式允許智慧合約返回指定賬戶地址的通證餘額。 該函式接受一個地址作為引數,
所以任何地址的通證餘額都是公開的。
contract MyERCToken {
//建立對映表來記錄賬戶餘額
mapping(address => uint256) balances;
// Owner of this contract
//合約擁有者
address public owner;
function balanceOf(address _owner) constant returns (uint256 balance) {
//返回指定地址的通證餘額
return balances[_owner];
}
}
approve()
此函式的呼叫方授權給定的地址可以從其地址中提款。
在這裡,以及後面的程式碼片段中,你可能會看到一個變數msg 。 這是由外部應用程式(如錢包)提供
的隱含欄位,以便更好地與合約進行互動。 以太坊虛擬機器(EVM)允許我們使用該欄位來儲存和處理
由外部應用程式提供的資料。
在這個例子中, 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;
}
}
transfer()
該函式讓呼叫方將指定數量的通證傳送到另一個地址,就像加密貨幣交易一樣。
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;
}
}
}
transferFrom()
該函式允許智慧合約自動執行轉賬流程並代表所有者傳送給定數量的通證。
看到這的時候你可能會有點困惑:為什麼有了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 - 通證名稱
name
是一個可選欄位,但許多流行的通證都定義了這個欄位,以便像Mist和MyEtherWallet
這樣的錢包能夠識別它們:
contract MyERCToken {
string public constant name = "My Custom ERC20 Token";
}
symbol - 通證符號
symbol
是另一個用於標識通證的可選欄位,通常採用三到四個字母的縮寫,就像BTC、ETH、AUG或SJCX一樣,
contract MyERCToken {
string public constant symbol = "MET";
}
decimals - 小數位數
這是一個可選欄位,用於確定通證數量的小數位數。 最常見的小數位數是18。
contract MyERCToken {
uint8 public constant decimals = 18;
}
這個ERC20通證的原始碼可以在Github找到。
ERC20標準開闢了一套新的智慧合約,可以像比特幣或以太坊一樣建立和分發,而且,
這些代幣可以在交易所託管,像其他資產一樣進行交易,因此投資者也可以輕鬆地購買和出售這些代幣。