代幣示例及講解

(注:本文是在原文的基礎(chǔ)上贞瞒,根據(jù)個人的理解弄跌,修改部分內(nèi)容并添加了一些注釋)

買賣部分代碼未調(diào)試通過


基礎(chǔ)版的代幣合約

下面是一個最簡單的代幣合約代碼煌恢,主要介紹可以看注釋:

pragma solidity 0.4.20;

/**

* @title 基礎(chǔ)版的代幣合約

*/

contract token {


? ? /* 公共變量 */

? ? string public standard = "https://mshk.top";


? ? /*記錄所有余額的映射*/

? ? mapping (address => uint256) public balanceOf;


? ? /* 初始化合約砾层,并且把初始的所有代幣都給這合約的創(chuàng)建者

? ? * @param initialSupply 代幣的總數(shù)

? ? */

? ? function token (uint256 initialSupply) public {

? ? ? ? balanceOf[msg.sender] = initialSupply;

? ? }


? ? /**

? ? * 私有方法從一個帳戶發(fā)送給另一個帳戶代幣

? ? * @param? from address 發(fā)送代幣的地址

? ? * @param? to address 接受代幣的地址

? ? * @param? value uint256 接受代幣的數(shù)量

? ? */

? ? function _transfer (address from, address to, uint256 value) internal {


? ? ? ? //避免轉(zhuǎn)帳的地址是0x0

? ? ? ? require(to != 0x0);


? ? ? ? //檢查發(fā)送者是否擁有足夠余額

? ? ? ? require(balanceOf[from] >= value);


? ? ? ? //檢查是否溢出

? ? ? ? require(balanceOf[to] + value > balanceOf[to]);


? ? ? ? //保存數(shù)據(jù)用于后面的判斷

? ? ? ? uint previousBalances = balanceOf[from] + balanceOf[to];


? ? ? ? //從發(fā)送者減掉發(fā)送額

? ? ? ? balanceOf[from] -= value;


? ? ? ? //給接收者加上相同的量

? ? ? ? balanceOf[to] += value;


? ? ? ? //判斷買糯景、賣雙方的數(shù)據(jù)是否和轉(zhuǎn)換前一致

? ? ? ? assert(balanceOf[from] + balanceOf[to] == previousBalances);

? ? }


? ? /**

? ? * 從主帳戶合約調(diào)用者發(fā)送給別人代幣

? ? * @param? to address 接受代幣的地址

? ? * @param? value uint256 接受代幣的數(shù)量

? ? */

? ? function transfer (address to, uint256 value) public {

? ? ? ? _transfer(msg.sender, to, value);

? ? }

}

接下來我們將上面的合約代碼枢贿,通過Mist部署到我們的私有鏈

首先如下圖中殉农,點(diǎn)擊合約->部署新合約:

然后如下面的兩張圖,選擇創(chuàng)建合約的帳戶局荚,將上面的代碼貼到SOLIDITY合約原始代碼處超凳,在右側(cè)選擇要部署的合約token,在token的下面Initial Supply處耀态,輸入我們要初始化的金額5000用于獎勵合約創(chuàng)建者轮傍,然后在頁面的最下面,點(diǎn)擊部署首装,的彈出的層中创夜,輸入創(chuàng)建合約這個帳號的密碼,輸入正確以后仙逻,合約創(chuàng)建成功挥下。

創(chuàng)建一個合約以后揍魂,再點(diǎn)擊Mist右側(cè)的合約,然后在定制化合約的下面棚瘟,可以看到我們剛剛創(chuàng)建的合約TOKEN,如下圖:

注意现斋,在合約下面也有一串0x開頭的地址,這個就相當(dāng)于一個錢包的地址偎蘸。在以太坊中庄蹋,合約也相當(dāng)于一個帳戶。

點(diǎn)擊TOKEN迷雪,進(jìn)入到合約里限书。在下面的Balance Of處,輸入剛才創(chuàng)建合約帳戶的地址0xa18e688326ab13b6147ce3ca2213db143a4ec2ee章咧,可以看到是有5000個代幣在里面倦西,如下圖:

在代幣創(chuàng)建的時候,初始值我們設(shè)置的是5000赁严,所以只有創(chuàng)建帳戶的地址有代幣扰柠,而輸入其他帳戶的地址,如0xc81896af13449a82f22699311df4ec4b48c07718疼约,是沒有值的卤档。

接下來,我們向0xc81896af13449a82f22699311df4ec4b48c07718這個帳戶地址程剥,轉(zhuǎn)入一些代幣劝枣。點(diǎn)擊右側(cè)選擇函數(shù)->選擇Transfer,在_to中輸入0xc81896af13449a82f22699311df4ec4b48c07718织鲸,在_value中輸入500舔腾,然后點(diǎn)擊執(zhí)行,在彈出的層中輸入調(diào)用合約帳戶的密碼搂擦,確認(rèn)操作舰始。

我們能夠看到實(shí)際調(diào)用合約的過程中炕吸,會花費(fèi)一定的gas拢肆,gas和以太幣會根據(jù)區(qū)塊的算力有一個計算公式郁岩,gas一般用于獎勵給挖礦者滔驶。

在transfer方法中这溅,我們設(shè)定了彭羹,只有合約的調(diào)用者msg.sender才能向指定地址轉(zhuǎn)移代幣奕筐。

/** * 從主帳戶合約調(diào)用者發(fā)送給別人代幣 *@param_to address 接受代幣的地址 *@param_value uint256 接受代幣的數(shù)量 */functiontransfer(address _to, uint256 _value)public{? ? _transfer(msg.sender, _to, _value);}

這時工扎,再次進(jìn)入合約徘钥,在Balance Of處,輸入兩個帳戶的地址肢娘,可以看到呈础,余額都發(fā)生的變化舆驶,如下圖:

改善代幣

通過上面的操作,我們已經(jīng)可以將合約代碼而钞,通過 Mist 部署到我們創(chuàng)建的私有鏈中沙廉,同樣如果部署到生產(chǎn)環(huán)境,只需要連上以太坊的網(wǎng)絡(luò)臼节,同樣的方法也可以將你的合約撬陵,部署到生產(chǎn)環(huán)境中,不過要根據(jù)代碼的大小网缝,花費(fèi)一些以太幣巨税。

實(shí)際使用過程中,交易的過程粉臊,需要通知到客戶端草添,并且記錄到區(qū)塊中,我們可以使用event事件來指定扼仲,如下代碼進(jìn)行聲明:

//在區(qū)塊鏈上創(chuàng)建一個事件远寸,用以通知客戶端eventTransfer(address indexed from, address indexed to, uint256 value);

設(shè)置一些代幣的基本信息

/* 公共變量 */stringpublicstandard ='https://mshk.top';stringpublicname;//代幣名稱stringpublicsymbol;//代幣符號比如'$'uint8publicdecimals =18;//代幣單位,展示的小數(shù)點(diǎn)后面多少個0,和以太幣一樣后面是是18個0uint256publictotalSupply;//代幣總量

某些特定的場景中犀盟,不允許某個帳戶花費(fèi)超過指定的上限而晒,避免大額支出,我們可以添加一個approve方法阅畴,來設(shè)置一個允許支出最大金額的列表倡怎。

注:根據(jù)個人的理解,approve是其他合約調(diào)用此合約贱枣,或者是代理监署,例如交易所,使用你的賬戶時纽哥,你可以設(shè)置一個代幣數(shù)量钠乏。他們只能對你設(shè)置的數(shù)量的代幣進(jìn)行操作,不知道這樣理解是否準(zhǔn)確春塌。下面是一個對approve晓避、allowance,以及后面的transferFrom的解釋:

注:approve只壳、transferFrom及allowance解釋:

賬戶A有1000個ETH俏拱,想允許B賬戶隨意調(diào)用100個ETH。A賬戶按照以下形式調(diào)用approve函數(shù)approve(B,100)吼句。當(dāng)B賬戶想用這100個ETH中的10個ETH給C賬戶時锅必,則調(diào)用transferFrom(A, C, 10)。這時調(diào)用allowance[A][B]可以查看B賬戶還能夠調(diào)用A賬戶多少個token惕艳。

mapping (address => mapping (address => uint256))publicallowance;/** * 設(shè)置帳戶允許支付的最大金額 * * 一般在智能合約的時候搞隐,避免支付過多驹愚,造成風(fēng)險 * *@param_spender 帳戶地址 *@param_value 金額 */functionapprove(address _spender, uint256 _value)publicreturns(bool success){? ? allowance[msg.sender][_spender] = _value;returntrue;}

同樣在solidity中,合約之間也可以相互調(diào)用劣纲,我們可以增加一個approveAndCall方法逢捺,用于在設(shè)置帳戶最大支出金額后,可以做一些其他操作癞季。

interfacetokenRecipient{functionreceiveApproval(address _from, uint256 _value, address _token, bytes _extraData)public; }/** * 設(shè)置帳戶允許支付的最大金額 * * 一般在智能合約的時候蒸甜,避免支付過多,造成風(fēng)險 * *@param_spender 帳戶地址 *@param_value 金額 */functionapprove(address _spender, uint256 _value)publicreturns(bool success){? ? allowance[msg.sender][_spender] = _value;returntrue;}/** * 設(shè)置帳戶允許支付的最大金額 * * 一般在智能合約的時候余佛,避免支付過多柠新,造成風(fēng)險,加入時間參數(shù)辉巡,可以在 tokenRecipient 中做其他操作 * *@param_spender 帳戶地址 *@param_value 金額 *@param_extraData 操作的時間 */functionapproveAndCall(address _spender, uint256 _value, bytes _extraData)publicreturns(bool success){? ? tokenRecipient spender = tokenRecipient(_spender);if(approve(_spender, _value)) {? ? ? ? spender.receiveApproval(msg.sender, _value, this, _extraData);returntrue;? ? }}

我們可以增加一個burn方法恨憎,用于管理員減去指定帳戶的指定金額。進(jìn)行該方法操作時郊楣,通知客戶端記錄到區(qū)塊鏈中憔恳。

注:代碼并沒有判斷調(diào)用者是否為管理員。

注:代理B在調(diào)用burnFrom刪除A賬戶余額時净蚤,也需要刪除A授權(quán)給自己的可調(diào)用余額數(shù)钥组。

//減去用戶余額事件event Burn(address indexed from, uint256 value);/** * 減少代幣調(diào)用者的余額 * * 操作以后是不可逆的 * *@param_value 要刪除的數(shù)量 */functionburn(uint256 _value)publicreturns(bool success){//檢查帳戶余額是否大于要減去的值require(balanceOf[msg.sender] >= _value);// Check if the sender has enough//給指定帳戶減去余額balanceOf[msg.sender] -= _value;//代幣問題做相應(yīng)扣除totalSupply -= _value;? ? Burn(msg.sender, _value);returntrue;}/** * 刪除帳戶的余額(含其他帳戶) * * 刪除以后是不可逆的 * *@param_from 要操作的帳戶地址 *@param_value 要減去的數(shù)量 */functionburnFrom(address _from, uint256 _value)publicreturns(bool success){//檢查帳戶余額是否大于要減去的值require(balanceOf[_from] >= _value);//檢查 其他帳戶 的余額是否夠使用require(_value <= allowance[_from][msg.sender]);//減掉代幣balanceOf[_from] -= _value;? ? allowance[_from][msg.sender] -= _value;//更新總量totalSupply -= _value;? ? Burn(_from, _value);returntrue;}

完整的代碼如下:

pragma solidity0.4.20;interfacetokenRecipient{functionreceiveApproval(address _from, uint256 _value, address _token, bytes _extraData)external; }/** *@title基礎(chǔ)版的代幣合約 */contract token {/* 公共變量 */stringpublicstandard ='https://mshk.top';? ? stringpublicname;//代幣名稱stringpublicsymbol;//代幣符號比如'$'uint8publicdecimals =18;//代幣單位,展示的小數(shù)點(diǎn)后面多少個0,和以太幣一樣后面是是18個0uint256publictotalSupply;//代幣總量/*記錄所有余額的映射*/mapping (address => uint256)publicbalanceOf;? ? mapping (address => mapping (address => uint256))publicallowance;/* 在區(qū)塊鏈上創(chuàng)建一個事件今瀑,用以通知客戶端*/event Transfer(address indexed from, address indexed to, uint256 value);//轉(zhuǎn)帳通知事件event Burn(address indexed from, uint256 value);//減去用戶余額事件/* 初始化合約程梦,并且把初始的所有代幣都給這合約的創(chuàng)建者? ? *@paraminitialSupply 代幣的總數(shù)? ? *@paramtokenName 代幣名稱? ? *@paramtokenSymbol 代幣符號? ? */functiontoken(uint256 initialSupply, string tokenName, string tokenSymbol)public{//初始化總量totalSupply = initialSupply *10** uint256(decimals);//以太幣是10^18,后面18個0橘荠,所以默認(rèn)decimals是18//給指定帳戶初始化代幣總量屿附,初始化用于獎勵合約創(chuàng)建者balanceOf[msg.sender] = totalSupply;? ? ? ? name = tokenName;? ? ? ? symbol = tokenSymbol;? ? }/**? ? * 私有方法從一個帳戶發(fā)送給另一個帳戶代幣? ? *@param_from address 發(fā)送代幣的地址? ? *@param_to address 接受代幣的地址? ? *@param_value uint256 接受代幣的數(shù)量? ? */function_transfer(address _from, address _to, uint256 _value)internal{//避免轉(zhuǎn)帳的地址是0x0require(_to !=0x0);//檢查發(fā)送者是否擁有足夠余額require(balanceOf[_from] >= _value);//檢查是否溢出require(balanceOf[_to] + _value > balanceOf[_to]);//保存數(shù)據(jù)用于后面的判斷uint previousBalances = balanceOf[_from] + balanceOf[_to];//從發(fā)送者減掉發(fā)送額balanceOf[_from] -= _value;//給接收者加上相同的量balanceOf[_to] += _value;//通知任何監(jiān)聽該交易的客戶端Transfer(_from, _to, _value);//判斷買、賣雙方的數(shù)據(jù)是否和轉(zhuǎn)換前一致assert(balanceOf[_from] + balanceOf[_to] == previousBalances);? ? }/**? ? * 從主帳戶合約調(diào)用者發(fā)送給別人代幣? ? *@param_to address 接受代幣的地址? ? *@param_value uint256 接受代幣的數(shù)量? ? */functiontransfer(address _to, uint256 _value)public{? ? ? ? _transfer(msg.sender, _to, _value);? ? }/**? ? * 從某個指定的帳戶中哥童,向另一個帳戶發(fā)送代幣? ? *? ? * 調(diào)用過程挺份,會檢查設(shè)置的允許最大交易額? ? *? ? *@param_from address 發(fā)送者地址? ? *@param_to address 接受者地址? ? *@param_value uint256 要轉(zhuǎn)移的代幣數(shù)量? ? *@returnsuccess? ? ? ? 是否交易成功? ? */functiontransferFrom(address _from, address _to, uint256 _value)publicreturns(bool success){//檢查發(fā)送者是否擁有足夠余額require(_value <= allowance[_from][msg.sender]);// Check allowanceallowance[_from][msg.sender] -= _value;? ? ? ? _transfer(_from, _to, _value);returntrue;? ? }/**? ? * 設(shè)置帳戶允許支付的最大金額? ? *? ? * 一般在智能合約的時候,避免支付過多贮懈,造成風(fēng)險? ? *? ? *@param_spender 帳戶地址? ? *@param_value 金額? ? */functionapprove(address _spender, uint256 _value)publicreturns(bool success){? ? ? ? allowance[msg.sender][_spender] = _value;returntrue;? ? }/**? ? * 設(shè)置帳戶允許支付的最大金額? ? *? ? * 一般在智能合約的時候匀泊,避免支付過多,造成風(fēng)險朵你,加入時間參數(shù)各聘,可以在 tokenRecipient 中做其他操作? ? *? ? *@param_spender 帳戶地址? ? *@param_value 金額? ? *@param_extraData 操作的時間? ? */functionapproveAndCall(address _spender, uint256 _value, bytes _extraData)publicreturns(bool success){? ? ? ? tokenRecipient spender = tokenRecipient(_spender);if(approve(_spender, _value)) {? ? ? ? ? ? spender.receiveApproval(msg.sender, _value, this, _extraData);returntrue;? ? ? ? }? ? }/**? ? * 減少代幣調(diào)用者的余額? ? *? ? * 操作以后是不可逆的? ? *? ? *@param_value 要刪除的數(shù)量? ? */functionburn(uint256 _value)publicreturns(bool success){//檢查帳戶余額是否大于要減去的值require(balanceOf[msg.sender] >= _value);// Check if the sender has enough//給指定帳戶減去余額balanceOf[msg.sender] -= _value;//代幣問題做相應(yīng)扣除totalSupply -= _value;? ? ? ? Burn(msg.sender, _value);returntrue;? ? }/**? ? * 刪除帳戶的余額(含其他帳戶)? ? *? ? * 刪除以后是不可逆的? ? *? ? *@param_from 要操作的帳戶地址? ? *@param_value 要減去的數(shù)量? ? */functionburnFrom(address _from, uint256 _value)publicreturns(bool success){//檢查帳戶余額是否大于要減去的值require(balanceOf[_from] >= _value);//檢查 其他帳戶 的余額是否夠使用require(_value <= allowance[_from][msg.sender]);//減掉代幣balanceOf[_from] -= _value;? ? ? ? allowance[_from][msg.sender] -= _value;//更新總量totalSupply -= _value;? ? ? ? Burn(_from, _value);returntrue;? ? }}

如上面的部署中,我們將完整的代碼撬呢,貼到Mist的solidity合約原始代碼處伦吠,在右側(cè)選擇token妆兑,Initial Supply輸入初始金額5000魂拦,Token name輸入我們的代幣名稱陌上花開毛仪,Token symbol代幣符號我們輸入$$,然后點(diǎn)擊部署,輸入部署帳戶的密碼芯勘。

部署合約以后箱靴,我們能夠在合約頁面看到剛才創(chuàng)建的合約。

點(diǎn)擊合約名稱荷愕,可以看到合約的一些基本信息衡怀,以及合約和操作函數(shù)

我們能夠在Mist上方的錢包中的主帳號這里看到有個小圖標(biāo),說明主帳戶已經(jīng)有了代幣安疗,其他帳戶是沒有這個圖標(biāo)的

點(diǎn)擊進(jìn)入主帳號以后抛杨,我們就可以看到主帳戶已經(jīng)擁有的代幣和以太幣的數(shù)量,因?yàn)槲覀兪菂⒖家蕴珟胚M(jìn)行設(shè)置荐类,最小單位是wei怖现,所以小數(shù)點(diǎn)后面有18個0。

接下來玉罐,我們向另一個帳戶發(fā)送一些陌上花開幣屈嗤,點(diǎn)擊Mist上方的發(fā)送,輸入發(fā)送的帳戶地址吊输,輸入數(shù)量500饶号,選擇發(fā)送的是陌上花開幣,點(diǎn)擊發(fā)送季蚂,如下圖

再次回到錢包中茫船,我們可以看到,另一個帳戶也有了一個代幣的圖標(biāo)扭屁,說明代幣已經(jīng)轉(zhuǎn)入成功透硝。

現(xiàn)在你擁有了自己的代幣,也可以做轉(zhuǎn)入轉(zhuǎn)出操作疯搅”羯可以被用于價值交換,或者工作時間追蹤或者其他項(xiàng)目。

高級版的代幣功能

雖然區(qū)塊鏈?zhǔn)侨ブ行幕尼E罚菍?shí)現(xiàn)對代幣(合約)的管理罪治,也在許多應(yīng)用中有需求,為了對代幣進(jìn)行管理礁蔗,首先需要給合約添加一個管理者觉义。

** * owned 是一個管理者 */contract owned {? ? addresspublicowner;/**

? ? * 初臺化構(gòu)造函數(shù)

? ? */functionowned(){? ? ? ? owner = msg.sender;? ? }/**

? ? * 判斷當(dāng)前合約調(diào)用者是否是管理員

? ? */modifier onlyOwner {require(msg.sender == owner);? ? ? ? _;? ? }/**? ? * 指派一個新的管理員? ? *@paramnewOwner address 新的管理員帳戶地址? ? */functiontransferOwnership(address newOwner)onlyOwner{if(newOwner != address(0)) {? ? ? ? owner = newOwner;? ? ? }? ? }}

上面的代碼是一個非常簡單的合約,我們可以在后面的代碼中浴井,使用繼承來實(shí)現(xiàn)后續(xù)的功能晒骇。

/** *@title高級版代幣 * 增加凍結(jié)用戶、挖礦、根據(jù)指定匯率購買(售出)代幣價格的功能 */contract MyAdvancedToken is owned{}

在MyAdvancedToken的所有方法中洪囤,可以使用owned的變量owner和modifier onlyOwner徒坡。

去中心化的管理者

我們也可以在構(gòu)造函數(shù)中設(shè)置是否需要一個去中心化的管理者。

/*初始化合約瘤缩,并且把初始的所有的令牌都給這合約的創(chuàng)建者 *@paraminitialSupply 所有幣的總數(shù) *@paramtokenName 代幣名稱 *@paramtokenSymbol 代幣符號 *@paramcentralMinter 是否指定其他帳戶為合約所有者,為0是去中心化 */functionMyAdvancedToken(

? uint256 initialSupply,

? string tokenName,

? string tokenSymbol,

? address centralMinter

){//設(shè)置合約的管理者if(centralMinter !=0) owner = centralMinter;}

代幣增發(fā)

實(shí)現(xiàn)代幣增發(fā)喇完,代幣增發(fā)就如同央行印鈔票一樣,想必很多人都需要這樣的功能剥啤。

/** * 合約擁有者锦溪,可以為指定帳戶創(chuàng)造一些代幣 *@paramtarget address 帳戶地址 *@parammintedAmount uint256 增加的金額(單位是wei) */functionmintToken(address target, uint256 mintedAmount)onlyOwner{//給指定地址增加代幣,同時總量也相加balanceOf[target] += mintedAmount;? ? totalSupply += mintedAmount;}

在方法的最后有一個onlyOwner府怯,說明mintToken是繼承了onlyOwner方法刻诊,會先調(diào)用modifier onlyOwner方法,然后將mintToken方法的內(nèi)容牺丙,插入到下劃線 _ 處調(diào)用坏逢。

凍結(jié)資產(chǎn)

有的場景中,某些用戶違反了規(guī)定赘被,需要凍結(jié)/解凍帳戶是整,不想讓他使用已經(jīng)擁有的代幣.可以增加以下代碼來控制:

//是否凍結(jié)帳戶的列表mapping (address => bool)publicfrozenAccount;//定義一個事件,當(dāng)有資產(chǎn)被凍結(jié)的時候民假,通知正在監(jiān)聽事件的客戶端event FrozenFunds(address target, bool frozen);/** * 增加凍結(jié)帳戶名稱 * * 你可能需要監(jiān)管功能以便你能控制誰可以/誰不可以使用你創(chuàng)建的代幣合約 * *@paramtarget address 帳戶地址 *@paramfreeze bool? ? 是否凍結(jié) */functionfreezeAccount(address target, bool freeze)onlyOwner{? ? frozenAccount[target] = freeze;? ? FrozenFunds(target, freeze);}

代幣買賣(兌換)

可以自己的貨幣中實(shí)現(xiàn)代幣與其他數(shù)字貨幣(ether 或其他tokens)的兌換機(jī)制浮入。有了這個功能,我們的合約就可以在一買一賣中賺利潤了羊异。

//賣出的匯率,一個代幣事秀,可以賣出多少個以太幣,單位是weiuint256publicsellPrice;//買入的匯率,1個以太幣野舶,可以買幾個代幣uint256publicbuyPrice;/** * 設(shè)置買賣價格 * * 如果你想讓ether(或其他代幣)為你的代幣進(jìn)行背書,以便可以市場價自動化買賣代幣,我們可以這么做易迹。如果要使用浮動的價格,也可以在這里設(shè)置 * *@paramnewSellPrice 新的賣出價格 *@paramnewBuyPrice 新的買入價格 */functionsetPrices(uint256 newSellPrice, uint256 newBuyPrice)onlyOwner{? ? sellPrice = newSellPrice;? ? buyPrice = newBuyPrice;}

然后增加買平道、賣的方法睹欲,每一次的交易,都會消耗掉一定的ether一屋。在 Solidity 0.4.0 之后窘疮,要接收ether的函數(shù)都要加一個payable屬性,如果你開放的合約冀墨,需要別人轉(zhuǎn)錢給你闸衫,就需要加payable。

下面的方法诽嘉,不會增加代幣蔚出,只是改變調(diào)用合約者的代幣數(shù)量弟翘,買、賣的價格單位不是ether骄酗,而是wei稀余,這是以太幣中最小的單位(就像美元里的美分,比特幣里的聰)。1 ether = 1000000000000000000 wei酥筝。因此使用ether設(shè)置價格的時候,在最后加18個0。

當(dāng)創(chuàng)建合約的時候,發(fā)送足夠多的ether作為代幣的背書,否則你的合約就是破產(chǎn)的,你的用戶就不能夠賣掉他們的代幣雏门。

/**

* 使用以太幣購買代幣

*/functionbuy()payablepublic{? uint amount = msg.value / buyPrice;? _transfer(this, msg.sender, amount);}/**

* @dev 賣出代幣

* @return 要賣出的數(shù)量(單位是wei)

*/functionsell(uint256 amount)public{//檢查合約的余額是否充足require(this.balance >= amount * sellPrice);? ? _transfer(msg.sender,this, amount);? ? msg.sender.transfer(amount * sellPrice);}

實(shí)現(xiàn)Gas的自動補(bǔ)充

以太坊中的交易時需要gas(支付給礦工的費(fèi)用嘿歌,費(fèi)用以ether來支付)。而如果用戶沒有以太幣茁影,只有代幣的情況(或者我們想向用戶隱藏以太坊的細(xì)節(jié))宙帝,就需要自動補(bǔ)充gas的功能。這個功能將使我們代幣更加好用募闲。

自動補(bǔ)充的邏輯是這樣了步脓,在執(zhí)行交易之前,我們判斷用戶的余額(用來支付礦工的費(fèi)用)浩螺,如果用戶的余額非常少(低于某個閾值時)可能影響到交易進(jìn)行靴患,合約自動售出一部分代幣來補(bǔ)充余額,以幫助用戶順利完成交易要出。

先來設(shè)定余額閾值:

uint minBalanceForAccounts;functionsetMinBalance(uint minimumBalanceInFinney)onlyOwner{? ? ? ? minBalanceForAccounts = minimumBalanceInFinney *1finney;? ? }

finney 是貨幣單位 1 finney = 0.001eth

然后交易中加入對用戶的余額的判斷鸳君。

functiontransfer(address _to, uint256 _value){? ? ...if(msg.sender.balance < minBalanceForAccounts)? ? ? ? sell((minBalanceForAccounts - msg.sender.balance) / sellPrice);if(_to.balance

全部代碼

pragma solidity0.4.20;interfacetokenRecipient{functionreceiveApproval(address _from, uint256 _value, address _token, bytes _extraData)external; }/**

* owned 是一個管理者

*/contract owned {? ? addresspublicowner;/**

? ? * 初臺化構(gòu)造函數(shù)

? ? */functionowned()public{? ? ? ? owner = msg.sender;? ? }/**

? ? * 判斷當(dāng)前合約調(diào)用者是否是管理員

? ? */modifier onlyOwner {require(msg.sender == owner);? ? ? ? _;? ? }/**? ? * 指派一個新的管理員? ? *@paramnewOwner address 新的管理員帳戶地址? ? */functiontransferOwnership(address newOwner)onlyOwnerpublic{if(newOwner != address(0)) {? ? ? ? owner = newOwner;? ? ? }? ? }}/** *@title基礎(chǔ)版的代幣合約 */contract token {/* 公共變量 */stringpublicstandard ='https://mshk.top';? ? stringpublicname;//代幣名稱stringpublicsymbol;//代幣符號比如'$'uint8publicdecimals =18;//代幣單位,展示的小數(shù)點(diǎn)后面多少個0,和以太幣一樣后面是是18個0uint256publictotalSupply;//代幣總量/*記錄所有余額的映射*/mapping (address => uint256)publicbalanceOf;? ? mapping (address => mapping (address => uint256))publicallowance;/* 在區(qū)塊鏈上創(chuàng)建一個事件患蹂,用以通知客戶端*/event Transfer(address indexed from, address indexed to, uint256 value);//轉(zhuǎn)帳通知事件event Burn(address indexed from, uint256 value);//減去用戶余額事件/* 初始化合約或颊,并且把初始的所有代幣都給這合約的創(chuàng)建者? ? *@paraminitialSupply 代幣的總數(shù)? ? *@paramtokenName 代幣名稱? ? *@paramtokenSymbol 代幣符號? ? */functiontoken(uint256 initialSupply, string tokenName, string tokenSymbol)public{//初始化總量totalSupply = initialSupply *10** uint256(decimals);//以太幣是10^18,后面18個0传于,所以默認(rèn)decimals是18//給指定帳戶初始化代幣總量囱挑,初始化用于獎勵合約創(chuàng)建者//balanceOf[msg.sender] = totalSupply;balanceOf[this] = totalSupply;? ? ? ? name = tokenName;? ? ? ? symbol = tokenSymbol;? ? }/**? ? * 私有方法從一個帳戶發(fā)送給另一個帳戶代幣? ? *@param_from address 發(fā)送代幣的地址? ? *@param_to address 接受代幣的地址? ? *@param_value uint256 接受代幣的數(shù)量? ? */function_transfer(address _from, address _to, uint256 _value)internal{//避免轉(zhuǎn)帳的地址是0x0require(_to !=0x0);//檢查發(fā)送者是否擁有足夠余額require(balanceOf[_from] >= _value);//檢查是否溢出require(balanceOf[_to] + _value > balanceOf[_to]);//保存數(shù)據(jù)用于后面的判斷uint previousBalances = balanceOf[_from] + balanceOf[_to];//從發(fā)送者減掉發(fā)送額balanceOf[_from] -= _value;//給接收者加上相同的量balanceOf[_to] += _value;//通知任何監(jiān)聽該交易的客戶端Transfer(_from, _to, _value);//判斷買、賣雙方的數(shù)據(jù)是否和轉(zhuǎn)換前一致assert(balanceOf[_from] + balanceOf[_to] == previousBalances);? ? }/**? ? * 從主帳戶合約調(diào)用者發(fā)送給別人代幣? ? *@param_to address 接受代幣的地址? ? *@param_value uint256 接受代幣的數(shù)量? ? */functiontransfer(address _to, uint256 _value)public{? ? ? ? _transfer(msg.sender, _to, _value);? ? }/**? ? * 從某個指定的帳戶中沼溜,向另一個帳戶發(fā)送代幣? ? *? ? * 調(diào)用過程平挑,會檢查設(shè)置的允許最大交易額? ? *? ? *@param_from address 發(fā)送者地址? ? *@param_to address 接受者地址? ? *@param_value uint256 要轉(zhuǎn)移的代幣數(shù)量? ? *@returnsuccess? ? ? ? 是否交易成功? ? */functiontransferFrom(address _from, address _to, uint256 _value)publicreturns(bool success){//檢查發(fā)送者是否擁有足夠余額require(_value <= allowance[_from][msg.sender]);// Check allowanceallowance[_from][msg.sender] -= _value;? ? ? ? _transfer(_from, _to, _value);returntrue;? ? }/**? ? * 設(shè)置帳戶允許支付的最大金額? ? *? ? * 一般在智能合約的時候,避免支付過多系草,造成風(fēng)險? ? *? ? *@param_spender 帳戶地址? ? *@param_value 金額? ? */functionapprove(address _spender, uint256 _value)publicreturns(bool success){? ? ? ? allowance[msg.sender][_spender] = _value;returntrue;? ? }/**? ? * 設(shè)置帳戶允許支付的最大金額? ? *? ? * 一般在智能合約的時候弹惦,避免支付過多,造成風(fēng)險悄但,加入時間參數(shù)棠隐,可以在 tokenRecipient 中做其他操作? ? *? ? *@param_spender 帳戶地址? ? *@param_value 金額? ? *@param_extraData 操作的時間? ? */functionapproveAndCall(address _spender, uint256 _value, bytes _extraData)publicreturns(bool success){? ? ? ? tokenRecipient spender = tokenRecipient(_spender);if(approve(_spender, _value)) {? ? ? ? ? ? spender.receiveApproval(msg.sender, _value, this, _extraData);returntrue;? ? ? ? }? ? }/**? ? * 減少代幣調(diào)用者的余額? ? *? ? * 操作以后是不可逆的? ? *? ? *@param_value 要刪除的數(shù)量? ? */functionburn(uint256 _value)publicreturns(bool success){//檢查帳戶余額是否大于要減去的值require(balanceOf[msg.sender] >= _value);// Check if the sender has enough//給指定帳戶減去余額balanceOf[msg.sender] -= _value;//代幣問題做相應(yīng)扣除totalSupply -= _value;? ? ? ? Burn(msg.sender, _value);returntrue;? ? }/**? ? * 刪除帳戶的余額(含其他帳戶)? ? *? ? * 刪除以后是不可逆的? ? *? ? *@param_from 要操作的帳戶地址? ? *@param_value 要減去的數(shù)量? ? */functionburnFrom(address _from, uint256 _value)publicreturns(bool success){//檢查帳戶余額是否大于要減去的值require(balanceOf[_from] >= _value);//檢查 其他帳戶 的余額是否夠使用require(_value <= allowance[_from][msg.sender]);//減掉代幣balanceOf[_from] -= _value;? ? ? ? allowance[_from][msg.sender] -= _value;//更新總量totalSupply -= _value;? ? ? ? Burn(_from, _value);returntrue;? ? }/**

? ? * 匿名方法,預(yù)防有人向這合約發(fā)送以太幣

? ? *//*function() {

? ? ? ? //return;? ? // Prevents accidental sending of ether

? ? }*/}/** *@title高級版代幣 * 增加凍結(jié)用戶檐嚣、挖礦助泽、根據(jù)指定匯率購買(售出)代幣價格的功能 */contract MyAdvancedToken is owned, token {//賣出的匯率,一個代幣啰扛,可以賣出多少個以太幣,單位是weiuint256publicsellPrice;//買入的匯率,1個以太幣嗡贺,可以買幾個代幣uint256publicbuyPrice;//是否凍結(jié)帳戶的列表mapping (address => bool)publicfrozenAccount;//定義一個事件隐解,當(dāng)有資產(chǎn)被凍結(jié)的時候,通知正在監(jiān)聽事件的客戶端event FrozenFunds(address target, bool frozen);/*初始化合約诫睬,并且把初始的所有的令牌都給這合約的創(chuàng)建者? ? *@paraminitialSupply 所有幣的總數(shù)? ? *@paramtokenName 代幣名稱? ? *@paramtokenSymbol 代幣符號? ? *@paramcentralMinter 是否指定其他帳戶為合約所有者,為0是去中心化? ? */functionMyAdvancedToken(

? ? ? uint256 initialSupply,

? ? ? string tokenName,

? ? ? string tokenSymbol,

? ? ? address centralMinter

? ? )token(initialSupply, tokenName, tokenSymbol)public{//設(shè)置合約的管理者if(centralMinter !=0) owner = centralMinter;? ? ? ? sellPrice =2;//設(shè)置1個單位的代幣(單位是wei)煞茫,能夠賣出2個以太幣buyPrice =4;//設(shè)置1個以太幣,可以買0.25個代幣}/**? ? * 私有方法摄凡,從指定帳戶轉(zhuǎn)出余額? ? *@param_from address 發(fā)送代幣的地址? ? *@param_to address 接受代幣的地址? ? *@param_value uint256 接受代幣的數(shù)量? ? */function_transfer(address _from, address _to, uint _value)internal{//避免轉(zhuǎn)帳的地址是0x0require(_to !=0x0);//檢查發(fā)送者是否擁有足夠余額require(balanceOf[_from] > _value);//檢查是否溢出require(balanceOf[_to] + _value > balanceOf[_to]);//檢查 凍結(jié)帳戶require(!frozenAccount[_from]);require(!frozenAccount[_to]);//從發(fā)送者減掉發(fā)送額balanceOf[_from] -= _value;//給接收者加上相同的量balanceOf[_to] += _value;//通知任何監(jiān)聽該交易的客戶端Transfer(_from, _to, _value);? ? }/**? ? * 合約擁有者续徽,可以為指定帳戶創(chuàng)造一些代幣? ? *@paramtarget address 帳戶地址? ? *@parammintedAmount uint256 增加的金額(單位是wei)? ? */functionmintToken(address target, uint256 mintedAmount)onlyOwnerpublic{//給指定地址增加代幣,同時總量也相加balanceOf[target] += mintedAmount;? ? ? ? totalSupply += mintedAmount;? ? ? ? Transfer(0, this, mintedAmount);? ? ? ? Transfer(this, target, mintedAmount);? ? }/**? ? * 增加凍結(jié)帳戶名稱? ? *? ? * 你可能需要監(jiān)管功能以便你能控制誰可以/誰不可以使用你創(chuàng)建的代幣合約? ? *? ? *@paramtarget address 帳戶地址? ? *@paramfreeze bool? ? 是否凍結(jié)? ? */functionfreezeAccount(address target, bool freeze)onlyOwnerpublic{? ? ? ? frozenAccount[target] = freeze;? ? ? ? FrozenFunds(target, freeze);? ? }/**? ? * 設(shè)置買賣價格? ? *? ? * 如果你想讓ether(或其他代幣)為你的代幣進(jìn)行背書,以便可以市場價自動化買賣代幣,我們可以這么做亲澡。如果要使用浮動的價格钦扭,也可以在這里設(shè)置? ? *? ? *@paramnewSellPrice 新的賣出價格? ? *@paramnewBuyPrice 新的買入價格? ? */functionsetPrices(uint256 newSellPrice, uint256 newBuyPrice)onlyOwnerpublic{? ? ? ? sellPrice = newSellPrice;? ? ? ? buyPrice = newBuyPrice;? ? }/**

? ? * 使用以太幣購買代幣

? ? */functionbuy()payablepublic{? ? ? uint amount = msg.value / buyPrice;? ? ? _transfer(this, msg.sender, amount);? ? }/**? ? *@dev賣出代幣? ? *@return要賣出的數(shù)量(單位是wei)? ? */functionsell(uint256 amount)public{//檢查合約的余額是否充足require(this.balance >= amount * sellPrice);? ? ? ? _transfer(msg.sender, this, amount);? ? ? ? msg.sender.transfer(amount * sellPrice);? ? }}

參考之前的方法,在Mist中重新部署合約床绪,貼完代碼后客情,在右側(cè)選擇My Advanced Token,Initial Supply輸入初始金額5000癞己,Token name輸入我們的代幣名稱陌上花開A膀斋,Token symbol代幣符號我們輸入#,然后點(diǎn)擊部署,輸入部署帳戶的密碼痹雅。

創(chuàng)建成功以后概页,我們在合約列表頁,可以看到剛才創(chuàng)建的新合約陌上花開A练慕。

點(diǎn)擊Mist上面的發(fā)送惰匙,我們先給帳戶0xd29adaadf3a40fd0b68c83c222c10d3ea637dce0轉(zhuǎn)入100個以太幣。

操作成功以后铃将,我們能夠在錢包頁面看到Account 4已經(jīng)有了100以太幣项鬼。

使用以太幣購買代幣

接下來,我們進(jìn)入合約頁面劲阎,使用以太幣購買陌上花開A代幣绘盟,進(jìn)入合約界面后,我們能夠看到代幣上的以太幣是0 ether悯仙,在右側(cè)選擇Buy方法龄毡,Execut from選擇Account 4,在Send ether輸入10個以太幣锡垄,點(diǎn)擊 執(zhí)行沦零。

執(zhí)行成功以后,能夠看到當(dāng)前頁面自動刷新货岭,合約中已經(jīng)有了10 ether路操,代幣的總量不變

再次回到 錢包 頁面疾渴,可以看到Account 4已經(jīng)從100 ether變成了90 ether,并且多了一個代幣圖標(biāo)屯仗。

點(diǎn)擊Account 4帳號進(jìn)去搞坝,可以看到一些詳細(xì)信息,ether的總量是89,999081514而不是90魁袜,是因?yàn)閳?zhí)行合約的時候桩撮,我們會消費(fèi)一定的gas。我們設(shè)置的費(fèi)率是1:4,所以10 ether峰弹,只可以購買2.5個陌上花開A代幣,最小單位也是wei店量,所以是2,500000000000000000。

賣出代幣

進(jìn)入合約界面后垮卓,我們能夠看到代幣上的以太幣是10 ether垫桂,在右側(cè)選擇Sell方法师幕,在Amount處輸入2000000000000000000(因?yàn)槲覀儎偛刨徺I了2.5個代幣粟按,現(xiàn)在賣出2個,賣出的最小單位是wei),Execut from選擇Account 4霹粥,點(diǎn)擊 執(zhí)行灭将。

執(zhí)行以后,在代幣的詳情頁面后控,能夠看到從10 ether變成了6 ether庙曙,因?yàn)閯偛臕ccount 4賣出了 2 個陌上花開A代幣,而我們設(shè)置的賣價是 1個代幣 能賣出 2個以太幣浩淘。

再次回到Account 4的詳情頁面捌朴,能夠看到以太幣變成了 93,998273026,而 陌上花開A 代幣的數(shù)量张抄,變成了 0,500000000000000000砂蔽。

注:Account4使用10個以太幣購買了2.5個代幣,如果交易機(jī)制沒有手續(xù)費(fèi)署惯,Account4賣出2.5個代幣仍然會獲得10個以太幣左驾。而這里通過設(shè)置買價4和賣價2,Account4賣出2.5個代幣只會獲得5個以太幣极谊。代幣合約利用手續(xù)費(fèi)賺取了5個以太幣诡右。


pragma solidity 0.4.24;

interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }

/**

* owned 是一個管理者

*/

contract owned {

? ? address public owner;

? ? /**

? ? * 初臺化構(gòu)造函數(shù)

? ? */

? ? constructor () public {

? ? ? ? owner = msg.sender;

? ? }

? ? /**

? ? * 判斷當(dāng)前合約調(diào)用者是否是管理員

? ? */

? ? modifier onlyOwner {

? ? ? ? require (msg.sender == owner);

? ? ? ? _;

? ? }

? ? /**

? ? * 指派一個新的管理員

? ? * @param? newOwner address 新的管理員帳戶地址

? ? */

? ? function transferOwnership(address newOwner) onlyOwner public {

? ? ? ? if (newOwner != address(0)) {

? ? ? ? owner = newOwner;

? ? ? }

? ? }

}

/**

* @title 基礎(chǔ)版的代幣合約

*/

contract token {

? ? /* 公共變量 */

? ? string public standard = 'https://mshk.top';

? ? string public name; //代幣名稱

? ? string public symbol; //代幣符號比如'$'

? ? uint8 public decimals = 18;? //代幣單位,展示的小數(shù)點(diǎn)后面多少個0,和以太幣一樣后面是是18個0

? ? uint256 public totalSupply; //代幣總量

? ? /*記錄所有余額的映射*/

? ? mapping (address => uint256) public balanceOf;

? ? mapping (address => mapping (address => uint256)) public allowance;

? ? /* 在區(qū)塊鏈上創(chuàng)建一個事件轻猖,用以通知客戶端*/

? ? event Transfer(address indexed from, address indexed to, uint256 value);? //轉(zhuǎn)帳通知事件

? ? event Burn(address indexed from, uint256 value);? //減去用戶余額事件

? ? /* 初始化合約帆吻,并且把初始的所有代幣都給這合約的創(chuàng)建者

? ? * @param initialSupply 代幣的總數(shù)

? ? * @param tokenName 代幣名稱

? ? * @param tokenSymbol 代幣符號

? ? */

? ? constructor (uint256 initialSupply, string tokenName, string tokenSymbol) public {

? ? ? ? //初始化總量

? ? ? ? totalSupply = initialSupply * 10 ** uint256(decimals);? ? //以太幣是10^18,后面18個0咙边,所以默認(rèn)decimals是18

? ? ? ? //給指定帳戶初始化代幣總量桅锄,初始化用于獎勵合約創(chuàng)建者

? ? ? ? //balanceOf[msg.sender] = totalSupply;

? ? ? ? balanceOf[this] = totalSupply;

? ? ? ? name = tokenName;

? ? ? ? symbol = tokenSymbol;

? ? }

? ? /**

? ? * 私有方法從一個帳戶發(fā)送給另一個帳戶代幣

? ? * @param? _from address 發(fā)送代幣的地址

? ? * @param? _to address 接受代幣的地址

? ? * @param? _value uint256 接受代幣的數(shù)量

? ? */

? ? function _transfer(address _from, address _to, uint256 _value) internal {

? ? ? //避免轉(zhuǎn)帳的地址是0x0

? ? ? require(_to != 0x0);

? ? ? //檢查發(fā)送者是否擁有足夠余額

? ? ? require(balanceOf[_from] >= _value);

? ? ? //檢查是否溢出

? ? ? require(balanceOf[_to] + _value > balanceOf[_to]);

? ? ? //保存數(shù)據(jù)用于后面的判斷

? ? ? uint previousBalances = balanceOf[_from] + balanceOf[_to];

? ? ? //從發(fā)送者減掉發(fā)送額

? ? ? balanceOf[_from] -= _value;

? ? ? //給接收者加上相同的量

? ? ? balanceOf[_to] += _value;

? ? ? //通知任何監(jiān)聽該交易的客戶端

? ? ? emit Transfer(_from, _to, _value);

? ? ? //判斷買琉雳、賣雙方的數(shù)據(jù)是否和轉(zhuǎn)換前一致

? ? ? assert(balanceOf[_from] + balanceOf[_to] == previousBalances);

? ? }

? ? /**

? ? * 從主帳戶合約調(diào)用者發(fā)送給別人代幣

? ? * @param? _to address 接受代幣的地址

? ? * @param? _value uint256 接受代幣的數(shù)量

? ? */

? ? function transfer(address _to, uint256 _value) public {

? ? ? ? _transfer(msg.sender, _to, _value);

? ? }

? ? /**

? ? * 從某個指定的帳戶中,向另一個帳戶發(fā)送代幣

? ? *

? ? * 調(diào)用過程友瘤,會檢查設(shè)置的允許最大交易額

? ? *

? ? * @param? _from address 發(fā)送者地址

? ? * @param? _to address 接受者地址

? ? * @param? _value uint256 要轉(zhuǎn)移的代幣數(shù)量

? ? * @return success? ? ? ? 是否交易成功

? ? */

? ? function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {

? ? ? ? //檢查發(fā)送者是否擁有足夠余額

? ? ? ? require(_value <= allowance[_from][msg.sender]);? // Check allowance

? ? ? ? allowance[_from][msg.sender] -= _value;

? ? ? ? _transfer(_from, _to, _value);

? ? ? ? return true;

? ? }

? ? /**

? ? * 設(shè)置帳戶允許支付的最大金額

? ? *

? ? * 一般在智能合約的時候翠肘,避免支付過多,造成風(fēng)險

? ? *

? ? * @param _spender 帳戶地址

? ? * @param _value 金額

? ? */

? ? function approve(address _spender, uint256 _value) public returns (bool success) {

? ? ? ? allowance[msg.sender][_spender] = _value;

? ? ? ? return true;

? ? }

? ? /**

? ? * 設(shè)置帳戶允許支付的最大金額

? ? *

? ? * 一般在智能合約的時候辫秧,避免支付過多束倍,造成風(fēng)險,加入時間參數(shù)盟戏,可以在 tokenRecipient 中做其他操作

? ? *

? ? * @param _spender 帳戶地址

? ? * @param _value 金額

? ? * @param _extraData 操作的時間

? ? */

? ? 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;

? ? ? ? }

? ? }

? ? /**

? ? * 減少代幣調(diào)用者的余額

? ? *

? ? * 操作以后是不可逆的

? ? *

? ? * @param _value 要刪除的數(shù)量

? ? */

? ? function burn(uint256 _value) public returns (bool success) {

? ? ? ? //檢查帳戶余額是否大于要減去的值

? ? ? ? require(balanceOf[msg.sender] >= _value);? // Check if the sender has enough

? ? ? ? //給指定帳戶減去余額

? ? ? ? balanceOf[msg.sender] -= _value;

? ? ? ? //代幣問題做相應(yīng)扣除

? ? ? ? totalSupply -= _value;

? ? ? ? emit Burn(msg.sender, _value);

? ? ? ? return true;

? ? }

? ? /**

? ? * 刪除帳戶的余額(含其他帳戶)

? ? *

? ? * 刪除以后是不可逆的

? ? *

? ? * @param _from 要操作的帳戶地址

? ? * @param _value 要減去的數(shù)量

? ? */

? ? function burnFrom(address _from, uint256 _value) public returns (bool success) {

? ? ? ? //檢查帳戶余額是否大于要減去的值

? ? ? ? require(balanceOf[_from] >= _value);

? ? ? ? //檢查 其他帳戶 的余額是否夠使用

? ? ? ? require(_value <= allowance[_from][msg.sender]);

? ? ? ? //減掉代幣

? ? ? ? balanceOf[_from] -= _value;

? ? ? ? allowance[_from][msg.sender] -= _value;

? ? ? ? //更新總量

? ? ? ? totalSupply -= _value;

? ? ? ? emit Burn(_from, _value);

? ? ? ? return true;

? ? }

? ? /**

? ? * 匿名方法绪妹,預(yù)防有人向這合約發(fā)送以太幣

? ? */

? ? /*function() {

? ? ? ? //return;? ? // Prevents accidental sending of ether

? ? }*/

}

/**

* @title 高級版代幣

* 增加凍結(jié)用戶、挖礦柿究、根據(jù)指定匯率購買(售出)代幣價格的功能

*/

contract MyAdvancedToken is owned, token {

? ? //賣出的匯率,一個代幣邮旷,可以賣出多少個以太幣,單位是wei

? ? uint256 public sellPrice;

? ? //買入的匯率,1個以太幣蝇摸,可以買幾個代幣

? ? uint256 public buyPrice;

? ? //是否凍結(jié)帳戶的列表

? ? mapping (address => bool) public frozenAccount;

? ? //定義一個事件婶肩,當(dāng)有資產(chǎn)被凍結(jié)的時候,通知正在監(jiān)聽事件的客戶端

? ? event FrozenFunds(address target, bool frozen);

? ? /*初始化合約貌夕,并且把初始的所有的令牌都給這合約的創(chuàng)建者

? ? * @param initialSupply 所有幣的總數(shù)

? ? * @param tokenName 代幣名稱

? ? * @param tokenSymbol 代幣符號

? ? * @param centralMinter 是否指定其他帳戶為合約所有者,為0是去中心化

? ? */

? ? constructor (

? ? ? uint256 initialSupply,

? ? ? string tokenName,

? ? ? string tokenSymbol,

? ? ? address centralMinter

? ? ) token (initialSupply, tokenName, tokenSymbol) public {

? ? ? ? //設(shè)置合約的管理者

? ? ? ? if(centralMinter != 0 ) owner = centralMinter;

? ? ? ? sellPrice = 2;? ? //設(shè)置1個單位的代幣(單位是wei)律歼,能夠賣出2個以太幣

? ? ? ? buyPrice = 4;? ? ? //設(shè)置1個以太幣,可以買0.25個代幣

? ? }

? ? /**

? ? * 私有方法啡专,從指定帳戶轉(zhuǎn)出余額

? ? * @param? _from address 發(fā)送代幣的地址

? ? * @param? _to address 接受代幣的地址

? ? * @param? _value uint256 接受代幣的數(shù)量

? ? */

? ? function _transfer(address _from, address _to, uint _value) internal {

? ? ? ? //避免轉(zhuǎn)帳的地址是0x0

? ? ? ? require (_to != 0x0);

? ? ? ? //檢查發(fā)送者是否擁有足夠余額

? ? ? ? require (balanceOf[_from] > _value);

? ? ? ? //檢查是否溢出

? ? ? ? require (balanceOf[_to] + _value > balanceOf[_to]);

? ? ? ? //檢查 凍結(jié)帳戶

? ? ? ? require(!frozenAccount[_from]);

? ? ? ? require(!frozenAccount[_to]);

? ? ? ? //從發(fā)送者減掉發(fā)送額

? ? ? ? balanceOf[_from] -= _value;

? ? ? ? //給接收者加上相同的量

? ? ? ? balanceOf[_to] += _value;

? ? ? ? //通知任何監(jiān)聽該交易的客戶端

? ? ? ? emit Transfer(_from, _to, _value);

? ? }

? ? /**

? ? * 合約擁有者险毁,可以為指定帳戶創(chuàng)造一些代幣

? ? * @param? target address 帳戶地址

? ? * @param? mintedAmount uint256 增加的金額(單位是wei)

? ? */

? ? function mintToken(address target, uint256 mintedAmount) onlyOwner public {

? ? ? ? //給指定地址增加代幣,同時總量也相加

? ? ? ? balanceOf[target] += mintedAmount;

? ? ? ? totalSupply += mintedAmount;

? ? ? ? emit Transfer(0, this, mintedAmount);

? ? ? ? emit Transfer(this, target, mintedAmount);

? ? }

? ? /**

? ? * 增加凍結(jié)帳戶名稱

? ? *

? ? * 你可能需要監(jiān)管功能以便你能控制誰可以/誰不可以使用你創(chuàng)建的代幣合約

? ? *

? ? * @param? target address 帳戶地址

? ? * @param? freeze bool? ? 是否凍結(jié)

? ? */

? ? function freezeAccount(address target, bool freeze) onlyOwner public {

? ? ? ? frozenAccount[target] = freeze;

? ? ? ? emit FrozenFunds(target, freeze);

? ? }

? ? /**

? ? * 設(shè)置買賣價格

? ? *

? ? * 如果你想讓ether(或其他代幣)為你的代幣進(jìn)行背書,以便可以市場價自動化買賣代幣,我們可以這么做们童。如果要使用浮動的價格畔况,也可以在這里設(shè)置

? ? *

? ? * @param newSellPrice 新的賣出價格

? ? * @param newBuyPrice 新的買入價格

? ? */

? ? function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner public {

? ? ? ? sellPrice = newSellPrice;

? ? ? ? buyPrice = newBuyPrice;

? ? }

? ? /**

? ? * 使用以太幣購買代幣

? ? */

? ? function buy() payable public {

? ? ? uint amount = msg.value / buyPrice;

? ? ? _transfer(this, msg.sender, amount);

? ? }

? ? /**

? ? * @dev 賣出代幣

? ? * @return 要賣出的數(shù)量(單位是wei)

? ? */

? ? function sell(uint256 amount) public {

? ? ? ? //檢查合約的余額是否充足

? ? ? ? require(address(this).balance >= amount * sellPrice);

? ? ? ? _transfer(msg.sender, this, amount);

? ? ? ? msg.sender.transfer(amount * sellPrice);

? ? }

}.


以上買賣未調(diào)試通過

以太坊開發(fā)(十三)代幣示例及講解

Go-Ethereum 1.7.2 結(jié)合 Mist 0.9.2 實(shí)現(xiàn)代幣智能合約的實(shí)例

以太坊使用數(shù)字貨幣(通證)完成去中心化投票DApp

基于以太坊發(fā)布屬于自己的數(shù)字貨幣(代幣)完整版

給代幣添加高級功能-代幣管理、增發(fā)慧库、兌換跷跪、凍結(jié)等

Create your own crypto-currency

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市完沪,隨后出現(xiàn)的幾起案子域庇,更是在濱河造成了極大的恐慌,老刑警劉巖覆积,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件听皿,死亡現(xiàn)場離奇詭異,居然都是意外死亡宽档,警方通過查閱死者的電腦和手機(jī)尉姨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吗冤,“玉大人又厉,你說我怎么就攤上這事九府。” “怎么了覆致?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵侄旬,是天一觀的道長。 經(jīng)常有香客問我煌妈,道長儡羔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任璧诵,我火速辦了婚禮汰蜘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘之宿。我一直安慰自己族操,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布比被。 她就那樣靜靜地躺著色难,像睡著了一般。 火紅的嫁衣襯著肌膚如雪姐赡。 梳的紋絲不亂的頭發(fā)上莱预,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天柠掂,我揣著相機(jī)與錄音项滑,去河邊找鬼。 笑死涯贞,一個胖子當(dāng)著我的面吹牛枪狂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宋渔,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼州疾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了皇拣?” 一聲冷哼從身側(cè)響起严蓖,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎氧急,沒想到半個月后颗胡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吩坝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年毒姨,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钉寝。...
    茶點(diǎn)故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡弧呐,死狀恐怖闸迷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情俘枫,我是刑警寧澤瞄摊,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站嗤放,受9級特大地震影響戏自,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜邓嘹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一酣栈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汹押,春花似錦矿筝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至妙痹,卻和暖如春铸史,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背怯伊。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工琳轿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人耿芹。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓崭篡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吧秕。 傳聞我的和親對象是個殘疾皇子琉闪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容