iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0
自我挑戰組

Solidity 初學之路系列 第 22

DAY 22 - 空投合約

  • 分享至 

  • xImage
  •  

空投 Airdrop

空投是幣圈中一種行銷策略,專案方將代幣免費發放給特定用戶群。為了拿到空投資格,使用者通常需要完成一些簡單的任務,例如測試產品、分享新聞、介紹朋友等。專案方透過空投可以獲得種子用戶,而用戶可以獲得一筆財富,兩全其美。 因為每次接收空投的用戶很多,所以項目方不可能一筆一筆的轉帳。利用智慧合約批量發放ERC20代幣,可顯著提高空投效率。

空投代幣合約

Airdrop空投合約邏輯非常簡單:利用循環,一筆交易將ERC20代幣發送給多個地址。合約中包含兩個函數

  1. getSum()函數:傳回uint陣列的和。
    function getSum(uint256[] calldata _arr) public pure returns(uint sum){
        for(uint i = 0; i < _arr.length; i++)
            sum = sum + _arr[i];
    }
    
  • multiTransferToken()函數:傳送ERC20代幣空投,包含3個參數:
    • _token:代幣合約地址(address類型
    • _addresses:接收空投的使用者位址陣列(address[]類型)
    • _amounts:空投數量數組,對應_addresses裡每個地址的數量(uint[]類型)
    • 函數有兩個檢查:第一個require檢查了_addresses和_amounts兩個數組長度是否相等;第二個require檢查了空投合約的授權額度大於要空投的代幣數量總和。
    /// @notice 向多個地址轉帳ERC20代幣,使用前需先授權
    ///
    /// @param _token 轉帳的ERC20代幣地址
    /// @param _addresses 空投位址數組
    /// @param _amounts 代幣數量數組(每個地址的空投數量)
    function multiTransferToken(
        address _token,
        address[] calldata _addresses,
        uint256[] calldata _amounts
        ) external {
        // 檢查:_addresses和_amounts數組的長度相等
        require(_addresses.length == _amounts.length, "Lengths of Addresses and Amounts NOT EQUAL");
        IERC20 token = IERC20(_token); // 聲明IERC合約變量
        uint _amountSum = getSum(_amounts); // 計算空投代幣總量
        // 檢查:授權代幣數量 >= 空投代幣總量
        require(token.allowance(msg.sender, address(this)) >= _amountSum, "Need Approve ERC20 token");
    
        // for循環,利用transferFrom函數發送空投
        for (uint8 i; i < _addresses.length; i++) {
            token.transferFrom(msg.sender, _addresses[i], _amounts[i]);
        }
    }
    
  1. multiTransferETH()函數:傳送ETH空投,包含2個參數:
    • _addresses:接收空投的使用者位址陣列(address[]類型)
    • _amounts:空投數量數組,對應_addresses裡每個地址的數量(uint[]類型)
    /// 向多個地址轉帳ETH
    function multiTransferETH(
        address payable[] calldata _addresses,
        uint256[] calldata _amounts
    ) public payable {
        // 檢查:_addresses和_amounts數組的長度相等
        require(_addresses.length == _amounts.length, "Lengths of Addresses and Amounts NOT EQUAL");
        uint _amountSum = getSum(_amounts); // 計算空投ETH總量
        // 檢查轉入ETH等於空投總量
        require(msg.value == _amountSum, "Transfer amount error");
        // for循環,利用transfer函數發送ETH
        for (uint256 i = 0; i < _addresses.length; i++) {
            // 註解程式碼有Dos攻擊風險, 且transfer 也是不推薦寫法
            // Dos攻擊具體參考 https://github.com/AmazingAng/WTF-Solidity/blob/main/S09_DoS/readme.md
            // _addresses[i].transfer(_amounts[i]);
            (bool success, ) = _addresses[i].call{value: _amounts[i]}("");
            if (!success) {
                failTransferList[_addresses[i]] = _amounts[i];
            }
        }
    }
    

上一篇
DAY 21 - ERC20、代幣水龍頭
下一篇
DAY 23 - ERC721
系列文
Solidity 初學之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言