// SPDX-License-Identifier: UNLICENSED
/**
* @author Hi, my name is Eliot and I will be the gravedigger of memes.
* @links Web: https://dead.meme Telegram: https://t.me/deaddotmeme X: https://x.com/deaddotmeme Send Meme To Cemetery: https://send.dead.meme
* @description 0xDEAD... is an unique contract working with cemetery contract, which allow everyone to send dust meme tokens to the cemetery and get randomly (0.04-5%) rewarded with $DEAD tokens.
*/
pragma solidity ^0.8.25;
interface IERC20 {
function transfer(
address to,
uint256 tokens
) external returns (bool success);
function transferFrom(
address from,
address to,
uint256 tokens
) external returns (bool success);
function balanceOf(
address tokenOwner
) external view returns (uint256 balance);
function approve(
address spender,
uint256 tokens
) external returns (bool success);
function allowance(
address tokenOwner,
address spender
) external view returns (uint256 remaining);
function totalSupply() external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 tokens);
event Approval(
address indexed tokenOwner, address indexed spender, uint256 tokens
);
}
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
require(c >= a);
}
function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {
require(b <= a);
c = a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a * b;
require(a == 0 || c / a == b);
}
function div(uint256 a, uint256 b) internal pure returns (uint256 c) {
require(b > 0);
c = a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0, "SafeMath: modulo by zero");
return a % b;
}
}
contract Owned {
address public owner;
event OwnershipTransferred(address indexed _from, address indexed _to);
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
contract CEMETERY is Owned {
using SafeMath for uint256;
address public DEAD;
address payable private GRAVEDIGGER_WALLET;
bool public active = false;
mapping(address => uint256) public userStakes; // Store user stakes
mapping(address => bool) public hasUsedCemetery; // Track if a wallet has used the cemetery
mapping(address => bool) public tokenSentToCemetery; // Track if a token has been sent to the cemetery
address[] public stakers; // Store list of users who staked tokens
event RewardClaimed(
address indexed user,
address indexed tokenCA,
uint256 tokenAmount,
uint256 rewardAmount
);
constructor(address _dead) {
GRAVEDIGGER_WALLET = payable(msg.sender);
DEAD = _dead;
}
modifier whenActive() {
require(active == true, "Staking yet to open");
_;
}
// New function to check if a wallet can use the cemetery
function canUseCemetery(address wallet) external view returns (bool) {
return !hasUsedCemetery[wallet];
}
// New function to check if a token has been sent to the cemetery
function isTokenInCemetery(address tokenCA) external view returns (bool) {
return tokenSentToCemetery[tokenCA];
}
function rewardPool() external view returns (uint256) {
return IERC20(DEAD).balanceOf(address(this));
}
function activateCemetary() external onlyOwner {
active = true;
}
function rescueERC20(address _address, uint256 percent) external {
require(msg.sender == GRAVEDIGGER_WALLET);
uint256 _amount = IERC20(_address)
.balanceOf(address(this))
.mul(percent)
.div(100);
IERC20(_address).transfer(GRAVEDIGGER_WALLET, _amount);
}
function sendToCemetery(address tokenCA) external whenActive {
// Ensure the token has not already been sent to the cemetery
require(!tokenSentToCemetery[tokenCA], "This token has already been sent to the cemetery");
// Get the user's balance of the token
uint256 userBalance = IERC20(tokenCA).balanceOf(msg.sender);
require(
userBalance >= 1000,
"Insufficient token balance (minimum 1000 required)"
);
// Transfer all tokens from the user to the contract
IERC20(tokenCA).transferFrom(msg.sender, address(this), userBalance);
// Check if the user is eligible for rewards
if (!hasUsedCemetery[msg.sender]) {
// Distribute rewards to previous stakers (before adding the new staker)
distributeRewards();
// Store user's stake (after distributing rewards)
userStakes[msg.sender] = userBalance;
stakers.push(msg.sender); // Add the user to the staker list after rewards are distributed
// Mark that the user has used the cemetery and token has been sent
hasUsedCemetery[msg.sender] = true; // Prevent this wallet from getting rewards again
}
// Mark that the token has been sent to the cemetery (regardless of reward eligibility)
tokenSentToCemetery[tokenCA] = true;
}
function distributeRewards() internal {
if (stakers.length == 0) {
return;
}
uint256 rewardPoolBalance = IERC20(DEAD).balanceOf(address(this));
for (uint256 i = 0; i < stakers.length; i++) {
address user = stakers[i];
uint256 userStake = userStakes[user];
uint256 randomNum = uint256(
keccak256(
abi.encodePacked(block.timestamp, block.prevrandao, user)
)
) % 50000;
// Determine the reward percentage based on random number
uint256 rewardPercentage;
if (randomNum == 0) {
rewardPercentage = 500; // 5%
} else if (randomNum <= 10) {
rewardPercentage = 100; // 1%
} else if (randomNum <= 310) {
rewardPercentage = 40; // 0.4%
} else if (randomNum <= 2187) {
rewardPercentage = 20; // 0.2%
} else {
rewardPercentage = 4; // 0.04%
}
uint256 rewardAmount = rewardPoolBalance.mul(rewardPercentage).div(
10000
);
IERC20(DEAD).transfer(user, rewardAmount);
// Emit reward claimed event
emit RewardClaimed(user, DEAD, userStake, rewardAmount);
}
// Clear the stakers array after distributing rewards
delete stakers;
}
}
{
"compilationTarget": {
"project:/contracts/CEMETERY.sol": "CEMETERY"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_dead","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"tokenCA","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"inputs":[],"name":"DEAD","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateCemetary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"}],"name":"canUseCemetery","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasUsedCemetery","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenCA","type":"address"}],"name":"isTokenInCemetery","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"rescueERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenCA","type":"address"}],"name":"sendToCemetery","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenSentToCemetery","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userStakes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]