文章閱讀頁通欄

河南22选5走势图彩宝:如何為4萬名訂閱者編寫自動空投腳本

來源: 區塊鏈研究實驗室 作者:鏈三豐
在本文/教程中,我將介紹編寫node.js腳本的過程,該腳本執行自動代幣分發/空投到以太坊地址列表。我將使用Polymath代幣分發過程編寫的代碼(這是一個非......
在本文/教程中,我將介紹編寫node.js腳本的過程,該腳本執行自動代幣分發/空投到以太坊地址列表。我將使用Polymath代幣分發過程編寫的代碼(這是一個非常標準的ERC20令牌),并檢查我處理代幣的自動分發而構建的腳本。

最初我打算通過Infura運行此腳本,因此不必在本地運行全節點。這就要求離線簽署交易記錄,這是我使用最新版本的web3中的幾個便捷函數完成的。不幸的是,即使這在testrpc和Ropsten上像魔咒一樣工作,在Mainnet上還是一場災難。交易沒有得到處理,還極其緩慢,昂貴且不可靠。

代幣和代幣分發的合約

我在Polymath的首要任務之一是幫助團隊制定代幣和代幣分發智能合約,我們將在未來幾天使用這些合約來推出POLY代幣,并向訂閱該平臺的4萬人執行空投活動。

以下是有關polytoken.sol和polydribution.sol智能合約的一些值得一提的內容,這將有助于理解本教程的其余部分:

· PolyToken.sol是POLY代幣的合約,這是一個相當固定的標準ERC20代幣合約。

· PolyDistribution.sol是將處理代幣初始分配的合約。我們將預售投資者,顧問,創始人等的代幣分配從空投中分離出來,因為其過程是非常不同的。在我們的案例中,我們將使用1000萬個代幣(已發行的10億個代幣)進行空投,向40,000人分發250個代幣。 對于本教程而言,最重要的功能是airdropTokens(),讓我們對其進行回顧:

function airdropTokens(address[] _recipient) public onlyOwnerOrAdmin {
    require(now >= startTime);
    uint airdropped;
    for(uint i = 0; i< _recipient.length; i++)
    {
        if (!airdrops[_recipient[i]]) {
          airdrops[_recipient[i]] = true;
          require(POLY.transfer(_recipient[i], 250 * decimalFactor));
          airdropped = airdropped.add(250 * decimalFactor);
        }
    }
    AVAILABLE_AIRDROP_SUPPLY = AVAILABLE_AIRDROP_SUPPLY.sub(airdropped);
    AVAILABLE_TOTAL_SUPPLY = AVAILABLE_TOTAL_SUPPLY.sub(airdropped);
    grandTotalClaimed = grandTotalClaimed.add(airdropped);
  }

airdropTokens()的基本作用是將250個POLY代幣(通常是ERC20代幣)分發(調用ERC20的transfer()函數)到一個地址數組中。 對于我們收到的每個地址,只要他們尚未收到分配,我們就會向他們轉移250 POLY。 流程完成后,我們將更新可用的供應并跟蹤已經分配了多少代幣。

在本教程中,我們將僅關注分發給空投接收者的代幣。從上面可以看出,這些代幣的分配和轉讓沒有行權期或懸崖期對于其他類型的分配。對于其他類型的分配,情況則不同,那些分配具有一些特殊條件,必須先滿足一些特殊條件,才能轉讓/出售它們。

如果您有興趣了解其余分配的完成方式,可以查看PolyDistribution.sol中的setAllocation()和transferTokens()函數。

代幣分配事件

當代幣分配日期到來時,我們的團隊需要做的就是將代幣分配給每個注冊空投的帳戶。這些數據是過去幾個月從公司網站上收集的,其中包含注冊空投并在KYC驗證過程中成功驗證的每個帳戶的地址??脹兜墓趟枋占氖荽媧⒃贑SV文件中,該文件只有1列:每個訂閱的以太坊地址。

請注意,可以很容易地修改腳本,使其不僅包含訂閱用戶的地址,還包含應傳輸的代幣數量。 在這種情況下,由于我們決定將250 POLY分配給每個人,因此這不是必需的,我們選擇在分發智能合約中對該數字進行硬編碼。

從理論上講,進行空投非常簡單。 我們需要做的就是為我們收集的每個地址調用ERC20令牌的transfer()函數。

如果我們只有很少的訂閱者,則可以通過手動執行transfer()函數來完成上述操作,但是潛在的成千上萬的人希望在啟動時立即擁有其代幣,逐個執行上述操作將非常耗時。

通過Node.js腳本自動執行代幣分發過程。

在解釋了代幣和分發合約的工作原理之后,讓我們深入研究JS代碼。為了使代幣分配過程自動化,我們需要做一些事情:

· 我們必須讀取CSV文件并對其進行處理,以刪除空白或無效的條目。我們假設某些數據會丟失或某些地址可能會錯誤,因此我們確保在將它們發送到區塊鏈之前將其刪除。

· 我們會將地址打包成多個數組,每個數組包含80個地址。為什么是80?經過多次測試,考慮到轉讓代幣的氣體成本,這是理想的數字。根據您要對每個條目進行的操作,每次交易可能會花費更多或更少的氣體,因此您應該相應地打包條目,以使交易不會耗盡氣體并回滾。

· 有了數組集后,我們將每個數組傳遞給智能合約上的airdropTokens()函數,該函數將遍歷數組并為每個訂閱者調用transfer()方法向其發送代幣。

· 之后,我們將運行另一個過程來獲取分發合約生成的所有“轉移”事件,以便我們可以檢查分發情況是否良好。(我們將對分發的代幣進行匯總,該代幣應與我們存檔的數據相匹配)。

讓我們從設置項目開始:

設置

運行以下命令以設置全新項目并安裝所需的依賴項:

$ mkdir distributionTutorial
$ npm init
$ truffle init
$ npm install web3 fast-csv truffle-contract ethereumjs-testrpc  --save

對于這個項目,我們將使用一些庫和框架:

· truffle:它允許我們從javascript輕松編譯、遷移和與我們的合約交互。
· Fast-csv:從CSV文件讀取和處理數據。

您還應該安裝Parity并將其同步到Ropsten(或您喜歡的任何testnet / mainnet)上。 以下命令對我來說效果很好:

parity — chain ropsten — rpcapi “eth,net,web3,personal,parity” 
— unlock <THE ACCOUNT YOU WANT TO UNLOCK> — password $HOME/password.file

接下來,將Polymath Distribution智能合約復制到項目的合約文件夾中。 可以在這里找到文件:https://github.com/PolymathNetwork/polymath-token-distribution/tree/master/contracts

打開truffle.js并將其內容替換為以下代碼:

module.exports = {
  networks: {
   development: {
      host: 'localhost',
      port: 8545,
      network_id: '*', // Match any network id
      gas: 3500000,
    }, 
   ropsten: {
      host: 'localhost',
      port: 8545,
      network_id: '3', // Match any network id
      gas: 3500000,
      gasPrice: 50000000000
    },
  },
  solc: {
    optimizer: {
      enabled: true,
      runs: 200,
    },
  },
};

上面的代碼將允許我們運行truffle migrate——network-ropsten來將合同部署到ropsten testnet。 在能夠將合約部署到Ropsten之前,我們需要創建用于truffle的部署腳本。 使用以下代碼在migrations文件夾中創建一個名為2_deploy_contracts.js的新文件:

var PolyToken = artifacts.require('./PolyToken.sol');
var PolyDistribution = artifacts.require('./PolyDistribution.sol');module.exports = async (deployer, network) => {
  let _now = Date.now();
  let _fromNow = 60 * 5 * 1000; // Start distribution in 1 hour
  let _startTime = (_now + _fromNow) / 1000;
  await deployer.deploy(PolyDistribution, _startTime);
  console.log(`
    ---------------------------------------------------------------
    --------- POLYMATH (POLY) TOKEN SUCCESSFULLY DEPLOYED ---------
    ---------------------------------------------------------------
    - Contract address: ${PolyDistribution.address}
    - Distribution starts in: ${_fromNow/1000/60} minutes
    - Local Time: ${new Date(_now + _fromNow)}
    ---------------------------------------------------------------
  `);
};

上面的代碼將在執行truffle migrate--network ropsten時運行它將把PolyDistribution合約部署到Ropsten(它也處理POLY Token合約的部署),將startTime設置為5分鐘后確保已正確設置了“starttime”變量,并且在到達“starttime”后嘗試空投,否則執行將失敗。我們正在使用starttime防止人們在代幣分發事件開始之前撤回代幣。

河南22选5第202期开奖 www.lyedr.com 繼續運行truffle migrate--network ropsten如果一切順利,您應該會在控制臺上看到類似的輸出:

TX哈希值和合約地址對您來說會有所不同。

如果看不到此輸出或出現錯誤,請確保您正在運行Parity并且已完全同步。 另外,請確保帳戶中有足夠的以太幣,用于在Ropsten測試網上部署合約。

記下我們剛剛部署的Poly Distribution合約的地址,稍后我們將使用它。

讀取CSV文件

讓我們開始編寫腳本,該腳本將自動將poly代幣分配到注冊空投的地址。

首先,創建一個名為scripts的新文件夾,并在該文件夾中創建一個名為csv_allocation.js的新文件。該文件將包含用于運行分配過程的所有代碼。

在繼續讀取和處理CSV文件的代碼之前,讓我們將文件添加到項目中。 我們需要一個名為airdrop.csv的1列CSV文件,該文件的每個地址都有一個接收代幣的地址。 創建此文件并將其添加到scripts / data文件夾。

如果要輕松測試空投,可以使用您控制的“隨機”地址自己生成此文件。 一種簡單的方法是運行testrpc并指定要創建的帳戶數,如下所示:

testrpc -m "word1 word2 word3..." -a 300

上面的命令將從您提供的助記符中生成300個帳戶。 將地址復制到airdrop.csv。

回到我們的csv_allocation.js腳本中,讓我們添加必要的代碼以能夠讀取airdrop.csv。 將以下代碼添加到csv_allocation.js中:

var fs = require('fs');
var csv = require('fast-csv');
var BigNumber = require('bignumber.js');let polyDistributionAddress = process.argv.slice(2)[0];
let BATCH_SIZE = process.argv.slice(2)[1];
if(!BATCH_SIZE) BATCH_SIZE = 80;
let distribData = new Array();
let allocData = new Array();function readFile() {
  var stream = fs.createReadStream("scripts/data/airdrop.csv");let index = 0;
let batch = 0;console.log(`
    --------------------------------------------
    --------- Parsing distrib.csv file ---------
    --------------------------------------------******** Removing beneficiaries without address data
  `);var csvStream = csv()
      .on("data", function(data){
          let isAddress = web3.utils.isAddress(data[0]);
          if(isAddress && data[0]!=null && data[0]!='' ){
            allocData.push(data[0]);index++;
            if(index >= BATCH_SIZE)
            {
              distribData.push(allocData);
              allocData = [];
              index = 0;
            }}
      })
      .on("end", function(){
           //Add last remainder batch
           distribData.push(allocData);
           allocData = [];
           setAllocation();
      });  stream.pipe(csvStream);
}if(polyDistributionAddress){
  console.log("Processing airdrop. Batch size is",BATCH_SIZE, "accounts per transaction");
  readFile();
}else{
  console.log("Please run the script by providing the address of the PolyDistribution contract");
}

您現在可以執行以下操作來運行腳本:

$ node scripts/csv_allocation.js 0x0... 80
// Where 0x0... is the address of the PolyDistribution contract we previously deployed to Ropsten.
// 80 is the batch size we want to process. (How many accounts per array we want to process and send to the airdropTokens function) Can be omitted, defaults to 80.

讓我們回顧一下代碼:

首先,我們導入允許我們讀取文件和處理csv文件的庫。

然后,如果您查看代碼的最后幾行,將會看到我們正在訪問運行腳本時傳遞的參數,并且如果有PolyDistribution合約的地址,我們將調用readFile()函數。

readFile()函數的作用是訪問airdrop.csv文件,并逐行讀取它。 在每一行中,我們確保該值不為null或為空,并且還使用web3的isAddress()函數來驗證傳遞的地址是否有效。 如果地址正確,我們會將其添加到一個數組中,該數組包含用于構建每個以太坊交易的已處理數據。

數據全部處理完畢并到達文件末尾后,我們將調用該函數,我們調用函數來獲取80個地址的每個數組并對它們進行處理。

請注意,此函數非常簡單,可以進一步改進,可以檢測超過poly供應量的代幣數量、重復地址等。所有這些情況仍在合約中處理,但如果我們可以節省一些對ethereum的事務調用,那就太好了。

處理代幣分配

現在我們已經將數據處理到一個數組中了-我們應該將名為distribData的數組包含幾個數組,每個數組最多具有80個地址addresses-我們將從智能合約中為每個數組調用airdropTokens()函數 。

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));async function setAllocation() {console.log(`
    --------------------------------------------
    ---------Performing allocations ------------
    --------------------------------------------
  `);let accounts = await web3.eth.getAccounts();let polyDistribution = await PolyDistribution.at(polyDistributionAddress);  for(var i = 0;i< distribData.length;i++){try{
      let gPrice = 50000000000;
      console.log("Attempting to allocate 250 POLYs to accounts:",distribData[i],"\n\n");
      let r = await polyDistribution.airdropTokens(distribData[i],{from:accounts[0], gas:4500000, gasPrice:gPrice});
      console.log("---------- ---------- ---------- ----------");
      console.log("Allocation + transfer was successful.", r.receipt.gasUsed, "gas used. Spent:",r.receipt.gasUsed * gPrice,"wei");
      console.log("---------- ---------- ---------- ----------\n\n")
    } catch (err){
      console.log("ERROR:",err);
    } }
}

讓我們仔細看看這個函數。 JS腳本中的setAllocation()所做的只是遍歷用CSV文件中處理后的數據填充的distribData數組,然后對于每個條目數組,我們繼續在智能合約上執行airdropTokens(),并傳遞該數組。

對于我們處理的每一批地址,我們都檢索事件日志并打印花費了多少氣體,以確保過程成功。

每批氣體消耗量應大致相同。 如果有一批天然氣的成本更低,則意味著該批中的某些地址未轉移代幣,或者可能是因為它們之前已經轉移了代幣。

從ERC20令牌讀取轉移事件以驗證交易

在每天調用它之前,我們可以做的最后一件事是訪問erc20 poly token transfer()函數的事件日志,以便我們可以快速檢查有多少帳戶獲得了代幣。

在setAllocation()函數的末尾添加以下行:

console.log("Distribution script finished successfully.")
  console.log("Waiting 2 minutes for transactions to be mined...")
  await delay(90000);
  console.log("Retrieving logs to inform total amount of tokens distributed so far. This may take a while...")let polytokenAddress = await polyDistribution.POLY({from:accounts[0]});
  let polyToken = await PolyToken.at(polytokenAddress);var sumAccounts = 0;
  var sumTokens = 0;var events = await polyToken.Transfer({from: polyDistribution.address},{fromBlock: 0, toBlock: 'latest'});
  events.get(function(error, log) {
      event_data = log;
      //console.log(log);
      for (var i=0; i<event_data.length;i++){
          //let tokens = event_data[i].args.value.times(10 ** -18).toString(10);
          //let addressB = event_data[i].args.to;
          sumTokens += event_data[i].args.value.times(10 ** -18).toNumber();
          sumAccounts +=1;
          //console.log(`Distributed ${tokens} POLY to address ${addressB}`);}
      console.log(`A total of ${sumTokens} POLY tokens have been distributed to ${sumAccounts} accounts so far.`);
  });

上面的代碼添加了一個超時函數,因此我們給事務留出一些時間來完成對事務的確認,然后我們獲得POLY代幣的Transfer()事件,并通過作為PolyDistribution合約的from字段過濾事件。

然后我們計算事件以及分配了多少大筆。我們可以使用該數據將其與原始文件進行比較。如果我們想花哨的話,我們也可以列出每個獲得代幣的地址,或者添加一個將CSV文件與事件日志數據進行比較的函數。

腳本執行

就這樣! 讓我們嘗試一下腳本。 運行以下命令:

$ node scripts/csv_allocation.js 0x0...
// Replace 0x0... with the address of the PolyDistribution contract you deployed to Ropsten

如果一切順利,您應該在控制臺上看到以下內容:

而且,如果您轉到Etherscan并輸入已部署的PolyDistribution合同的地址,則應該看到類似以下內容:

如果您可以看到csv文件中每個帳戶的transfer()事件,那么恭喜!

你的空投成功了!

到此就結束了,感謝你的耐心閱讀!

關鍵詞: 空投  區塊鏈空投  
0/300
?