Last active
September 25, 2023 19:54
-
-
Save WPSmartContracts/fc9f60d3b5442e48b9f13079592eaec8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.2; | |
// Standard OpenZeppelin Contracts | |
import "../access/Ownable.sol"; | |
import "../security/ReentrancyGuard.sol"; | |
import "../token/ERC20/IERC20.sol"; | |
import "../utils/Address.sol"; | |
import "../token/ERC20/utils/SafeERC20.sol"; | |
import "../utils/Context.sol"; | |
import "../security/Pausable.sol"; | |
/** | |
* Tiramisu – A whitelisted airdrop that allows recipients to receive a fixed amount at once | |
* Owner can bulk load the total amount of tokens for each beneficiary | |
* Beneficiaries can claim the tokens at any time | |
*/ | |
contract Tiramisu is Ownable, Pausable, ReentrancyGuard { | |
using SafeERC20 for IERC20; | |
// The token to be airdropped | |
IERC20 public token; | |
// The wallet that holds the funds for the airdrop | |
address public wallet; | |
// Amount of tokens to claim per beneficiary | |
mapping (address => uint256) public totalTokens; | |
// Event emitted when a beneficiary is loaded with tokens | |
event BeneficiaryLoaded(address indexed user, uint256 qty); | |
// Event emitted when a beneficiary claims tokens | |
event Claim(address indexed user, uint256 qty); | |
// Event emitted when the owner sets a new Token | |
event TokenChanged(address indexed newToken); | |
// Event emitted when the owner sets a new Wallet | |
event WalletChanged(address indexed newWallet); | |
/** | |
* Constructor to initialize the Tiramisu contract | |
* @param _token The ERC20 token contract address | |
* @param _owner The initial owner of the contract | |
* @param _wallet The address holding the airdrop tokens | |
*/ | |
constructor (IERC20 _token, address _owner, address _wallet) Ownable() { | |
require(address(_token)!=address(0), "Token cannot be the zero address"); | |
require(_wallet!=address(0), "Wallet cannot be the zero address"); | |
token = _token; | |
wallet = _wallet; | |
transferOwnership(_owner); | |
} | |
/** | |
* @dev Allows the contract owner to bulk load the addresses and their corresponding total token amounts for airdrop. | |
* @param beneficiaries_ Array of beneficiary addresses. Zero Addresses are ignored | |
* @param quantities_ Array of total token quantities to airdrop to each account | |
*/ | |
function load(address[] memory beneficiaries_, uint256[] memory quantities_) external onlyOwner { | |
for (uint256 index = 0; index < beneficiaries_.length; index++) { | |
if (beneficiaries_[index] != address(0)) { | |
emit BeneficiaryLoaded(beneficiaries_[index], quantities_[index]); | |
totalTokens[beneficiaries_[index]] = quantities_[index]; | |
} | |
} | |
} | |
/** | |
* @dev Allows the contract owner to load a single beneficiary's address and the total token amount to airdrop to their account. | |
* @param beneficiary_ The address of the beneficiary | |
* @param qty_ The quantity of tokens to airdrop to the account | |
*/ | |
function loadSingle(address beneficiary_, uint256 qty_) external onlyOwner { | |
require(address(beneficiary_)!=address(0), "Beneficiary cannot be the zero address"); | |
totalTokens[beneficiary_] = qty_; | |
emit BeneficiaryLoaded(beneficiary_, qty_); | |
} | |
/** | |
* @dev Allows beneficiaries to claim the tokens allocated to them. The claim is subject to available balance and approval by the contract owner. | |
*/ | |
function claim() external nonReentrant whenNotPaused { | |
uint256 _amountToClaim = totalTokens[msg.sender]; | |
require(_amountToClaim > 0, "Error: No tokens available for claiming."); | |
// Check allowance before transferring tokens | |
uint256 allowance = token.allowance(wallet, address(this)); | |
require(allowance >= _amountToClaim, "Insufficient allowance. Approve the contract to spend tokens."); | |
totalTokens[msg.sender] = 0; | |
emit Claim(msg.sender, _amountToClaim); | |
token.safeTransferFrom(wallet, msg.sender, _amountToClaim); | |
} | |
/** | |
* Owner functions to set contract parameters | |
*/ | |
/** | |
* @dev Changes the address of the ERC20 token contract. Only the contract owner can perform this action. | |
* @param token_ The new ERC20 token contract address | |
*/ | |
function changeToken(IERC20 token_) external onlyOwner { | |
require(address(token_)!=address(0), "Token cannot be the zero address"); | |
emit TokenChanged(address(token_)); | |
token = token_; | |
} | |
/** | |
* @dev Changes the wallet address holding the airdrop tokens. Only the contract owner can perform this action. | |
* @param _wallet The new wallet address | |
*/ | |
function changeWallet(address _wallet) external onlyOwner { | |
require(_wallet!=address(0), "Wallet cannot be the zero address"); | |
emit WalletChanged(_wallet); | |
wallet = _wallet; | |
} | |
/** | |
* @dev Pause the airdrop activity | |
*/ | |
function pause() external onlyOwner() { | |
_pause(); | |
} | |
/** | |
* @dev Resume the airdrop activity | |
*/ | |
function unpause() external onlyOwner() { | |
_unpause(); | |
} | |
// Fallback function to handle accidental transfers of Ether and revert them. | |
receive() external payable { | |
revert("Ether transfers are not accepted by this contract."); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment