@@ -13,15 +13,30 @@ import { CurrencyTransferLib } from "../lib/CurrencyTransferLib.sol";
1313
1414// ========== Features ==========
1515import "../extension/Ownable.sol " ;
16-
17- contract AirdropERC20 is Initializable , Ownable , ReentrancyGuardUpgradeable , MulticallUpgradeable , IAirdropERC20 {
16+ import "../extension/PermissionsEnumerable.sol " ;
17+
18+ contract AirdropERC20 is
19+ Initializable ,
20+ Ownable ,
21+ PermissionsEnumerable ,
22+ ReentrancyGuardUpgradeable ,
23+ MulticallUpgradeable ,
24+ IAirdropERC20
25+ {
1826 /*///////////////////////////////////////////////////////////////
1927 State variables
2028 //////////////////////////////////////////////////////////////*/
2129
2230 bytes32 private constant MODULE_TYPE = bytes32 ("AirdropERC20 " );
2331 uint256 private constant VERSION = 1 ;
2432
33+ uint256 public payeeCount;
34+ uint256 public processedCount;
35+
36+ uint256 [] private indicesOfFailed;
37+
38+ mapping (uint256 => AirdropContent) private airdropContent;
39+
2540 /*///////////////////////////////////////////////////////////////
2641 Constructor + initializer logic
2742 //////////////////////////////////////////////////////////////*/
@@ -30,6 +45,7 @@ contract AirdropERC20 is Initializable, Ownable, ReentrancyGuardUpgradeable, Mul
3045
3146 /// @dev Initiliazes the contract, like a constructor.
3247 function initialize (address _defaultAdmin ) external initializer {
48+ _setupRole (DEFAULT_ADMIN_ROLE, _defaultAdmin);
3349 _setupOwner (_defaultAdmin);
3450 __ReentrancyGuard_init ();
3551 }
@@ -52,35 +68,96 @@ contract AirdropERC20 is Initializable, Ownable, ReentrancyGuardUpgradeable, Mul
5268 Airdrop logic
5369 //////////////////////////////////////////////////////////////*/
5470
55- /**
56- * @notice Lets contract-owner send ERC20 tokens to a list of addresses.
57- * @dev The token-owner should approve target tokens to Airdrop contract,
58- * which acts as operator for the tokens.
59- *
60- * @param _tokenAddress Contract address of ERC20 tokens to air-drop.
61- * @param _tokenOwner Address from which to transfer tokens.
62- * @param _recipients List of recipient addresses for the air-drop.
63- * @param _amounts Quantity of tokens to air-drop, per recipient.
64- */
65- function airdrop (
66- address _tokenAddress ,
67- address _tokenOwner ,
68- address [] memory _recipients ,
69- uint256 [] memory _amounts
70- ) external payable nonReentrant onlyOwner {
71- uint256 len = _amounts.length ;
72- require (len == _recipients.length , "length mismatch " );
73-
74- if (_tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
75- uint256 totalAmount;
76- for (uint256 i = 0 ; i < len; i++ ) {
77- totalAmount += _amounts[i];
71+ ///@notice Lets contract-owner set up an airdrop of ERC20 or native tokens to a list of addresses.
72+ function addAirdropRecipients (AirdropContent[] calldata _contents ) external payable onlyRole (DEFAULT_ADMIN_ROLE) {
73+ uint256 len = _contents.length ;
74+ require (len > 0 , "No payees provided. " );
75+
76+ uint256 currentCount = payeeCount;
77+ payeeCount += len;
78+
79+ uint256 nativeTokenAmount;
80+
81+ for (uint256 i = currentCount; i < len; i += 1 ) {
82+ airdropContent[i] = _contents[i];
83+
84+ if (_contents[i].tokenAddress == CurrencyTransferLib.NATIVE_TOKEN) {
85+ nativeTokenAmount += _contents[i].amount;
7886 }
79- require (totalAmount == msg .value , "Incorrect native token amount " );
8087 }
8188
82- for (uint256 i = 0 ; i < len; i++ ) {
83- CurrencyTransferLib.transferCurrency (_tokenAddress, _tokenOwner, _recipients[i], _amounts[i]);
89+ require (nativeTokenAmount == msg .value , "Incorrect native token amount " );
90+
91+ emit RecipientsAdded (_contents);
92+ }
93+
94+ /// @notice Lets contract-owner send ERC20 or native tokens to a list of addresses.
95+ function airdrop (uint256 paymentsToProcess ) external nonReentrant {
96+ uint256 totalPayees = payeeCount;
97+ uint256 countOfProcessed = processedCount;
98+
99+ require (countOfProcessed + paymentsToProcess <= totalPayees, "invalid no. of payments " );
100+
101+ processedCount += paymentsToProcess;
102+
103+ for (uint256 i = countOfProcessed; i < (countOfProcessed + paymentsToProcess); i += 1 ) {
104+ AirdropContent memory content = airdropContent[i];
105+
106+ CurrencyTransferLib.transferCurrency (
107+ content.tokenAddress,
108+ content.tokenOwner,
109+ content.recipient,
110+ content.amount
111+ );
112+
113+ emit AirdropPayment (content.recipient, content);
114+ }
115+ }
116+
117+ /*///////////////////////////////////////////////////////////////
118+ Airdrop view logic
119+ //////////////////////////////////////////////////////////////*/
120+
121+ /// @notice Returns all airdrop payments set up -- pending, processed or failed.
122+ function getAllAirdropPayments () external view returns (AirdropContent[] memory contents ) {
123+ uint256 count = payeeCount;
124+ contents = new AirdropContent [](count);
125+
126+ for (uint256 i = 0 ; i < count; i += 1 ) {
127+ contents[i] = airdropContent[i];
128+ }
129+ }
130+
131+ /// @notice Returns all pending airdrop payments.
132+ function getAllAirdropPaymentsPending () external view returns (AirdropContent[] memory contents ) {
133+ uint256 endCount = payeeCount;
134+ uint256 startCount = processedCount;
135+ contents = new AirdropContent [](endCount - startCount);
136+
137+ uint256 idx;
138+ for (uint256 i = startCount; i < endCount; i += 1 ) {
139+ contents[idx] = airdropContent[i];
140+ idx += 1 ;
141+ }
142+ }
143+
144+ /// @notice Returns all pending airdrop processed.
145+ function getAllAirdropPaymentsProcessed () external view returns (AirdropContent[] memory contents ) {
146+ uint256 count = processedCount;
147+ contents = new AirdropContent [](count);
148+
149+ for (uint256 i = 0 ; i < count; i += 1 ) {
150+ contents[i] = airdropContent[i];
151+ }
152+ }
153+
154+ /// @notice Returns all pending airdrop failed.
155+ function getAllAirdropPaymentsFailed () external view returns (AirdropContent[] memory contents ) {
156+ uint256 count = indicesOfFailed.length ;
157+ contents = new AirdropContent [](count);
158+
159+ for (uint256 i = 0 ; i < count; i += 1 ) {
160+ contents[i] = airdropContent[indicesOfFailed[i]];
84161 }
85162 }
86163
0 commit comments