Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
5.2 kB
5
Indexable
Never
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract SafeMoneyUp is ERC20, Ownable {
    uint256 private constant PRECISION = 1e18;
    uint256 private constant FIXED_SUPPLY = 400 * 1e12 * PRECISION;

    mapping(address => bool) public excludedFromFees;
    mapping(address => bool) public isBlacklisted;

    uint256 public adminFee = 50; // 0.5% (50/10000)

    constructor() ERC20("SafeMoney Up", "SMU") {
        _mint(address(this), FIXED_SUPPLY);
        excludedFromFees[owner()] = true;
    }

    ///@notice user can buy tokens by calling this function.
    ///@notice user shouldn't be blacklisted and smartcontract should have enough tokens to process his buy
    
    function buyTokens() public payable {
        require(!isBlacklisted[msg.sender], "Address is blacklisted");
        require(msg.value > 0, "Amount must be greater than 0");
        uint256 supplyWithoutContractAndBurn = totalSupply() - balanceOf(address(this)) - balanceOf(address(0));
        uint256 ethAmountInPool = address(this).balance;
        uint256 perTokenPrice = supplyWithoutContractAndBurn / ethAmountInPool;
        uint256 tokensToBuy = msg.value/perTokenPrice;
        require (balanceOf(address(this)) >= tokensToBuy, "not enough tokens in the pool");
        uint256 fee = (msg.value * adminFee) / 10000;
        uint256 tokensWithFee = (tokensToBuy * 98) / 100; // 2% fee

        if (!excludedFromFees[msg.sender]) {
            tokensToBuy = tokensWithFee;
            require (balanceOf(address(this)) >= tokensToBuy, "not enough tokens in the pool");
            (bool sent,) = owner().call{value: fee}("");
            require(sent, "eth fees to admin failed");
        }

        _transfer(address(this), msg.sender, tokensToBuy);
    }

    /// @param tokensToSell - number of tokens users want to sell.
    /// @notice user can call this function to sell his/her tokens.
    function sellTokens(uint256 tokensToSell) public {
        require(!isBlacklisted[msg.sender], "Address is blacklisted");
        require(tokensToSell > 0, "Amount must be greater than 0");
        uint256 supplyWithoutContractAndBurn = totalSupply() - balanceOf(address(this)) - balanceOf(address(0));
        uint256 ethAmountInPool = address(this).balance;
        uint256 perTokenPrice = supplyWithoutContractAndBurn / ethAmountInPool;
        uint256 ethAmount = tokensToSell * perTokenPrice;
        require (address(this).balance >= ethAmount, "not enough eth in the pool");
        uint256 fee = (tokensToSell * adminFee) / 10000;
        uint256 ethWithFee = (ethAmount * 98) / 100; // 2% fee
        _transfer(msg.sender, address(this), tokensToSell);
         
        if (!excludedFromFees[msg.sender]) {
            ethAmount = ethWithFee;
            require (address(this).balance >= ethAmount, "not enough eth in the pool");
            _transfer (address(this), owner(), fee); //deduct fee in tokens
        } 
        payable(msg.sender).transfer(ethAmount);
    }
     
    ///@param newAdminFee amount of fees in basis point
    ///@dev set admin fees, limited to 10 percent. 
    function setAdminFee(uint256 newAdminFee) public onlyOwner {
        require(newAdminFee >= 0 && newAdminFee <= 1000, "Invalid fee value"); //max admin fee is 10 percent
        adminFee = newAdminFee;
    }
    
    ///@param account - user address
    ///@param excluded - boolean value
    ///@dev excluded or include someone from/in fees 
    function excludeFromFees(address account, bool excluded) public onlyOwner {
        excludedFromFees[account] = excluded;
    }
    
    ///@param account - user address
    ///@param blacklisted - boolean value
    ///@dev manage blacklist of users using this function.
    function setBlacklistStatus(address account, bool blacklisted) public onlyOwner {
        isBlacklisted[account] = blacklisted;
    }

    
    /// @dev owner can add initial liquidity using this function (eth)
    function injectInitialETHLiquidity () public onlyOwner payable {
        require (msg.value > 0, "eth amount should be greator than 0");
    }
    
    /// @param - tokenAddress - address of ERC20 token
    /// @param - amount - amount to withdraw from smart contract
    /// @dev - owner can withdraw any ERC20 token using this function 
    function withdrawToken(address tokenAddress, uint256 amount) public onlyOwner {
        require(tokenAddress != address(0), "not a valid token");
        IERC20 token = IERC20(tokenAddress);
        uint256 tokenBalance = token.balanceOf(address(this));
        require(amount <= tokenBalance, "Not enough tokens in contract");
        token.transfer(owner(), amount);
    }
   /// @dev withdraw eth from contract
    withdrawETH (uint256 amount) external onlyOwner {
        (bool sent,) = owner().call{value: amount}("");
        require (sent, "eth transfer failed");
    }

    /// @notice receive any external ether sent by user (except owner of this smartcontract)
    receive() external payable {
        require(msg.sender != owner(), "Owner cannot send Ether directly");
    }

    
}