Skip to content

Instantly share code, notes, and snippets.

@WPSmartContracts
Last active September 25, 2023 19:54
Show Gist options
  • Save WPSmartContracts/fc9f60d3b5442e48b9f13079592eaec8 to your computer and use it in GitHub Desktop.
Save WPSmartContracts/fc9f60d3b5442e48b9f13079592eaec8 to your computer and use it in GitHub Desktop.
// 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