Transaction Hash:
Block:
16979003 at Apr-05-2023 12:18:11 AM +UTC
Transaction Fee:
0.00602338348590498 ETH
$15.36
Gas Used:
211,770 Gas / 28.443044274 Gwei
Emitted Events:
163 |
LuckyRoo.Transfer( from=[Receiver] LuckyRooAirdrop, to=[Sender] 0x99f378488b93f1f74cdfbdc7f23c5dd20babf508, value=897947833185508056200903337 )
|
164 |
LuckyRooAirdrop.Claim( user=[Sender] 0x99f378488b93f1f74cdfbdc7f23c5dd20babf508, amount=897947833185508056200903337 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x5A7C9842...C12C0B1c2 | |||||
0x5F927395...C0F16844F
Miner
| (Manta-builder) | 6.839005297558543259 Eth | 6.839026474558543259 Eth | 0.000021177 | |
0x99F37848...20BABf508 |
0.034133803099110711 Eth
Nonce: 346
|
0.027590419613205731 Eth
Nonce: 347
| 0.00654338348590498 | ||
0x9d7107c8...ae8bbA938 | |||||
0xE2123f0F...8e0102D44 | 0.066598010452204569 Eth | 0.067118010452204569 Eth | 0.00052 |
Execution Trace
ETH 0.00052
LuckyRooAirdrop.CALL( )
- ETH 0.00052
0xe2123f0f85953414eb3b4dfa97790ec8e0102d44.CALL( )
-
LuckyRoo.transfer( recipient=0x99F378488B93F1f74cDfbDC7f23c5dD20BABf508, amount=897947833185508056200903337 ) => ( True )
File 1 of 2: LuckyRooAirdrop
File 2 of 2: LuckyRoo
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; pragma abicoder v2; /** * @author Brewlabs * This contract has been developed by brewlabs.info */ import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol"; import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; import "../libs/IPriceOracle.sol"; interface IPegSwap { function swap(uint256 amount, address source, address target) external; function getSwappableAmount(address source, address target) external view returns (uint256); } contract LuckyRooAirdrop is ReentrancyGuard, VRFConsumerBaseV2, Ownable { using SafeERC20 for IERC20; VRFCoordinatorV2Interface COORDINATOR; LinkTokenInterface LINKTOKEN; bool public initialized = false; IERC20 public token; IPriceOracle private oracle; uint64 public s_subscriptionId; bytes32 keyHash; uint32 callbackGasLimit = 150000; uint16 requestConfirmations = 3; uint32 numWords = 3; uint256 public s_requestId; uint256 public r_requestId; uint256[] public s_randomWords; struct AirdropResult { address[3] winner; uint256[3] amount; } uint256 public currentID = 1; uint256 public distributeRate = 9500; uint256 public distributorLimit = 500 ether; uint256[3] public airdropRates = [6000, 2500, 1000]; mapping(uint256 => AirdropResult) private results; uint256 public lastAirdropTime; struct DistributorInfo { uint256 amount; uint256 regAirdropID; } mapping(address => DistributorInfo) public userInfo; address[] public distributors; address public treasury = 0xE2123f0F85953414eb3B4Dfa97790ec8e0102D44; uint256 public performanceFee = 0.00052 ether; uint256 public totalStaked; // BSC Mainnet ERC20_LINK_ADDRESS address public constant ERC20_LINK_ADDRESS = 0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD; address public constant PEGSWAP_ADDRESS = 0x1FCc3B22955e76Ca48bF025f1A6993685975Bb9e; event AddDistributor(address user, uint256 amount); event Claim(address user, uint256 amount); event HolderDistributed(uint256 id, address[3] winners, uint256[3] amounts); event SetDistributorLimit(uint256 limit); event SetDistributorRates(uint256[3] rates); event ServiceInfoUpadted(address addr, uint256 fee); /** * @notice Constructor * @dev RandomNumberGenerator must be deployed prior to this contract */ constructor(address _vrfCoordinator, address _link, bytes32 _keyHash) VRFConsumerBaseV2(_vrfCoordinator) { COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); s_subscriptionId = COORDINATOR.createSubscription(); keyHash = _keyHash; COORDINATOR.addConsumer(s_subscriptionId, address(this)); LINKTOKEN = LinkTokenInterface(_link); } /** * @notice Initialize the contract * @dev This function must be called by the owner of the contract. */ function initialize(address _token, address _oracle) external onlyOwner { require(!initialized, "Contract already initialized"); initialized = true; token = IERC20(_token); oracle = IPriceOracle(_oracle); } function addDistributor() external payable nonReentrant { require(initialized, "Contract not initialized"); require(!isContract(msg.sender), "contract cannot be distributor"); DistributorInfo storage user = userInfo[msg.sender]; require(user.regAirdropID < currentID, "already added"); require(user.amount == 0, "claim previous stake first"); _transferPerformanceFee(); uint256 tokenPrice = oracle.getTokenPrice(address(token)); uint256 tokenBal = token.balanceOf(msg.sender); uint256 amount = distributorLimit * 1 ether / tokenPrice; require(tokenPrice > 0, "LUCKY ROO price is missing"); require(tokenBal >= amount, "insufficient holder balance"); uint256 beforeAmt = token.balanceOf(address(this)); token.safeTransferFrom(msg.sender, address(this), amount); uint256 realAmt = token.balanceOf(address(this)) - beforeAmt; if (realAmt > amount) realAmt = amount; user.amount = realAmt; user.regAirdropID = currentID; distributors.push(msg.sender); totalStaked += user.amount; emit AddDistributor(msg.sender, realAmt); } function claim() external payable nonReentrant { DistributorInfo storage user = userInfo[msg.sender]; require(user.amount > 0, "not registered"); require(user.regAirdropID < currentID, "can claim after this round is finished"); _transferPerformanceFee(); token.safeTransfer(msg.sender, user.amount); emit Claim(msg.sender, user.amount); totalStaked -= user.amount; user.amount = 0; } function _transferPerformanceFee() internal { require(msg.value >= performanceFee, "should pay small gas to add as a distributor"); payable(treasury).transfer(performanceFee); if (msg.value > performanceFee) { payable(msg.sender).transfer(msg.value - performanceFee); } } function numDistributors() external view returns (uint256) { return distributors.length; } /** * @notice Distribute the prizes to the three winners * @dev This function must be called by the owner of the contract. */ function callAirdrop() external onlyOwner { require(initialized, "Contract not initialized"); require(s_requestId == r_requestId, "Request IDs do not match"); require(s_randomWords.length == numWords, "Number of words does not match"); uint256 numHolders = distributors.length; require(numHolders > 3, "Not enough distributors"); s_requestId = 0; uint256[3] memory idx; uint256[3] memory sortedIdx; for (uint256 i = 0; i < 3; i++) { idx[i] = s_randomWords[i] % (numHolders - i); for (uint256 j = 0; j < i; j++) { if (idx[i] >= sortedIdx[j]) { idx[i] = idx[i] + 1; } else { break; } } idx[i] = idx[i] % numHolders; sortedIdx[i] = idx[i]; if (i > 0 && sortedIdx[i] < sortedIdx[i - 1]) { uint256 t = sortedIdx[i]; sortedIdx[i] = sortedIdx[i - 1]; sortedIdx[i - 1] = t; } } AirdropResult storage airdropResult = results[currentID]; uint256 amount = address(this).balance; amount = amount * distributeRate / 10000; for (uint256 i = 0; i < 3; i++) { address winnerA = distributors[idx[i]]; airdropResult.winner[i] = winnerA; uint256 amountA = amount * airdropRates[i] / 10000; airdropResult.amount[i] = amountA; payable(winnerA).transfer(amountA); } emit HolderDistributed(currentID, airdropResult.winner, airdropResult.amount); currentID = currentID + 1; lastAirdropTime = block.timestamp; distributors = new address[](0); } function getAirdropResult(uint256 _id) external view returns (address[3] memory, uint256[3] memory) { return (results[_id].winner, results[_id].amount); } /** * @notice Set the distribution rates for the three wallets * @dev This function must be called by the owner of the contract. */ function setAirdropRates(uint256 _rateA, uint256 _rateB, uint256 _rateC) external onlyOwner { require(_rateA > 0, "Rate A must be greater than 0"); require(_rateB > 0, "Rate B must be greater than 0"); require(_rateC > 0, "Rate C must be greater than 0"); require(_rateA + _rateB + _rateC < 10000, "Total rate must be less than 10000"); airdropRates = [_rateA, _rateB, _rateC]; emit SetDistributorRates(airdropRates); } /** * @notice Set the minimum holding tokens to add distributor in usd * @dev This function must be called by the owner of the contract. */ function setDistributorBalanceLimit(uint256 _min) external onlyOwner { distributorLimit = _min * 1 ether; emit SetDistributorLimit(_min); } function setServiceInfo(address _treasury, uint256 _fee) external { require(msg.sender == treasury, "setServiceInfo: FORBIDDEN"); require(_treasury != address(0x0), "Invalid address"); treasury = _treasury; performanceFee = _fee; emit ServiceInfoUpadted(_treasury, _fee); } function setCoordiatorConfig(bytes32 _keyHash, uint32 _gasLimit, uint32 _numWords) external onlyOwner { keyHash = _keyHash; callbackGasLimit = _gasLimit; numWords = _numWords; } /** * @notice fetch subscription information from the VRF coordinator */ function getSubscriptionInfo() external view returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers) { return COORDINATOR.getSubscription(s_subscriptionId); } /** * @notice cancle subscription from the VRF coordinator * @dev This function must be called by the owner of the contract. */ function cancelSubscription() external onlyOwner { COORDINATOR.cancelSubscription(s_subscriptionId, msg.sender); s_subscriptionId = 0; } /** * @notice subscribe to the VRF coordinator * @dev This function must be called by the owner of the contract. */ function startSubscription(address _vrfCoordinator) external onlyOwner { require(s_subscriptionId == 0, "Subscription already started"); COORDINATOR = VRFCoordinatorV2Interface(_vrfCoordinator); s_subscriptionId = COORDINATOR.createSubscription(); COORDINATOR.addConsumer(s_subscriptionId, address(this)); } /** * @notice Fund link token from the VRF coordinator for subscription * @dev This function must be called by the owner of the contract. */ function fundToCoordiator(uint96 _amount) external onlyOwner { LINKTOKEN.transferFrom(msg.sender, address(this), _amount); LINKTOKEN.transferAndCall(address(COORDINATOR), _amount, abi.encode(s_subscriptionId)); } /** * @notice Fund link token from the VRF coordinator for subscription * @dev This function must be called by the owner of the contract. */ function fundPeggedLinkToCoordiator(uint256 _amount) external onlyOwner { IERC20(ERC20_LINK_ADDRESS).transferFrom(msg.sender, address(this), _amount); IERC20(ERC20_LINK_ADDRESS).approve(PEGSWAP_ADDRESS, _amount); IPegSwap(PEGSWAP_ADDRESS).swap(_amount, ERC20_LINK_ADDRESS, address(LINKTOKEN)); uint256 tokenBal = LINKTOKEN.balanceOf(address(this)); LINKTOKEN.transferAndCall(address(COORDINATOR), tokenBal, abi.encode(s_subscriptionId)); } /** * @notice Request random words from the VRF coordinator * @dev This function must be called by the owner of the contract. */ function requestRandomWords() external onlyOwner { r_requestId = 0; // Will revert if subscription is not set and funded. s_requestId = COORDINATOR.requestRandomWords(keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, numWords); } function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { r_requestId = requestId; s_randomWords = randomWords; } function emergencyWithdrawETH() external onlyOwner { uint256 _tokenAmount = address(this).balance; payable(msg.sender).transfer(_tokenAmount); } /** * @notice It allows the admin to recover wrong tokens sent to the contract * @param _token: the address of the token to withdraw * @dev This function is only callable by admin. */ function emergencyWithdrawToken(address _token) external onlyOwner { uint256 _tokenAmount = IERC20(_token).balanceOf(address(this)); IERC20(_token).safeTransfer(msg.sender, _tokenAmount); } function isContract(address _addr) internal view returns (bool) { uint256 size; assembly { size := extcodesize(_addr) } return size > 0; } receive() external payable {} } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance(address owner, address spender) external view returns (uint256 remaining); function approve(address spender, uint256 value) external returns (bool success); function balanceOf(address owner) external view returns (uint256 balance); function decimals() external view returns (uint8 decimalPlaces); function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); function increaseApproval(address spender, uint256 subtractedValue) external; function name() external view returns (string memory tokenName); function symbol() external view returns (string memory tokenSymbol); function totalSupply() external view returns (uint256 totalTokensIssued); function transfer(address to, uint256 value) external returns (bool success); function transferAndCall( address to, uint256 value, bytes calldata data ) external returns (bool success); function transferFrom( address from, address to, uint256 value ) external returns (bool success); } // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; } // SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } } // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.0; interface IPriceOracle { /** * @notice Get the price of a token * @param token The token to get the price of * @return The asset price mantissa (scaled by 1e18). * Zero means the price is unavailable. */ function getTokenPrice(address token) external view returns (uint256); } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) pragma solidity ^0.8.0; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
File 2 of 2: LuckyRoo
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IERC20 { function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 amount) external returns (bool); function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); } interface IFactory { function createPair(address tokenA, address tokenB) external returns (address pair); function getPair(address tokenA, address tokenB) external view returns (address pair); } interface IRouter { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountETH, uint256 liquidity ); function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; } library SafeMath { function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } library Address { function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } function sendValue(address payable recipient, uint256 amount) internal { require( address(this).balance >= amount, "Address: insufficient balance" ); (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}( data ); return _verifyCallResult(success, returndata, errorMessage); } function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall( target, data, "Address: low-level static call failed" ); } function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private pure returns (bytes memory) { if (success) { return returndata; } else { if (returndata.length > 0) { assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } function owner() public view returns (address) { return _owner; } modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } contract LuckyRoo is IERC20, Ownable { using Address for address; using SafeMath for uint256; IRouter public uniswapV2Router; address public immutable uniswapV2Pair; string private constant _name = "LUCKY ROO"; string private constant _symbol = "ROO"; uint8 private constant _decimals = 18; mapping (address => uint256) private _rOwned; mapping (address => uint256) private _tOwned; mapping (address => mapping (address => uint256)) private _allowances; uint256 private constant MAX = ~uint256(0); uint256 private constant _tTotal = 10000000000000 * 10**18; uint256 private _rTotal = (MAX - (MAX % _tTotal)); uint256 private _tFeeTotal; bool public isTradingEnabled; // max wallet is 1.5% of _tTotal uint256 public maxWalletAmount = _tTotal * 150 / 10000; // max buy and sell tx is 0.5% of _tTotal uint256 public maxTxAmount = _tTotal * 50 / 10000; bool private _swapping; uint256 public minimumTokensBeforeSwap = 25000000 * (10**18); address public liquidityWallet; address public marketingWallet; address public buyBackWallet; address public airdropWallet; struct CustomTaxPeriod { bytes23 periodName; uint8 blocksInPeriod; uint256 timeInPeriod; uint8 liquidityFeeOnBuy; uint8 liquidityFeeOnSell; uint8 marketingFeeOnBuy; uint8 marketingFeeOnSell; uint8 buyBackFeeOnBuy; uint8 buyBackFeeOnSell; uint8 airdropFeeOnBuy; uint8 airdropFeeOnSell; uint8 holdersFeeOnBuy; uint8 holdersFeeOnSell; } // Base taxes CustomTaxPeriod private _base = CustomTaxPeriod('base',0,0,1,1,3,3,1,1,1,1,2,2); uint256 private _launchStartTimestamp; uint256 private _launchBlockNumber; uint256 private constant _blockedTimeLimit = 172800; mapping (address => bool) private _isBlocked; mapping (address => bool) private _isExcludedFromFee; mapping (address => bool) private _isExcludedFromMaxTransactionLimit; mapping (address => bool) private _isExcludedFromMaxWalletLimit; mapping (address => bool) private _isAllowedToTradeWhenDisabled; mapping (address => bool) private _isExcludedFromDividends; mapping (address => bool) private _feeOnSelectedWalletTransfers; address[] private _excludedFromDividends; mapping (address => bool) public automatedMarketMakerPairs; uint8 private _liquidityFee; uint8 private _marketingFee; uint8 private _buyBackFee; uint8 private _airdropFee; uint8 private _holdersFee; uint8 private _totalFee; event AutomatedMarketMakerPairChange(address indexed pair, bool indexed value); event AllowedWhenTradingDisabledChange(address indexed account, bool isExcluded); event UniswapV2RouterChange(address indexed newAddress, address indexed oldAddress); event WalletChange(string indexed walletIdentifier, address indexed newWallet, address indexed oldWallet); event FeeChange(string indexed identifier, uint8 liquidityFee, uint8 marketingFee, uint8 buyBackFee, uint8 airdropFee, uint8 holdersFee); event CustomTaxPeriodChange(uint8 indexed newValue, uint8 indexed oldValue, string indexed taxType, bytes23 period); event BlockedAccountChange(address indexed holder, bool indexed status); event MaxTransactionAmountChange(uint256 indexed newValue, uint256 indexed oldValue); event MaxWalletAmountChange(uint256 indexed newValue, uint256 indexed oldValue); event MinTokenAmountBeforeSwapChange(uint256 indexed newValue, uint256 indexed oldValue); event ExcludeFromFeesChange(address indexed account, bool isExcluded); event ExcludeFromMaxTransferChange(address indexed account, bool isExcluded); event ExcludeFromMaxWalletChange(address indexed account, bool isExcluded); event ExcludeFromDividendsChange(address indexed account, bool isExcluded); event SwapAndLiquify(uint256 tokensSwapped, uint256 ethReceived,uint256 tokensIntoLiqudity); event FeeOnSelectedWalletTransfersChange(address indexed account, bool newValue); event ClaimEthOverflow(uint256 amount); event TradingStatusChange(bool indexed newValue, bool indexed oldValue); constructor() { liquidityWallet = owner(); marketingWallet = owner(); buyBackWallet = owner(); airdropWallet = owner(); IRouter _uniswapV2Router = IRouter(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); address _uniswapV2Pair = IFactory(_uniswapV2Router.factory()).createPair( address(this), _uniswapV2Router.WETH() ); uniswapV2Router = _uniswapV2Router; uniswapV2Pair = _uniswapV2Pair; _setAutomatedMarketMakerPair(_uniswapV2Pair, true); _isExcludedFromFee[owner()] = true; _isExcludedFromFee[address(this)] = true; excludeFromDividends(address(0), true); excludeFromDividends(address(_uniswapV2Router), true); excludeFromDividends(address(_uniswapV2Pair), true); _isAllowedToTradeWhenDisabled[owner()] = true; _isExcludedFromMaxTransactionLimit[address(this)] = true; _isExcludedFromMaxTransactionLimit[owner()] = true; _isExcludedFromMaxWalletLimit[_uniswapV2Pair] = true; _isExcludedFromMaxWalletLimit[address(uniswapV2Router)] = true; _isExcludedFromMaxWalletLimit[address(this)] = true; _isExcludedFromMaxWalletLimit[owner()] = true; _rOwned[owner()] = _rTotal; emit Transfer(address(0), owner(), _tTotal); } receive() external payable {} // Setters function transfer(address recipient, uint256 amount) external override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } function approve(address spender, uint256 amount) public override returns (bool) { _approve(_msgSender(), spender, amount); return true; } function transferFrom( address sender,address recipient,uint256 amount) external override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount,"ERC20: transfer amount exceeds allowance")); return true; } function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool){ _approve(_msgSender(),spender,_allowances[_msgSender()][spender].add(addedValue)); return true; } function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool) { _approve(_msgSender(),spender,_allowances[_msgSender()][spender].sub(subtractedValue,"ERC20: decreased allowance below zero")); return true; } function _approve(address owner,address spender,uint256 amount) private { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } function activateTrading() external onlyOwner { isTradingEnabled = true; if (_launchStartTimestamp == 0) { _launchStartTimestamp = block.timestamp; _launchBlockNumber = block.number; } emit TradingStatusChange(true, false); } function deactivateTrading() external onlyOwner { isTradingEnabled = false; emit TradingStatusChange(false, true); } function allowTradingWhenDisabled(address account, bool allowed) external onlyOwner { _isAllowedToTradeWhenDisabled[account] = allowed; emit AllowedWhenTradingDisabledChange(account, allowed); } function setFeeOnSelectedWalletTransfers(address account, bool value) external onlyOwner { require(_feeOnSelectedWalletTransfers[account] != value, "LuckyRoo: The selected wallet is already set to the value "); _feeOnSelectedWalletTransfers[account] = value; emit FeeOnSelectedWalletTransfersChange(account, value); } function _setAutomatedMarketMakerPair(address pair, bool value) private { require(automatedMarketMakerPairs[pair] != value, "LuckyRoo: Automated market maker pair is already set to that value"); automatedMarketMakerPairs[pair] = value; emit AutomatedMarketMakerPairChange(pair, value); } function blockAccount(address account) external onlyOwner { require(!_isBlocked[account], "LuckyRoo: Account is already blocked"); if (_launchStartTimestamp > 0) { require((block.timestamp - _launchStartTimestamp) < _blockedTimeLimit, "LuckyRoo: Time to block accounts has expired"); } _isBlocked[account] = true; emit BlockedAccountChange(account, true); } function unblockAccount(address account) external onlyOwner { require(_isBlocked[account], "LuckyRoo: Account is not blcoked"); _isBlocked[account] = false; emit BlockedAccountChange(account, false); } function excludeFromFees(address account, bool excluded) external onlyOwner { require(_isExcludedFromFee[account] != excluded, "LuckyRoo: Account is already the value of 'excluded'"); _isExcludedFromFee[account] = excluded; emit ExcludeFromFeesChange(account, excluded); } function excludeFromMaxTransactionLimit(address account, bool excluded) external onlyOwner { require(_isExcludedFromMaxTransactionLimit[account] != excluded, "LuckyRoo: Account is already the value of 'excluded'"); _isExcludedFromMaxTransactionLimit[account] = excluded; emit ExcludeFromMaxTransferChange(account, excluded); } function excludeFromMaxWalletLimit(address account, bool excluded) external onlyOwner { require(_isExcludedFromMaxWalletLimit[account] != excluded, "LuckyRoo: Account is already the value of 'excluded'"); _isExcludedFromMaxWalletLimit[account] = excluded; emit ExcludeFromMaxWalletChange(account, excluded); } function excludeFromDividends(address account, bool excluded) public onlyOwner { require(_isExcludedFromDividends[account] != excluded, "LuckyRoo: Account is already the value of 'excluded'"); if(excluded) { if(_rOwned[account] > 0) { _tOwned[account] = tokenFromReflection(_rOwned[account]); } _isExcludedFromDividends[account] = excluded; _excludedFromDividends.push(account); } else { for (uint256 i = 0; i < _excludedFromDividends.length; i++) { if (_excludedFromDividends[i] == account) { _excludedFromDividends[i] = _excludedFromDividends[_excludedFromDividends.length - 1]; _tOwned[account] = 0; _isExcludedFromDividends[account] = false; _excludedFromDividends.pop(); break; } } } emit ExcludeFromDividendsChange(account, excluded); } function setWallets(address newLiquidityWallet, address newMarketingWallet, address newBuyBackWallet, address newAirdropWallet) external onlyOwner { if(liquidityWallet != newLiquidityWallet) { require(newLiquidityWallet != address(0), "LuckyRoo: The liquidityWallet cannot be 0"); emit WalletChange('liquidityWallet', newLiquidityWallet, liquidityWallet); liquidityWallet = newLiquidityWallet; } if(marketingWallet != newMarketingWallet) { require(newMarketingWallet != address(0), "LuckyRoo: The marketingWallet cannot be 0"); emit WalletChange('marketingWallet', newMarketingWallet, marketingWallet); marketingWallet = newMarketingWallet; } if(buyBackWallet != newBuyBackWallet) { require(newBuyBackWallet != address(0), "LuckyRoo: The buyBackWallet cannot be 0"); emit WalletChange('buyBackWallet', newBuyBackWallet, buyBackWallet); buyBackWallet = newBuyBackWallet; } if(airdropWallet != newAirdropWallet) { require(newAirdropWallet != address(0), "LuckyRoo: The airdropWallet cannot be 0"); emit WalletChange('airdropWallet', newAirdropWallet, airdropWallet); airdropWallet = newAirdropWallet; } } function setBaseFeesOnBuy(uint8 _liquidityFeeOnBuy, uint8 _marketingFeeOnBuy, uint8 _buyBackFeeOnBuy, uint8 _airdropFeeOnBuy, uint8 _holdersFeeOnBuy) external onlyOwner { _setCustomBuyTaxPeriod(_base, _liquidityFeeOnBuy, _marketingFeeOnBuy, _buyBackFeeOnBuy, _airdropFeeOnBuy, _holdersFeeOnBuy); emit FeeChange('baseFees-Buy', _liquidityFeeOnBuy, _marketingFeeOnBuy, _buyBackFeeOnBuy, _airdropFeeOnBuy, _holdersFeeOnBuy); } function setBaseFeesOnSell(uint8 _liquidityFeeOnSell,uint8 _marketingFeeOnSell, uint8 _buyBackFeeOnSell, uint8 _airdropFeeOnSell, uint8 _holdersFeeOnSell) external onlyOwner { _setCustomSellTaxPeriod(_base, _liquidityFeeOnSell, _marketingFeeOnSell, _buyBackFeeOnSell, _airdropFeeOnSell, _holdersFeeOnSell); emit FeeChange('baseFees-Sell', _liquidityFeeOnSell, _marketingFeeOnSell, _buyBackFeeOnSell, _airdropFeeOnSell, _holdersFeeOnSell); } function setUniswapRouter(address newAddress) external onlyOwner { require(newAddress != address(uniswapV2Router), "LuckyRoo: The router already has that address"); emit UniswapV2RouterChange(newAddress, address(uniswapV2Router)); uniswapV2Router = IRouter(newAddress); } function setMaxTransactionAmount(uint256 newValue) external onlyOwner { require(newValue != maxTxAmount, "LuckyRoo: Cannot update maxTxAmount to same value"); emit MaxTransactionAmountChange(newValue, maxTxAmount); maxTxAmount = newValue; } function setMaxWalletAmount(uint256 newValue) external onlyOwner { require(newValue != maxWalletAmount, "LuckyRoo: Cannot update maxWalletAmount to same value"); emit MaxWalletAmountChange(newValue, maxWalletAmount); maxWalletAmount = newValue; } function setMinimumTokensBeforeSwap(uint256 newValue) external onlyOwner { require(newValue != minimumTokensBeforeSwap, "LuckyRoo: Cannot update minimumTokensBeforeSwap to same value"); emit MinTokenAmountBeforeSwapChange(newValue, minimumTokensBeforeSwap); minimumTokensBeforeSwap = newValue; } function claimEthOverflow(uint256 amount) external onlyOwner { require(amount < address(this).balance, "LuckyRoo: Cannot send more than contract balance"); (bool success,) = address(owner()).call{value : amount}(""); if (success){ emit ClaimEthOverflow(amount); } } // Getters function name() external pure returns (string memory) { return _name; } function symbol() external pure returns (string memory) { return _symbol; } function decimals() external view virtual returns (uint8) { return _decimals; } function totalSupply() external pure override returns (uint256) { return _tTotal; } function balanceOf(address account) public view override returns (uint256) { if (_isExcludedFromDividends[account]) return _tOwned[account]; return tokenFromReflection(_rOwned[account]); } function totalFees() external view returns (uint256) { return _tFeeTotal; } function allowance(address owner, address spender) external view override returns (uint256) { return _allowances[owner][spender]; } function getBaseBuyFees() external view returns (uint8, uint8, uint8, uint8, uint8){ return (_base.liquidityFeeOnBuy, _base.marketingFeeOnBuy, _base.buyBackFeeOnBuy, _base.airdropFeeOnBuy, _base.holdersFeeOnBuy); } function getBaseSellFees() external view returns (uint8, uint8, uint8, uint8, uint8){ return (_base.liquidityFeeOnSell, _base.marketingFeeOnSell, _base.buyBackFeeOnSell, _base.airdropFeeOnSell, _base.holdersFeeOnSell); } function tokenFromReflection(uint256 rAmount) public view returns(uint256) { require(rAmount <= _rTotal, "LuckyRoo: Amount must be less than total reflections"); uint256 currentRate = _getRate(); return rAmount / currentRate; } function reflectionFromToken(uint256 tAmount, bool deductTransferFee) external view returns (uint256) { require(tAmount <= _tTotal, "LuckyRoo: Amount must be less than supply"); uint256 currentRate = _getRate(); uint256 rAmount = tAmount * currentRate; if (!deductTransferFee) { return rAmount; } else { uint256 rTotalFee = tAmount * _totalFee / 100 * currentRate; uint256 rTransferAmount = rAmount - rTotalFee; return rTransferAmount; } } // Main function _transfer( address from, address to, uint256 amount ) internal { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); require(amount > 0, "LuckyRoo: Transfer amount must be greater than zero"); require(amount <= balanceOf(from), "LuckyRoo: Cannot transfer more than balance"); if(!_isAllowedToTradeWhenDisabled[from] && !_isAllowedToTradeWhenDisabled[to]) { require(isTradingEnabled, "LuckyRoo: Trading is currently disabled."); require(!_isBlocked[to], "LuckyRoo: Account is blocked"); require(!_isBlocked[from], "LuckyRoo: Account is blocked"); if (!_isExcludedFromMaxTransactionLimit[to] && !_isExcludedFromMaxTransactionLimit[from]) { require(amount <= maxTxAmount, "LuckyRoo: Buy amount exceeds the maxTxBuyAmount."); } if (!_isExcludedFromMaxWalletLimit[to]) { require((balanceOf(to) + amount) <= maxWalletAmount, "LuckyRoo: Expected wallet amount exceeds the maxWalletAmount."); } } _adjustTaxes(automatedMarketMakerPairs[from], automatedMarketMakerPairs[to], to, from); bool canSwap = balanceOf(address(this)) >= minimumTokensBeforeSwap; if ( isTradingEnabled && canSwap && !_swapping && _totalFee > 0 && automatedMarketMakerPairs[to] ) { _swapping = true; _swapAndLiquify(); _swapping = false; } bool takeFee = !_swapping && isTradingEnabled; if(_isExcludedFromFee[from] || _isExcludedFromFee[to]){ takeFee = false; } _tokenTransfer(from, to, amount, takeFee); } function _tokenTransfer(address sender,address recipient, uint256 tAmount, bool takeFee) private { (uint256 tTransferAmount,uint256 tFee, uint256 tOther) = _getTValues(tAmount, takeFee); (uint256 rAmount, uint256 rTransferAmount, uint256 rFee, uint256 rOther) = _getRValues(tAmount, tFee, tOther, _getRate()); if (_isExcludedFromDividends[sender]) { _tOwned[sender] = _tOwned[sender] - tAmount; } if (_isExcludedFromDividends[recipient]) { _tOwned[recipient] = _tOwned[recipient] + tTransferAmount; } _rOwned[sender] = _rOwned[sender] - rAmount; _rOwned[recipient] = _rOwned[recipient] + rTransferAmount; _reflectFee(rFee, tFee, rOther, tOther); emit Transfer(sender, recipient, tTransferAmount); } function _reflectFee(uint256 rFee, uint256 tFee, uint256 rOther, uint256 tOther) private { _rTotal -= rFee; _tFeeTotal += tFee; if (_isExcludedFromDividends[address(this)]) { _tOwned[address(this)] += tOther; } _rOwned[address(this)] += rOther; } function _getTValues(uint256 tAmount, bool takeFee) private view returns (uint256,uint256,uint256){ if (!takeFee) { return (tAmount, 0, 0); } else { uint256 tFee = tAmount * _holdersFee / 100; uint256 tOther = tAmount * (_liquidityFee + _marketingFee + _airdropFee + _buyBackFee) / 100; uint256 tTransferAmount = tAmount - (tFee + tOther); return (tTransferAmount, tFee, tOther); } } function _getRValues( uint256 tAmount, uint256 tFee, uint256 tOther, uint256 currentRate ) private pure returns ( uint256, uint256, uint256, uint256) { uint256 rAmount = tAmount * currentRate; uint256 rFee = tFee * currentRate; uint256 rOther = tOther * currentRate; uint256 rTransferAmount = rAmount - (rFee + rOther); return (rAmount, rTransferAmount, rFee, rOther); } function _getRate() private view returns (uint256) { (uint256 rSupply, uint256 tSupply) = _getCurrentSupply(); return rSupply.div(tSupply); } function _getCurrentSupply() private view returns (uint256, uint256) { uint256 rSupply = _rTotal; uint256 tSupply = _tTotal; for (uint256 i = 0; i < _excludedFromDividends.length; i++) { if ( _rOwned[_excludedFromDividends[i]] > rSupply || _tOwned[_excludedFromDividends[i]] > tSupply ) return (_rTotal, _tTotal); rSupply = rSupply - _rOwned[_excludedFromDividends[i]]; tSupply = tSupply - _tOwned[_excludedFromDividends[i]]; } if (rSupply < _rTotal / _tTotal) return (_rTotal, _tTotal); return (rSupply, tSupply); } function _adjustTaxes(bool isBuyFromLp, bool isSelltoLp, address to, address from) private { _liquidityFee = 0; _marketingFee = 0; _airdropFee = 0; _buyBackFee = 0; _holdersFee = 0; if (isBuyFromLp) { if (block.number - _launchBlockNumber <= 5) { _liquidityFee = 100; } else { _liquidityFee = _base.liquidityFeeOnBuy; _marketingFee = _base.marketingFeeOnBuy; _buyBackFee = _base.buyBackFeeOnBuy; _airdropFee = _base.airdropFeeOnBuy; _holdersFee = _base.holdersFeeOnBuy; } } if (isSelltoLp) { _liquidityFee = _base.liquidityFeeOnSell; _marketingFee = _base.marketingFeeOnSell; _buyBackFee = _base.buyBackFeeOnSell; _airdropFee = _base.airdropFeeOnSell; _holdersFee = _base.holdersFeeOnSell; } if (!isSelltoLp && !isBuyFromLp && (_feeOnSelectedWalletTransfers[from] || _feeOnSelectedWalletTransfers[to])) { _liquidityFee = _base.liquidityFeeOnSell; _marketingFee = _base.marketingFeeOnSell; _buyBackFee = _base.buyBackFeeOnSell; _airdropFee = _base.airdropFeeOnSell; _holdersFee = _base.holdersFeeOnSell; } _totalFee = _liquidityFee + _marketingFee + _buyBackFee + _airdropFee + _holdersFee; } function _setCustomSellTaxPeriod(CustomTaxPeriod storage map, uint8 _liquidityFeeOnSell, uint8 _marketingFeeOnSell, uint8 _buyBackFeeOnSell, uint8 _airdropFeeOnSell, uint8 _holdersFeeOnSell ) private { if (map.liquidityFeeOnSell != _liquidityFeeOnSell) { emit CustomTaxPeriodChange(_liquidityFeeOnSell, map.liquidityFeeOnSell, 'liquidityFeeOnSell', map.periodName); map.liquidityFeeOnSell = _liquidityFeeOnSell; } if (map.marketingFeeOnSell != _marketingFeeOnSell) { emit CustomTaxPeriodChange(_marketingFeeOnSell, map.marketingFeeOnSell, 'marketingFeeOnSell', map.periodName); map.marketingFeeOnSell = _marketingFeeOnSell; } if (map.buyBackFeeOnSell != _buyBackFeeOnSell) { emit CustomTaxPeriodChange(_buyBackFeeOnSell, map.buyBackFeeOnSell, 'buyBackFeeOnSell', map.periodName); map.buyBackFeeOnSell = _buyBackFeeOnSell; } if (map.airdropFeeOnSell != _airdropFeeOnSell) { emit CustomTaxPeriodChange(_airdropFeeOnSell, map.airdropFeeOnSell, 'airdropFeeOnSell', map.periodName); map.airdropFeeOnSell = _airdropFeeOnSell; } if (map.holdersFeeOnSell != _holdersFeeOnSell) { emit CustomTaxPeriodChange(_holdersFeeOnSell, map.holdersFeeOnSell, 'holdersFeeOnSell', map.periodName); map.holdersFeeOnSell = _holdersFeeOnSell; } } function _setCustomBuyTaxPeriod(CustomTaxPeriod storage map, uint8 _liquidityFeeOnBuy, uint8 _marketingFeeOnBuy, uint8 _buyBackFeeOnBuy, uint8 _airdropFeeOnBuy, uint8 _holdersFeeOnBuy ) private { if (map.liquidityFeeOnBuy != _liquidityFeeOnBuy) { emit CustomTaxPeriodChange(_liquidityFeeOnBuy, map.liquidityFeeOnBuy, 'liquidityFeeOnBuy', map.periodName); map.liquidityFeeOnBuy = _liquidityFeeOnBuy; } if (map.marketingFeeOnBuy != _marketingFeeOnBuy) { emit CustomTaxPeriodChange(_marketingFeeOnBuy, map.marketingFeeOnBuy, 'marketingFeeOnBuy', map.periodName); map.marketingFeeOnBuy = _marketingFeeOnBuy; } if (map.buyBackFeeOnBuy != _buyBackFeeOnBuy) { emit CustomTaxPeriodChange(_buyBackFeeOnBuy, map.buyBackFeeOnBuy, 'buyBackFeeOnBuy', map.periodName); map.buyBackFeeOnBuy = _buyBackFeeOnBuy; } if (map.airdropFeeOnBuy != _airdropFeeOnBuy) { emit CustomTaxPeriodChange(_airdropFeeOnBuy, map.airdropFeeOnBuy, 'airdropFeeOnBuy', map.periodName); map.airdropFeeOnBuy = _airdropFeeOnBuy; } if (map.holdersFeeOnBuy != _holdersFeeOnBuy) { emit CustomTaxPeriodChange(_holdersFeeOnBuy, map.holdersFeeOnBuy, 'holdersFeeOnBuy', map.periodName); map.holdersFeeOnBuy = _holdersFeeOnBuy; } } function _swapAndLiquify() private { uint256 contractBalance = balanceOf(address(this)); uint256 initialEthBalance = address(this).balance; uint8 totalFeePrior = _totalFee; uint8 liquidityFeePrior = _liquidityFee; uint8 marketingFeePrior = _marketingFee; uint8 buyBackFeePrior = _buyBackFee; uint8 airdropFeePrior = _airdropFee; uint8 holdersFeePrior = _holdersFee; uint256 amountToLiquify = contractBalance * _liquidityFee / _totalFee / 2; uint256 amountToSwap = contractBalance - amountToLiquify; _swapTokensForEth(amountToSwap); uint256 ethBalanceAfterSwap = address(this).balance - initialEthBalance; uint256 totalEthFee = totalFeePrior - (liquidityFeePrior / 2) - (holdersFeePrior); uint256 amountEthLiquidity = ethBalanceAfterSwap * liquidityFeePrior / totalEthFee / 2; uint256 amountEthMarketing = ethBalanceAfterSwap * marketingFeePrior / totalEthFee; uint256 amountEthBuyBack = ethBalanceAfterSwap * buyBackFeePrior / totalEthFee; uint256 amountEthAirdrop = ethBalanceAfterSwap - (amountEthLiquidity + amountEthMarketing + amountEthBuyBack); Address.sendValue(payable(marketingWallet),amountEthMarketing); Address.sendValue(payable(buyBackWallet),amountEthBuyBack); Address.sendValue(payable(airdropWallet),amountEthAirdrop); if (amountToLiquify > 0) { _addLiquidity(amountToLiquify, amountEthLiquidity); emit SwapAndLiquify(amountToSwap, amountEthLiquidity, amountToLiquify); } _totalFee = totalFeePrior; _liquidityFee = liquidityFeePrior; _marketingFee = marketingFeePrior; _buyBackFee = buyBackFeePrior; _airdropFee = airdropFeePrior; _holdersFee = holdersFeePrior; } function _swapTokensForEth(uint256 tokenAmount) private { address[] memory path = new address[](2); path[0] = address(this); path[1] = uniswapV2Router.WETH(); _approve(address(this), address(uniswapV2Router), tokenAmount); uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens( tokenAmount, 1, // accept any amount of ETH path, address(this), block.timestamp ); } function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private { _approve(address(this), address(uniswapV2Router), tokenAmount); uniswapV2Router.addLiquidityETH{value: ethAmount}( address(this), tokenAmount, 1, // slippage is unavoidable 1, // slippage is unavoidable liquidityWallet, block.timestamp ); } }