//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.0;

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

contract Wolfcoin is ERC20, Ownable {
    // Libaries —————————————————————————————————————————————————————
    using SafeMath for uint256;

    // Events ———————————————————————————————————————————————————————
    event WillClaim(address indexed claimant, uint256 amount);
    event DidClaim(address indexed claimant, uint256 amount);

    // Constants ————————————————————————————————————————————————————
    // Aggregate supply in wei.
    uint256 private constant AGGREGATE_SUPPLY = 1_337_069_420_000e18;
    // Allocate 80% of the supply to the market.
    uint256 private constant MARKET_SUPPLY = 1_069_655_536_000e18;
    // Date when airdrop is completed and remaining airdrop supply is burned.
    uint256 private constant MINIMUM_BALANCE = 0.25 ether; 
    // 1e16 represents 0.01% reduction after each subsequent claim.
    uint256 private constant CLAIM_REDUCTION = 1e16; 
    // 1e20 represents dividing by 100 as a percentage.
    uint256 private constant CLAIM_DIVISOR = 1e20;

    // Airdrop state ————————————————————————————————————————————————
    // List of addresses that have previously claimed the airdrop.
    mapping(address => bool) private claimed;
    // Represents the state of the airdrop (in/active).
    bool private isAirdropActive;
    // Allocate the remaining 20% supply to the airdrop.
    uint256 public airdropSupply = AGGREGATE_SUPPLY - MARKET_SUPPLY;
    // 1e18 represents 1% as the starting claim percentage.
    uint256 public claimRatio = 1e18;

    constructor(address marketSupplyOwnerAddress) ERC20("Wolfcoin", "WOLF") {
        _mint(marketSupplyOwnerAddress, MARKET_SUPPLY);
        _mint(address(this), airdropSupply);
        isAirdropActive = true;
    }

    // [α] To preventing underflow the order of operation matters `uint256.mul(MULTIPLE).div(DIVISOR)`.
    function claimAirdrop() public returns (uint256) {
        require(isAirdropActive, "Wolfcoin: Claim is inactive.");
        require(airdropSupply > 0, "Wolfcoin: Airdrop supply gone.");
        require(msg.sender.balance >= MINIMUM_BALANCE, "Wolfcoin: Balance too low.");
        require(!claimed[msg.sender], "Wolfcoin: Already claimed.");
        claimed[msg.sender] = true;

        // Transfer claim amount to caller.
        uint256 claimAmount = airdropSupply.mul(claimRatio).div(CLAIM_DIVISOR); // α
        emit WillClaim(msg.sender, claimAmount);
        _transfer(address(this), msg.sender, claimAmount);
        emit DidClaim(msg.sender, claimAmount);

        // Update claim permillages for next caller.
        claimRatio -= claimRatio.mul(CLAIM_REDUCTION).div(CLAIM_DIVISOR); // α
        airdropSupply -= claimAmount;

        return claimAmount;
    }

    function burnRemainingAirdrop() public onlyOwner {
        require(isAirdropActive, "Wolfcoin: Claim is active.");
        _transfer(address(this), address(0), balanceOf(address(this)));
    }

    function deactivateAirdrop() public onlyOwner {
        isAirdropActive = false;
    }
}
[{"inputs":[{"internalType":"address","name":"marketSupplyOwnerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DidClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimant","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WillClaim","type":"event"},{"inputs":[],"name":"airdropSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"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":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnRemainingAirdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimAirdrop","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deactivateAirdrop","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","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"},{"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"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]