-
Notifications
You must be signed in to change notification settings - Fork 2
/
Wentokens.sol
129 lines (121 loc) · 6.25 KB
/
Wentokens.sol
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// From: https://github.com/magna-eng/wentokens/blob/main/contracts/src/Airdrop.sol
// License: https://github.com/magna-eng/wentokens/blob/33525bd94508f0976e114bcbc6761add2a21ad06/LICENSE.md
// Pragma modified to 0.8.20
pragma solidity 0.8.20;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/**
* ▄█ █▄ ▄████████ ███▄▄▄▄ ███ ▄██████▄ ▄█ ▄█▄ ▄████████ ███▄▄▄▄ ▄████████
* ███ ███ ███ ███ ███▀▀▀██▄ ▀█████████▄ ███ ███ ███ ▄███▀ ███ ███ ███▀▀▀██▄ ███ ███
* ███ ███ ███ █▀ ███ ███ ▀███▀▀██ ███ ███ ███▐██▀ ███ █▀ ███ ███ ███ █▀
* ███ ███ ▄███▄▄▄ ███ ███ ███ ▀ ███ ███ ▄█████▀ ▄███▄▄▄ ███ ███ ███
* ███ ███ ▀▀███▀▀▀ ███ ███ ███ ███ ███ ▀▀█████▄ ▀▀███▀▀▀ ███ ███ ▀███████████
* ███ ███ ███ █▄ ███ ███ ███ ███ ███ ███▐██▄ ███ █▄ ███ ███ ███
* ███ ▄█▄ ███ ███ ███ ███ ███ ███ ███ ███ ███ ▀███▄ ███ ███ ███ ███ ▄█ ███
* ▀███▀███▀ ██████████ ▀█ █▀ ▄████▀ ▀██████▀ ███ ▀█▀ ██████████ ▀█ █▀ ▄████████▀
* ▀
*/
/**
* @title Magna Airdrop | wentokens.xyz
* @notice Hyper efficient Airdrop contract for ERC20 and ETH
* @author Harrison (@PopPunkOnChain)
* @author Magna (@MagnaTokens)
*/
contract Airdrop {
/**
*
* @param _recipients list of recipients
* @param _amounts list of amounts to send each recipient
*/
function airdropETH(address[] calldata _recipients, uint256[] calldata _amounts) external payable {
// looop through _recipients
assembly {
// store runningTotal
let runningTotal := 0
// store length of _recipients
let sz := _amounts.length
for { let i := 0 } lt(i, sz) {
// increment i
i := add(i, 1)
} {
// store offset for _amounts[i]
let offset := mul(i, 0x20)
// store _amounts[i]
let amt := calldataload(add(_amounts.offset, offset))
// store _recipients[i]
let recp := calldataload(add(_recipients.offset, offset))
// send _amounts[i] to _recipients[i]
let success :=
call(
gas(),
recp, // address
amt, // amount
0,
0,
0,
0
)
// revert if call fails
if iszero(success) { revert(0, 0) }
// add _amounts[i] to runningTotal
runningTotal := add(runningTotal, amt)
}
// revert if runningTotal != msg.value
if iszero(eq(runningTotal, callvalue())) { revert(0, 0) }
}
}
/**
*
* @param _token ERC20 token to airdrop
* @param _recipients list of recipients
* @param _amounts list of amounts to send each recipient
* @param _total total amount to transfer from caller
*/
function airdropERC20(IERC20 _token, address[] calldata _recipients, uint256[] calldata _amounts, uint256 _total)
external
{
// bytes selector for transferFrom(address,address,uint256)
bytes4 transferFrom = 0x23b872dd;
// bytes selector for transfer(address,uint256)
bytes4 transfer = 0xa9059cbb;
assembly {
// store transferFrom selector
let transferFromData := add(0x20, mload(0x40))
mstore(transferFromData, transferFrom)
// store caller address
mstore(add(transferFromData, 0x04), caller())
// store address
mstore(add(transferFromData, 0x24), address())
// store _total
mstore(add(transferFromData, 0x44), _total)
// call transferFrom for _total
let successTransferFrom := call(gas(), _token, 0, transferFromData, 0x64, 0, 0)
// revert if call fails
if iszero(successTransferFrom) { revert(0, 0) }
// store transfer selector
let transferData := add(0x20, mload(0x40))
mstore(transferData, transfer)
// store length of _recipients
let sz := _amounts.length
// loop through _recipients
for { let i := 0 } lt(i, sz) {
// increment i
i := add(i, 1)
} {
// store offset for _amounts[i]
let offset := mul(i, 0x20)
// store _amounts[i]
let amt := calldataload(add(_amounts.offset, offset))
// store _recipients[i]
let recp := calldataload(add(_recipients.offset, offset))
// store _recipients[i] in transferData
mstore(add(transferData, 0x04), recp)
// store _amounts[i] in transferData
mstore(add(transferData, 0x24), amt)
// call transfer for _amounts[i] to _recipients[i]
let successTransfer := call(gas(), _token, 0, transferData, 0x44, 0, 0)
// revert if call fails
if iszero(successTransfer) { revert(0, 0) }
}
}
}
}