// File: contracts/utils/ERC20.sol



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

contract ERC20 {

    uint internal _totalSupply;
    mapping(address => uint) internal _balanceOf;
    mapping(address => mapping(address => uint)) internal _allowance;

    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function _mint(address to, uint value) internal {
        _totalSupply += value;
        _balanceOf[to] += value;
        emit Transfer(address(0), to, value);
    }

    function _burn(address from, uint value) internal {
        _balanceOf[from] -= value;
        _totalSupply -= value;
        emit Transfer(from, address(0), value);
    }

    function _approve(
        address owner,
        address spender,
        uint value
    ) internal virtual {
        _allowance[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    function _transfer(
        address from,
        address to,
        uint value
    ) internal virtual {
        _balanceOf[from] -= value;
        _balanceOf[to] += value;
        emit Transfer(from, to, value);
    }

    function allowance(address owner, address spender) external view virtual returns (uint) {
        return _allowance[owner][spender];
    }

    function _spendAllowance(address owner, address spender, uint value) internal virtual {
        if (_allowance[owner][spender] != type(uint256).max) {
            require(_allowance[owner][spender] >= value, "ERC20: insufficient allowance");
            _allowance[owner][spender] -= value;
        }
    }

    function totalSupply() external view virtual returns (uint) {
        return _totalSupply;
    }

    function balanceOf(address owner) external view virtual returns (uint) {
        return _balanceOf[owner];
    }

    function approve(address spender, uint value) external virtual returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint value) external virtual returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }
    
    function transferFrom(
        address from,
        address to,
        uint value
    ) external virtual returns (bool) {
        _spendAllowance(from, msg.sender, value);
        _transfer(from, to, value);
        return true;
    }
}

// File: contracts/work/SWC.sol



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

import {ERC20} from "../utils/ERC20.sol";

interface IUNI {
    function createPair(address, address) external returns (address);
}

contract SWC is ERC20 {

    /// @notice Uniswap V2 (UNI-V2) SWC - WETH pair address
    address public immutable swcPair;
    /// @notice After purchase, selling is not allowed in the current block to prevent arbitrage bot attacks.
    mapping(address => uint256) public freezedBlock;

    address public owner;

    mapping(address => bool) public blackList;
    event BlackList(address indexed account, bool value);

    modifier onlyOwner {
        require(msg.sender == owner, "only owner");
        _;
    }

    function name() public pure returns (string memory) {
        return "Stand With Crypto";
    }

    function symbol() public pure returns (string memory) {
        return "SWC";
    }

    function decimals() public pure returns (uint8) {
        return 18;
    }

    function setBlackList(address[] calldata _accounts, bool[] calldata _values) external onlyOwner {
        for(uint i = 0; i < _accounts.length; i++) {
            blackList[_accounts[i]] = _values[i];
            emit BlackList(_accounts[i], _values[i]);
        }
    }

    function setOwner(address _owner) external onlyOwner {
        owner = _owner;
    }

    constructor(
        address _factory,
        address _weth
    ) {
        _mint(msg.sender, 120_000_000_000_000 ether);
        swcPair = IUNI(_factory).createPair(address(this), _weth);
        owner = msg.sender;
    }

    function _transfer(
        address from,
        address to,
        uint value
    ) internal override {
        require(!blackList[from], "locked");
        require(block.number >= freezedBlock[from], "not allowed current block");
        // @dev buy and remove liquidity
        if (from == swcPair) {
            // @dev After purchase, the account will be temporarily locked for 4 blocks.
            freezedBlock[to] = block.number + 4;
        }
        _balanceOf[from] -= value;
        _balanceOf[to] += value;
        emit Transfer(from, to, value);
    }

    function burn(uint256 amount) external {
        _burn(msg.sender, amount);
    }
}