0%

solidity | 空投合约「批量」

参考资料

这里说一下流程

  • 创建一个 ERC20 合约
  • 创建一个空投合约
  • ERC20 合约中赋予 approve 权限
  • 执行空投合约的批量函数

关于 ERC20 请参考

空投合约如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";

pragma solidity ^0.8.0;

contract airdrop {

using SafeMath for uint256;

// 数组求和函数
function getSum(uint256[] calldata _arr) public pure returns (uint sum)
{
bool state;
for (uint i = 0; i < _arr.length; i++) {
(state, sum) = sum.tryAdd(_arr[i]);
require(state == true, "over max");
}
}

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]);
}
}

/// 向多个地址转账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++) {
_addresses[i].transfer(_amounts[i]);
}
}

}

部署在 bsc 测试网 0x2062359C43E6B14E0E752a13034df1c21a514Adb

借用

过程

  • 地址 A mint 10000 个币
  • 地址 A 赋予空投合约地址关于这个币的权限
  • 地址 A 调用空投地址,批量转移 10000 个币
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from web3 import Web3

abi_erc20 = """[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"msg","type":"string"}],"name":"mathError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]"""

abi_aridrop = """[{"inputs":[{"internalType":"addresspayable[]","name":"_addresses","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"multiTransferETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"multiTransferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_arr","type":"uint256[]"}],"name":"getSum","outputs":[{"internalType":"uint256","name":"sum","type":"uint256"}],"stateMutability":"pure","type":"function"}]"""
w3 = Web3(Web3.HTTPProvider("https://bsc.getblock.io/testnet/?api_key=5deb2***"))

address = "0xD1B260aba3bA6f3D3099725b1b1C7cdD12581974"
contract_erc20 = "0xd1693560A107B2E12F32e925FDe1867EC38FA3c6"
contract_airdrop = "0x2062359C43E6B14E0E752a13034df1c21a514Adb"
private = ""

contract_erc20_ = w3.eth.contract(
address=Web3.toChecksumAddress(contract_erc20), abi=abi_erc20)
contract_airdrop_ = w3.eth.contract(
address=Web3.toChecksumAddress(contract_airdrop), abi=abi_aridrop)


def encode_mint():
tx_dic = contract_erc20_.functions.mint(10000). \
buildTransaction(
{
'gas': 500000,
}
)
return tx_dic


def encode_approve():
tx_dic = contract_erc20_.functions.approve(Web3.toChecksumAddress("0x2062359C43E6B14E0E752a13034df1c21a514Adb"), 10000). \
buildTransaction(
{
'gas': 500000,
}
)
return tx_dic


def encode_airdrop():
tx_dic = contract_airdrop_.functions.multiTransferToken(
Web3.toChecksumAddress("0xd1693560A107B2E12F32e925FDe1867EC38FA3c6"),
[
Web3.toChecksumAddress("0x177C713E09cA2C5B703C05E40F3846dD77108f94"),
Web3.toChecksumAddress("0x85D8b13f2D8B80AA4d8a58F7Bcb9AaAC562A67E8")
],
[200, 500]
). \
buildTransaction(
{
'gas': 500000,
}
)
return tx_dic


def send_transaction(tx_dic):
nonce = w3.eth.getTransactionCount(address)
tx_dic["nonce"] = nonce
tx_dic['gasPrice'] = w3.eth.gasPrice
sign_tx = w3.eth.account.signTransaction(tx_dic, private_key=private)
txn_hash = w3.eth.sendRawTransaction(sign_tx.rawTransaction)
print(Web3.toHex(txn_hash))
return Web3.toHex(txn_hash)


def get_wait_receipt(tx):
data = w3.eth.waitForTransactionReceipt(tx)
return data


if __name__ == '__main__':
print(get_wait_receipt(send_transaction(encode_mint())))
print(get_wait_receipt(send_transaction(encode_approve())))
print(get_wait_receipt(send_transaction(encode_airdrop())))
请我喝杯咖啡吧~