以太坊智能合約之批量轉幣

一直想寫這篇教程來着,由於你會發現網絡上不多有關於批量轉幣的詳盡的教程,一些提供該工具的網站也並不會將其智能合約代碼開源出來。雖然最終咱們會發現原來這個批量轉幣的智能合約原來就這麼幾行代碼就夠啦,可是整個流程不明因此的話,給你這個合約代碼我相信你也是用不了的,所以對於新手來講想要寫出這個功能多少仍是有不小的難度的。html

批量轉幣其實也屬於 空投的一種,所謂空投,筆者的理解是利用程序或者人工的方式,將代幣發放至目標帳戶。

注意:這裏所說的代幣均指代的是 ERC20 Token,對於更新的代幣例如 ERC721 Token 等,因爲自己就優化了這方面,所以不須要咱們這樣折騰。編程

用途

咱們爲何須要批量轉幣這樣的智能合約呢?數組

  1. 大大節約轉幣的資金成本。很明顯,若是咱們人工一次次的進行轉幣操做,那麼轉個幾百次所須要的 gas 費用會讓你吃一驚。可是使用這個批量轉幣的智能合約,通常來講,兩百次左右能夠一次性操做完,那麼也就是兩百次轉幣費只須要支付一次轉幣費便可。
  2. 大大節約轉幣的人工成本。和支付費用成本相似,讓你手工轉個幾百次估計怕是要瘋掉了。
  3. 有足夠的需求。前面也講到,新的 ERC721 Token 等不須要咱們這樣折騰,可是目前 ERC20 Token 幾乎是絕大多數代幣的模板,所以需求足夠大,也就是應用場景足夠大。

前置知識點

  1. 合約調用合約
  2. 受權轉帳方法

合約調用合約

要在智能合約中調用其餘合約,就須要瞭解抽象合約的概念,具體細節能夠看這裏安全

以本文所要講的轉幣合約爲例,咱們要在合約中調用 ERC20 Token 的 transferFrom 方法,那麼咱們首先要先建立一個 ERC20 Token 的抽象合約,代碼以下:網絡

/**
 * @dev ERC20 Token abstract constract.
 */
contract ERC20Token {
    function transferFrom(address, address, uint256) public returns (bool);
}

由於咱們只須要用到代幣的 transferFrom 方法,所以咱們只須要聲明該方法便可,注意是沒有函數體的空方法。編程語言

那麼咱們在批量轉幣的合約中如何進行調用呢?和大多數面向對象的編程語言同樣,咱們只須要建立這個代幣合約,而後調用這個代幣合約實例的受權轉帳方法便可,代碼以下:函數

/**
    * @dev calls the ERC20 token's transferFrom function
    * @param _token address The address of ERC20 token.
    * @param _dsts address The addresses which be air dropped.
    * @param _values uint256 The token values that each address will receive.
    */
function transfer(address _token, address[] _dsts, uint256[] _values) 
    public
    payable
{
    ERC20Token token = ERC20Token(_token);
    for (uint256 i = 0; i < _dsts.length; i++) {
        token.transferFrom(msg.sender, _dsts[i], _values[i]);
    }
}

咱們的批量轉幣代碼是否是很是簡單~能夠看到,咱們首先建立了 ERC20 Token 的合約實例,而後循環要轉幣的地址列表,每次遍歷中調用目標 ERC20 Token 的 transferFrom 方法便可。工具

這個函數能夠作的更好:對於代碼邊際判斷,咱們能夠判斷一下 _token 以及 _dsts 是否均爲合法帳戶,或者判斷一下 _values 是否均爲合法正數值,又或者比較一下 _dsts 和 _values 的數組長度是否相等(健壯的代碼必定是邊際安全的)。。。是否還能完善的更好一些?固然是能夠的,好比咱們增長一個 Event 事件供調用者監聽以便作出相應處理。。。

受權轉帳方法

那麼是否是上面的這些代碼就足夠了呢?對於批量轉幣合約來講核心代碼就是這些。區塊鏈

可是!有個前提!優化

咱們在使用這個合約轉幣前,須要受權給這個合約必定的代幣數額受權給這個合約必定的代幣數額受權給這個合約必定的代幣數額

這裏就引出了受權轉帳的概念,仍是以批量轉幣爲例:

首先咱們須要明確,假如你擁有 1000 個 SIM 代幣,那麼這些代幣就獨屬於你,沒人能拿走(別給我瞎扯什麼被盜啊之類的狀況,講例子的時候咱們純真些。。。)那麼若是你啥也不作,想要讓轉幣合約可以轉走你的 SIM 代幣,顯然這是不可能的,由於是你擁有這些代幣,而不是轉幣合約擁有。

因此此時你就須要把本身的 SIM 代幣受權給轉幣合約,至於受權多少看你要轉多少。一旦你完成受權操做,那麼轉幣合約就有權利將你的代幣進行轉帳操做了(等下,我能夠以後忽然改主意取消受權嗎?能夠,你再次受權一次,數目爲零便可。)

案例

筆者以前花了點時間作了一個 Web 頁面,將批量轉幣的功能作在了上面,下面咱們簡單的看下整個流程,配合示例圖會更加清晰 :)

獲取代幣信息

第一步主要是獲取用戶須要批量轉帳的代幣信息,經過用戶填寫的代幣合約地址,而後獲取到基本的代幣信息。

填寫轉幣數量和帳戶

第二步主要是獲取用戶轉幣的數目和帳戶信息,而後須要讓用戶受權相應數目的代幣給咱們的轉幣合約。

確認並空投

第三步主要是讓用戶確認信息,並開始空投。

這是批量轉 ERC20 代幣的交易記錄:
Ropsten Transaction 0x630b868e41ecfbd97273371ed33242439230355d9110095b814ae3029b88d829

擴展

這裏筆者給新手們留個做業,若是我想要批量轉 ETH 怎麼辦?若是直接使用上面的代碼可很差使哦,可是思路是一毛同樣的,並且代碼上會更簡潔~

附上一個批量轉 ETH 的交易記錄:
Ropsten Transaction 0x4fcfc6245d7ffecfae7c02eb2f983f203806b83b5a1cf2fc0450a61d7c226401

哦,你們可能還會看到另一種批量轉幣的合約代碼的寫法,代碼以下:

bytes4 id = bytes4(keccak256("transferFrom(address,address,uint256)"));
token_address.call(id, msg.sender, _dsts[i], _valus[i]);

這在低版本的 Solidity 中是能夠正常運行的,由於本質上和上面講的是同樣的,但在高版本中廢棄了該用法,所以筆者在嘗試高版本中使用會出現每次批量轉幣的最後一次老是會失敗。因此推薦的作法是經過抽象合約的方式進行調用其餘合約的方法。

最後,但願你們在區塊鏈的世界中玩的開心~

相關文章
相關標籤/搜索