// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
interface Token {
function transfer(address to, uint256 value) external returns (bool);
function balanceOf(address who) external view returns (uint256);
}
contract MiningContract {
address public owner;
address public token;
uint256 public constant DEFAULT_MINING_RATE = 0.0000001 ether; // 0.0000001 token per second
uint256 public constant BONUS_LIMIT = 3000;
uint256 public constant BONUS_TOKENS = 6000 ether;
uint256 public minerCount;
mapping(address => uint256) public miningStartTimes;
event Mined(address indexed miner, uint256 tokensMined);
event TokenWithdrawn(address indexed miner, uint256 tokensWithdrawn);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address _token) {
owner = msg.sender;
token = _token;
minerCount = 0;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
function mine() public payable {
require(msg.value == 100000000000000000, "Mine function requires 0.1 ETH fee");
require(miningStartTimes[msg.sender] == 0, "You have already started mining");
miningStartTimes[msg.sender] = block.timestamp;
minerCount++;
emit Mined(msg.sender, DEFAULT_MINING_RATE);
// first 3000
if (minerCount <= BONUS_LIMIT) {
_sendBonusTokens(msg.sender);
}
}
function _sendBonusTokens(address _miner) internal {
(bool success, ) = token.call(abi.encodeWithSignature("transfer(address,uint256)", _miner, BONUS_TOKENS));
require(success, "Bonus token transfer failed");
}
function getTokensMined(address _miner) public view returns (uint256) {
require(miningStartTimes[_miner] != 0, "This user has not started mining yet");
uint256 elapsedTime = block.timestamp - miningStartTimes[_miner];
uint256 tokensMined = elapsedTime * DEFAULT_MINING_RATE;
return tokensMined;
}
function withdrawToken() public {
require(miningStartTimes[msg.sender] != 0, "You have not started mining yet");
uint256 elapsedTime = block.timestamp - miningStartTimes[msg.sender];
uint256 tokenAmount = elapsedTime * DEFAULT_MINING_RATE;
(bool success, ) = token.call(abi.encodeWithSignature("transfer(address,uint256)", msg.sender, tokenAmount));
require(success, "Token transfer failed");
miningStartTimes[msg.sender] = block.timestamp;
emit TokenWithdrawn(msg.sender, tokenAmount);
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "New owner is the zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
{
"compilationTarget": {
"MiningContract.sol": "MiningContract"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"miner","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensMined","type":"uint256"}],"name":"Mined","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":"miner","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokensWithdrawn","type":"uint256"}],"name":"TokenWithdrawn","type":"event"},{"inputs":[],"name":"BONUS_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BONUS_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_MINING_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_miner","type":"address"}],"name":"getTokensMined","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mine","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"minerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"miningStartTimes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]