// File: Doha Fifa Coin.sol







pragma solidity =0.8.10 >=0.8.10 >=0.8.0 <0.9.0;



pragma experimental ABIEncoderV2;







////// lib/openzeppelin-contracts/contracts/utils/Context.sol



// OpenZeppelin Contracts v4.4.0 (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;



    }



}







////// lib/openzeppelin-contracts/contracts/access/Ownable.sol



// OpenZeppelin Contracts v4.4.0 (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);



    }



}







////// lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol



// OpenZeppelin Contracts v4.4.0 (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);



}







////// lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol



// OpenZeppelin Contracts v4.4.0 (token/ERC20/extensions/IERC20Metadata.sol)







/* pragma solidity ^0.8.0; */







/* import "../IERC20.sol"; */







/**



 * @dev Interface for the optional metadata functions from the ERC20 standard.



 *



 * _Available since v4.1._



 */



interface IERC20Metadata is IERC20 {



    /**



     * @dev Returns the name of the token.



     */



    function name() external view returns (string memory);







    /**



     * @dev Returns the symbol of the token.



     */



    function symbol() external view returns (string memory);







    /**



     * @dev Returns the decimals places of the token.



     */



    function decimals() external view returns (uint8);



}







////// lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol



// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol)







/* pragma solidity ^0.8.0; */







/* import "./IERC20.sol"; */



/* import "./extensions/IERC20Metadata.sol"; */



/* import "../../utils/Context.sol"; */







/**



 * @dev Implementation of the {IERC20} interface.



 *



 * This implementation is agnostic to the way tokens are created. This means



 * that a supply mechanism has to be added in a derived contract using {_mint}.



 * For a generic mechanism see {ERC20PresetMinterPauser}.



 *



 * TIP: For a detailed writeup see our guide



 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How



 * to implement supply mechanisms].



 *



 * We have followed general OpenZeppelin Contracts guidelines: functions revert



 * instead returning `false` on failure. This behavior is nonetheless



 * conventional and does not conflict with the expectations of ERC20



 * applications.



 *



 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.



 * This allows applications to reconstruct the allowance for all accounts just



 * by listening to said events. Other implementations of the EIP may not emit



 * these events, as it isn't required by the specification.



 *



 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}



 * functions have been added to mitigate the well-known issues around setting



 * allowances. See {IERC20-approve}.



 */



contract ERC20 is Context, IERC20, IERC20Metadata {



    mapping(address => uint256) private _balances;







    mapping(address => mapping(address => uint256)) private _allowances;







    uint256 private _totalSupply;







    string private _name;



    string private _symbol;







    /**



     * @dev Sets the values for {name} and {symbol}.



     *



     * The default value of {decimals} is 18. To select a different value for



     * {decimals} you should overload it.



     *



     * All two of these values are immutable: they can only be set once during



     * construction.



     */



    constructor(string memory name_, string memory symbol_) {



        _name = name_;



        _symbol = symbol_;



    }







    /**



     * @dev Returns the name of the token.



     */



    function name() public view virtual override returns (string memory) {



        return _name;



    }







    /**



     * @dev Returns the symbol of the token, usually a shorter version of the



     * name.



     */



    function symbol() public view virtual override returns (string memory) {



        return _symbol;



    }







    /**



     * @dev Returns the number of decimals used to get its user representation.



     * For example, if `decimals` equals `2`, a balance of `505` tokens should



     * be displayed to a user as `5.05` (`505 / 10 ** 2`).



     *



     * Tokens usually opt for a value of 18, imitating the relationship between



     * Ether and Wei. This is the value {ERC20} uses, unless this function is



     * overridden;



     *



     * NOTE: This information is only used for _display_ purposes: it in



     * no way affects any of the arithmetic of the contract, including



     * {IERC20-balanceOf} and {IERC20-transfer}.



     */



    function decimals() public view virtual override returns (uint8) {



        return 18;



    }







    /**



     * @dev See {IERC20-totalSupply}.



     */



    function totalSupply() public view virtual override returns (uint256) {



        return _totalSupply;



    }







    /**



     * @dev See {IERC20-balanceOf}.



     */



    function balanceOf(address account) public view virtual override returns (uint256) {



        return _balances[account];



    }







    /**



     * @dev See {IERC20-transfer}.



     *



     * Requirements:



     *



     * - `recipient` cannot be the zero address.



     * - the caller must have a balance of at least `amount`.



     */



    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {



        _transfer(_msgSender(), recipient, amount);



        return true;



    }







    /**



     * @dev See {IERC20-allowance}.



     */



    function allowance(address owner, address spender) public view virtual override returns (uint256) {



        return _allowances[owner][spender];



    }







    /**



     * @dev See {IERC20-approve}.



     *



     * Requirements:



     *



     * - `spender` cannot be the zero address.



     */



    function approve(address spender, uint256 amount) public virtual override returns (bool) {



        _approve(_msgSender(), spender, amount);



        return true;



    }







    /**



     * @dev See {IERC20-transferFrom}.



     *



     * Emits an {Approval} event indicating the updated allowance. This is not



     * required by the EIP. See the note at the beginning of {ERC20}.



     *



     * Requirements:



     *



     * - `sender` and `recipient` cannot be the zero address.



     * - `sender` must have a balance of at least `amount`.



     * - the caller must have allowance for ``sender``'s tokens of at least



     * `amount`.



     */



    function transferFrom(



        address sender,



        address recipient,



        uint256 amount



    ) public virtual override returns (bool) {



        _transfer(sender, recipient, amount);







        uint256 currentAllowance = _allowances[sender][_msgSender()];



        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");



        unchecked {



            _approve(sender, _msgSender(), currentAllowance - amount);



        }







        return true;



    }







    /**



     * @dev Atomically increases the allowance granted to `spender` by the caller.



     *



     * This is an alternative to {approve} that can be used as a mitigation for



     * problems described in {IERC20-approve}.



     *



     * Emits an {Approval} event indicating the updated allowance.



     *



     * Requirements:



     *



     * - `spender` cannot be the zero address.



     */



    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {



        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);



        return true;



    }







    /**



     * @dev Atomically decreases the allowance granted to `spender` by the caller.



     *



     * This is an alternative to {approve} that can be used as a mitigation for



     * problems described in {IERC20-approve}.



     *



     * Emits an {Approval} event indicating the updated allowance.



     *



     * Requirements:



     *



     * - `spender` cannot be the zero address.



     * - `spender` must have allowance for the caller of at least



     * `subtractedValue`.



     */



    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {



        uint256 currentAllowance = _allowances[_msgSender()][spender];



        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");



        unchecked {



            _approve(_msgSender(), spender, currentAllowance - subtractedValue);



        }







        return true;



    }







    /**



     * @dev Moves `amount` of tokens from `sender` to `recipient`.



     *



     * This internal function is equivalent to {transfer}, and can be used to



     * e.g. implement automatic token fees, slashing mechanisms, etc.



     *



     * Emits a {Transfer} event.



     *



     * Requirements:



     *



     * - `sender` cannot be the zero address.



     * - `recipient` cannot be the zero address.



     * - `sender` must have a balance of at least `amount`.



     */



    function _transfer(



        address sender,



        address recipient,



        uint256 amount



    ) internal virtual {



        require(sender != address(0), "ERC20: transfer from the zero address");



        require(recipient != address(0), "ERC20: transfer to the zero address");







        _beforeTokenTransfer(sender, recipient, amount);







        uint256 senderBalance = _balances[sender];



        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");



        unchecked {



            _balances[sender] = senderBalance - amount;



        }



        _balances[recipient] += amount;







        emit Transfer(sender, recipient, amount);







        _afterTokenTransfer(sender, recipient, amount);



    }







    /** @dev Creates `amount` tokens and assigns them to `account`, increasing



     * the total supply.



     *



     * Emits a {Transfer} event with `from` set to the zero address.



     *



     * Requirements:



     *



     * - `account` cannot be the zero address.



     */



    function _mint(address account, uint256 amount) internal virtual {



        require(account != address(0), "ERC20: mint to the zero address");







        _beforeTokenTransfer(address(0), account, amount);







        _totalSupply += amount;



        _balances[account] += amount;



        emit Transfer(address(0), account, amount);







        _afterTokenTransfer(address(0), account, amount);



    }







    /**



     * @dev Destroys `amount` tokens from `account`, reducing the



     * total supply.



     *



     * Emits a {Transfer} event with `to` set to the zero address.



     *



     * Requirements:



     *



     * - `account` cannot be the zero address.



     * - `account` must have at least `amount` tokens.



     */



    function _burn(address account, uint256 amount) internal virtual {



        require(account != address(0), "ERC20: burn from the zero address");







        _beforeTokenTransfer(account, address(0), amount);







        uint256 accountBalance = _balances[account];



        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");



        unchecked {



            _balances[account] = accountBalance - amount;



        }



        _totalSupply -= amount;







        emit Transfer(account, address(0), amount);







        _afterTokenTransfer(account, address(0), amount);



    }







    /**



     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.



     *



     * This internal function is equivalent to `approve`, and can be used to



     * e.g. set automatic allowances for certain subsystems, etc.



     *



     * Emits an {Approval} event.



     *



     * Requirements:



     *



     * - `owner` cannot be the zero address.



     * - `spender` cannot be the zero address.



     */



    function _approve(



        address owner,



        address spender,



        uint256 amount



    ) internal virtual {



        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);



    }







    /**



     * @dev Hook that is called before any transfer of tokens. This includes



     * minting and burning.



     *



     * Calling conditions:



     *



     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens



     * will be transferred to `to`.



     * - when `from` is zero, `amount` tokens will be minted for `to`.



     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.



     * - `from` and `to` are never both zero.



     *



     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].



     */



    function _beforeTokenTransfer(



        address from,



        address to,



        uint256 amount



    ) internal virtual {}







    /**



     * @dev Hook that is called after any transfer of tokens. This includes



     * minting and burning.



     *



     * Calling conditions:



     *



     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens



     * has been transferred to `to`.



     * - when `from` is zero, `amount` tokens have been minted for `to`.



     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.



     * - `from` and `to` are never both zero.



     *



     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].



     */



    function _afterTokenTransfer(



        address from,



        address to,



        uint256 amount



    ) internal virtual {}



}







////// lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol



// OpenZeppelin Contracts v4.4.0 (utils/math/SafeMath.sol)







/* pragma solidity ^0.8.0; */







// CAUTION



// This version of SafeMath should only be used with Solidity 0.8 or later,



// because it relies on the compiler's built in overflow checks.







/**



 * @dev Wrappers over Solidity's arithmetic operations.



 *



 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler



 * now has built in overflow checking.



 */



library SafeMath {



    /**



     * @dev Returns the addition of two unsigned integers, with an overflow flag.



     *



     * _Available since v3.4._



     */



    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {



        unchecked {



            uint256 c = a + b;



            if (c < a) return (false, 0);



            return (true, c);



        }



    }







    /**



     * @dev Returns the substraction of two unsigned integers, with an overflow flag.



     *



     * _Available since v3.4._



     */



    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {



        unchecked {



            if (b > a) return (false, 0);



            return (true, a - b);



        }



    }







    /**



     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.



     *



     * _Available since v3.4._



     */



    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {



        unchecked {



            // 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 (true, 0);



            uint256 c = a * b;



            if (c / a != b) return (false, 0);



            return (true, c);



        }



    }







    /**



     * @dev Returns the division of two unsigned integers, with a division by zero flag.



     *



     * _Available since v3.4._



     */



    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {



        unchecked {



            if (b == 0) return (false, 0);



            return (true, a / b);



        }



    }







    /**



     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.



     *



     * _Available since v3.4._



     */



    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {



        unchecked {



            if (b == 0) return (false, 0);



            return (true, a % b);



        }



    }







    /**



     * @dev Returns the addition of two unsigned integers, reverting on



     * overflow.



     *



     * Counterpart to Solidity's `+` operator.



     *



     * Requirements:



     *



     * - Addition cannot overflow.



     */



    function add(uint256 a, uint256 b) internal pure returns (uint256) {



        return a + b;



    }







    /**



     * @dev Returns the subtraction of two unsigned integers, reverting on



     * overflow (when the result is negative).



     *



     * Counterpart to Solidity's `-` operator.



     *



     * Requirements:



     *



     * - Subtraction cannot overflow.



     */



    function sub(uint256 a, uint256 b) internal pure returns (uint256) {



        return a - b;



    }







    /**



     * @dev Returns the multiplication of two unsigned integers, reverting on



     * overflow.



     *



     * Counterpart to Solidity's `*` operator.



     *



     * Requirements:



     *



     * - Multiplication cannot overflow.



     */



    function mul(uint256 a, uint256 b) internal pure returns (uint256) {



        return a * b;



    }







    /**



     * @dev Returns the integer division of two unsigned integers, reverting on



     * division by zero. The result is rounded towards zero.



     *



     * Counterpart to Solidity's `/` operator.



     *



     * Requirements:



     *



     * - The divisor cannot be zero.



     */



    function div(uint256 a, uint256 b) internal pure returns (uint256) {



        return a / b;



    }







    /**



     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),



     * reverting when dividing by zero.



     *



     * Counterpart to Solidity's `%` operator. This function uses a `revert`



     * opcode (which leaves remaining gas untouched) while Solidity uses an



     * invalid opcode to revert (consuming all remaining gas).



     *



     * Requirements:



     *



     * - The divisor cannot be zero.



     */



    function mod(uint256 a, uint256 b) internal pure returns (uint256) {



        return a % b;



    }







    /**



     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on



     * overflow (when the result is negative).



     *



     * CAUTION: This function is deprecated because it requires allocating memory for the error



     * message unnecessarily. For custom revert reasons use {trySub}.



     *



     * Counterpart to Solidity's `-` operator.



     *



     * Requirements:



     *



     * - Subtraction cannot overflow.



     */



    function sub(



        uint256 a,



        uint256 b,



        string memory errorMessage



    ) internal pure returns (uint256) {



        unchecked {



            require(b <= a, errorMessage);



            return a - b;



        }



    }







    /**



     * @dev Returns the integer division of two unsigned integers, reverting with custom message on



     * division by zero. The result is rounded towards zero.



     *



     * Counterpart to Solidity's `/` operator. Note: this function uses a



     * `revert` opcode (which leaves remaining gas untouched) while Solidity



     * uses an invalid opcode to revert (consuming all remaining gas).



     *



     * Requirements:



     *



     * - The divisor cannot be zero.



     */



    function div(



        uint256 a,



        uint256 b,



        string memory errorMessage



    ) internal pure returns (uint256) {



        unchecked {



            require(b > 0, errorMessage);



            return a / b;



        }



    }







    /**



     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),



     * reverting with custom message when dividing by zero.



     *



     * CAUTION: This function is deprecated because it requires allocating memory for the error



     * message unnecessarily. For custom revert reasons use {tryMod}.



     *



     * Counterpart to Solidity's `%` operator. This function uses a `revert`



     * opcode (which leaves remaining gas untouched) while Solidity uses an



     * invalid opcode to revert (consuming all remaining gas).



     *



     * Requirements:



     *



     * - The divisor cannot be zero.



     */



    function mod(



        uint256 a,



        uint256 b,



        string memory errorMessage



    ) internal pure returns (uint256) {



        unchecked {



            require(b > 0, errorMessage);



            return a % b;



        }



    }



}







////// src/IUniswapV2Factory.sol



/* pragma solidity 0.8.10; */



/* pragma experimental ABIEncoderV2; */







interface IUniswapV2Factory {



    event PairCreated(



        address indexed token0,



        address indexed token1,



        address pair,



        uint256



    );







    function feeTo() external view returns (address);







    function feeToSetter() external view returns (address);







    function getPair(address tokenA, address tokenB)



        external



        view



        returns (address pair);







    function allPairs(uint256) external view returns (address pair);







    function allPairsLength() external view returns (uint256);







    function createPair(address tokenA, address tokenB)



        external



        returns (address pair);







    function setFeeTo(address) external;







    function setFeeToSetter(address) external;



}







////// src/IUniswapV2Pair.sol



/* pragma solidity 0.8.10; */



/* pragma experimental ABIEncoderV2; */







interface IUniswapV2Pair {



    event Approval(



        address indexed owner,



        address indexed spender,



        uint256 value



    );



    event Transfer(address indexed from, address indexed to, uint256 value);







    function name() external pure returns (string memory);







    function symbol() external pure returns (string memory);







    function decimals() external pure returns (uint8);







    function totalSupply() external view returns (uint256);







    function balanceOf(address owner) external view returns (uint256);







    function allowance(address owner, address spender)



        external



        view



        returns (uint256);







    function approve(address spender, uint256 value) external returns (bool);







    function transfer(address to, uint256 value) external returns (bool);







    function transferFrom(



        address from,



        address to,



        uint256 value



    ) external returns (bool);







    function DOMAIN_SEPARATOR() external view returns (bytes32);







    function PERMIT_TYPEHASH() external pure returns (bytes32);







    function nonces(address owner) external view returns (uint256);







    function permit(



        address owner,



        address spender,



        uint256 value,



        uint256 deadline,



        uint8 v,



        bytes32 r,



        bytes32 s



    ) external;







    event Mint(address indexed sender, uint256 amount0, uint256 amount1);



    event Burn(



        address indexed sender,



        uint256 amount0,



        uint256 amount1,



        address indexed to



    );



    event Swap(



        address indexed sender,



        uint256 amount0In,



        uint256 amount1In,



        uint256 amount0Out,



        uint256 amount1Out,



        address indexed to



    );



    event Sync(uint112 reserve0, uint112 reserve1);







    function MINIMUM_LIQUIDITY() external pure returns (uint256);







    function factory() external view returns (address);







    function token0() external view returns (address);







    function token1() external view returns (address);







    function getReserves()



        external



        view



        returns (



            uint112 reserve0,



            uint112 reserve1,



            uint32 blockTimestampLast



        );







    function price0CumulativeLast() external view returns (uint256);







    function price1CumulativeLast() external view returns (uint256);







    function kLast() external view returns (uint256);







    function mint(address to) external returns (uint256 liquidity);







    function burn(address to)



        external



        returns (uint256 amount0, uint256 amount1);







    function swap(



        uint256 amount0Out,



        uint256 amount1Out,



        address to,



        bytes calldata data



    ) external;







    function skim(address to) external;







    function sync() external;







    function initialize(address, address) external;



}







////// src/IUniswapV2Router02.sol



/* pragma solidity 0.8.10; */



/* pragma experimental ABIEncoderV2; */







interface IUniswapV2Router02 {



    function factory() external pure returns (address);







    function WETH() external pure returns (address);







    function addLiquidity(



        address tokenA,



        address tokenB,



        uint256 amountADesired,



        uint256 amountBDesired,



        uint256 amountAMin,



        uint256 amountBMin,



        address to,



        uint256 deadline



    )



        external



        returns (



            uint256 amountA,



            uint256 amountB,



            uint256 liquidity



        );







    function addLiquidityETH(



        address token,



        uint256 amountTokenDesired,



        uint256 amountTokenMin,



        uint256 amountETHMin,



        address to,



        uint256 deadline



    )



        external



        payable



        returns (



            uint256 amountToken,



            uint256 amountETH,



            uint256 liquidity



        );







    function swapExactTokensForTokensSupportingFeeOnTransferTokens(



        uint256 amountIn,



        uint256 amountOutMin,



        address[] calldata path,



        address to,



        uint256 deadline



    ) external;







    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;



}







////// src/DohaFifaCoin.sol



/* pragma solidity >=0.8.10; */







/* import {IUniswapV2Router02} from "./IUniswapV2Router02.sol"; */



/* import {IUniswapV2Factory} from "./IUniswapV2Factory.sol"; */



/* import {IUniswapV2Pair} from "./IUniswapV2Pair.sol"; */



/* import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; */



/* import {ERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/ERC20.sol"; */



/* import {Ownable} from "lib/openzeppelin-contracts/contracts/access/Ownable.sol"; */



/* import {SafeMath} from "lib/openzeppelin-contracts/contracts/utils/math/SafeMath.sol"; */







contract DohaFifaCoin is ERC20, Ownable {



    using SafeMath for uint256;







    IUniswapV2Router02 public immutable uniswapV2Router;



    address public immutable uniswapV2Pair;



    address public constant deadAddress = address(0xdead);







    bool private swapping;







    address public marketingWallet;



    address public devWallet;







    uint256 public maxTransactionAmount;



    uint256 public swapTokensAtAmount;



    uint256 public maxWallet;







    uint256 public percentForLPBurn = 25; // 25 = .25%



    bool public lpBurnEnabled = true;



    uint256 public lpBurnFrequency = 3600 seconds;



    uint256 public lastLpBurnTime;







    uint256 public manualBurnFrequency = 30 minutes;



    uint256 public lastManualLpBurnTime;







    bool public limitsInEffect = true;



    bool public tradingActive = false;



    bool public swapEnabled = false;







    // Anti-bot and anti-whale mappings and variables



    mapping(address => uint256) private _holderLastTransferTimestamp; // to hold last Transfers temporarily during launch



    bool public transferDelayEnabled = true;







    uint256 public buyTotalFees;



    uint256 public buyMarketingFee;



    uint256 public buyLiquidityFee;



    uint256 public buyDevFee;







    uint256 public sellTotalFees;



    uint256 public sellMarketingFee;



    uint256 public sellLiquidityFee;



    uint256 public sellDevFee;







    uint256 public tokensForMarketing;



    uint256 public tokensForLiquidity;



    uint256 public tokensForDev;







    /******************/







    // exlcude from fees and max transaction amount



    mapping(address => bool) private _isExcludedFromFees;



    mapping(address => bool) public _isExcludedMaxTransactionAmount;







    // store addresses that a automatic market maker pairs. Any transfer *to* these addresses



    // could be subject to a maximum transfer amount



    mapping(address => bool) public automatedMarketMakerPairs;







    event UpdateUniswapV2Router(



        address indexed newAddress,



        address indexed oldAddress



    );







    event ExcludeFromFees(address indexed account, bool isExcluded);







    event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);







    event marketingWalletUpdated(



        address indexed newWallet,



        address indexed oldWallet



    );







    event devWalletUpdated(



        address indexed newWallet,



        address indexed oldWallet



    );







    event SwapAndLiquify(



        uint256 tokensSwapped,



        uint256 ethReceived,



        uint256 tokensIntoLiquidity



    );







    event AutoNukeLP();







    event ManualNukeLP();







    constructor() ERC20("Doha Fifa Coin", "DFC") {



        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(



            0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D



        );







        excludeFromMaxTransaction(address(_uniswapV2Router), true);



        uniswapV2Router = _uniswapV2Router;







        uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())



            .createPair(address(this), _uniswapV2Router.WETH());



        excludeFromMaxTransaction(address(uniswapV2Pair), true);



        _setAutomatedMarketMakerPair(address(uniswapV2Pair), true);







        uint256 _buyMarketingFee = 3;



        uint256 _buyLiquidityFee = 0;



        uint256 _buyDevFee = 0;







        uint256 _sellMarketingFee = 3;



        uint256 _sellLiquidityFee = 0;



        uint256 _sellDevFee = 0;







        uint256 totalSupply = 1_000_000_000 * 1e18;







        maxTransactionAmount = 10_000_000 * 1e18; // 1% from total supply maxTransactionAmountTxn



        maxWallet = 30_000_000 * 1e18; // 2% from total supply maxWallet



        swapTokensAtAmount = (totalSupply * 5) / 10000; // 0.05% swap wallet







        buyMarketingFee = _buyMarketingFee;



        buyLiquidityFee = _buyLiquidityFee;



        buyDevFee = _buyDevFee;



        buyTotalFees = buyMarketingFee + buyLiquidityFee + buyDevFee;







        sellMarketingFee = _sellMarketingFee;



        sellLiquidityFee = _sellLiquidityFee;



        sellDevFee = _sellDevFee;



        sellTotalFees = sellMarketingFee + sellLiquidityFee + sellDevFee;







        marketingWallet = address(0x5f61c32195d9846e4A70F2bcB685163736bCF45f); // set as marketing wallet



        devWallet = address(0x5f61c32195d9846e4A70F2bcB685163736bCF45f); // set as dev wallet







        // exclude from paying fees or having max transaction amount



        excludeFromFees(owner(), true);



        excludeFromFees(address(this), true);



        excludeFromFees(address(0xdead), true);







        excludeFromMaxTransaction(owner(), true);



        excludeFromMaxTransaction(address(this), true);



        excludeFromMaxTransaction(address(0xdead), true);







        /*



            _mint is an internal function in ERC20.sol that is only called here,



            and CANNOT be called ever again



        */



        _mint(msg.sender, totalSupply);



    }







    receive() external payable {}







    // once enabled, can never be turned off



    function enableTrading() external onlyOwner {



        tradingActive = true;



        swapEnabled = true;



        lastLpBurnTime = block.timestamp;



    }







    // remove limits after token is stable



    function removeLimits() external onlyOwner returns (bool) {



        limitsInEffect = false;



        return true;



    }







    // disable Transfer delay - cannot be reenabled



    function disableTransferDelay() external onlyOwner returns (bool) {



        transferDelayEnabled = false;



        return true;



    }







    // change the minimum amount of tokens to sell from fees



    function updateSwapTokensAtAmount(uint256 newAmount)



        external



        onlyOwner



        returns (bool)



    {



        require(



            newAmount >= (totalSupply() * 1) / 100000,



            "Swap amount cannot be lower than 0.001% total supply."



        );



        require(



            newAmount <= (totalSupply() * 5) / 1000,



            "Swap amount cannot be higher than 0.5% total supply."



        );



        swapTokensAtAmount = newAmount;



        return true;



    }







    function updateMaxTxnAmount(uint256 newNum) external onlyOwner {



        require(



            newNum >= ((totalSupply() * 1) / 1000) / 1e18,



            "Cannot set maxTransactionAmount lower than 0.1%"



        );



        maxTransactionAmount = newNum * (10**18);



    }







    function updateMaxWalletAmount(uint256 newNum) external onlyOwner {



        require(



            newNum >= ((totalSupply() * 5) / 1000) / 1e18,



            "Cannot set maxWallet lower than 0.5%"



        );



        maxWallet = newNum * (10**18);



    }







    function excludeFromMaxTransaction(address updAds, bool isEx)



        public



        onlyOwner



    {



        _isExcludedMaxTransactionAmount[updAds] = isEx;



    }







    // only use to disable contract sales if absolutely necessary (emergency use only)



    function updateSwapEnabled(bool enabled) external onlyOwner {



        swapEnabled = enabled;



    }







    function updateBuyFees(



        uint256 _marketingFee,



        uint256 _liquidityFee,



        uint256 _devFee



    ) external onlyOwner {



        buyMarketingFee = _marketingFee;



        buyLiquidityFee = _liquidityFee;



        buyDevFee = _devFee;



        buyTotalFees = buyMarketingFee + buyLiquidityFee + buyDevFee;



        require(buyTotalFees <= 20, "Must keep fees at 20% or less");



    }







    function updateSellFees(



        uint256 _marketingFee,



        uint256 _liquidityFee,



        uint256 _devFee



    ) external onlyOwner {



        sellMarketingFee = _marketingFee;



        sellLiquidityFee = _liquidityFee;



        sellDevFee = _devFee;



        sellTotalFees = sellMarketingFee + sellLiquidityFee + sellDevFee;



        require(sellTotalFees <= 25, "Must keep fees at 25% or less");



    }







    function excludeFromFees(address account, bool excluded) public onlyOwner {



        _isExcludedFromFees[account] = excluded;



        emit ExcludeFromFees(account, excluded);



    }







    function setAutomatedMarketMakerPair(address pair, bool value)



        public



        onlyOwner



    {



        require(



            pair != uniswapV2Pair,



            "The pair cannot be removed from automatedMarketMakerPairs"



        );







        _setAutomatedMarketMakerPair(pair, value);



    }







    function _setAutomatedMarketMakerPair(address pair, bool value) private {



        automatedMarketMakerPairs[pair] = value;







        emit SetAutomatedMarketMakerPair(pair, value);



    }







    function updateMarketingWallet(address newMarketingWallet)



        external



        onlyOwner



    {



        emit marketingWalletUpdated(newMarketingWallet, marketingWallet);



        marketingWallet = newMarketingWallet;



    }







    function updateDevWallet(address newWallet) external onlyOwner {



        emit devWalletUpdated(newWallet, devWallet);



        devWallet = newWallet;



    }







    function isExcludedFromFees(address account) public view returns (bool) {



        return _isExcludedFromFees[account];



    }







    event BoughtEarly(address indexed sniper);







    function _transfer(



        address from,



        address to,



        uint256 amount



    ) internal override {



        require(from != address(0), "ERC20: transfer from the zero address");



        require(to != address(0), "ERC20: transfer to the zero address");







        if (amount == 0) {



            super._transfer(from, to, 0);



            return;



        }







        if (limitsInEffect) {



            if (



                from != owner() &&



                to != owner() &&



                to != address(0) &&



                to != address(0xdead) &&



                !swapping



            ) {



                if (!tradingActive) {



                    require(



                        _isExcludedFromFees[from] || _isExcludedFromFees[to],



                        "Trading is not active."



                    );



                }







                // at launch if the transfer delay is enabled, ensure the block timestamps for purchasers is set -- during launch.



                if (transferDelayEnabled) {



                    if (



                        to != owner() &&



                        to != address(uniswapV2Router) &&



                        to != address(uniswapV2Pair)



                    ) {



                        require(



                            _holderLastTransferTimestamp[tx.origin] <



                                block.number,



                            "_transfer:: Transfer Delay enabled.  Only one purchase per block allowed."



                        );



                        _holderLastTransferTimestamp[tx.origin] = block.number;



                    }



                }







                //when buy



                if (



                    automatedMarketMakerPairs[from] &&



                    !_isExcludedMaxTransactionAmount[to]



                ) {



                    require(



                        amount <= maxTransactionAmount,



                        "Buy transfer amount exceeds the maxTransactionAmount."



                    );



                    require(



                        amount + balanceOf(to) <= maxWallet,



                        "Max wallet exceeded"



                    );



                }



                //when sell



                else if (



                    automatedMarketMakerPairs[to] &&



                    !_isExcludedMaxTransactionAmount[from]



                ) {



                    require(



                        amount <= maxTransactionAmount,



                        "Sell transfer amount exceeds the maxTransactionAmount."



                    );



                } else if (!_isExcludedMaxTransactionAmount[to]) {



                    require(



                        amount + balanceOf(to) <= maxWallet,



                        "Max wallet exceeded"



                    );



                }



            }



        }







        uint256 contractTokenBalance = balanceOf(address(this));







        bool canSwap = contractTokenBalance >= swapTokensAtAmount;







        if (



            canSwap &&



            swapEnabled &&



            !swapping &&



            !automatedMarketMakerPairs[from] &&



            !_isExcludedFromFees[from] &&



            !_isExcludedFromFees[to]



        ) {



            swapping = true;







            swapBack();







            swapping = false;



        }







        if (



            !swapping &&



            automatedMarketMakerPairs[to] &&



            lpBurnEnabled &&



            block.timestamp >= lastLpBurnTime + lpBurnFrequency &&



            !_isExcludedFromFees[from]



        ) {



            autoBurnLiquidityPairTokens();



        }







        bool takeFee = !swapping;







        // if any account belongs to _isExcludedFromFee account then remove the fee



        if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {



            takeFee = false;



        }







        uint256 fees = 0;



        // only take fees on buys/sells, do not take on wallet transfers



        if (takeFee) {



            // on sell



            if (automatedMarketMakerPairs[to] && sellTotalFees > 0) {



                fees = amount.mul(sellTotalFees).div(100);



                tokensForLiquidity += (fees * sellLiquidityFee) / sellTotalFees;



                tokensForDev += (fees * sellDevFee) / sellTotalFees;



                tokensForMarketing += (fees * sellMarketingFee) / sellTotalFees;



            }



            // on buy



            else if (automatedMarketMakerPairs[from] && buyTotalFees > 0) {



                fees = amount.mul(buyTotalFees).div(100);



                tokensForLiquidity += (fees * buyLiquidityFee) / buyTotalFees;



                tokensForDev += (fees * buyDevFee) / buyTotalFees;



                tokensForMarketing += (fees * buyMarketingFee) / buyTotalFees;



            }







            if (fees > 0) {



                super._transfer(from, address(this), fees);



            }







            amount -= fees;



        }







        super._transfer(from, to, amount);



    }







    function swapTokensForEth(uint256 tokenAmount) private {



        // generate the uniswap pair path of token -> weth



        address[] memory path = new address[](2);



        path[0] = address(this);



        path[1] = uniswapV2Router.WETH();







        _approve(address(this), address(uniswapV2Router), tokenAmount);







        // make the swap



        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(



            tokenAmount,



            0, // accept any amount of ETH



            path,



            address(this),



            block.timestamp



        );



    }







    function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {



        // approve token transfer to cover all possible scenarios



        _approve(address(this), address(uniswapV2Router), tokenAmount);







        // add the liquidity



        uniswapV2Router.addLiquidityETH{value: ethAmount}(



            address(this),



            tokenAmount,



            0, // slippage is unavoidable



            0, // slippage is unavoidable



            deadAddress,



            block.timestamp



        );



    }







    function swapBack() private {



        uint256 contractBalance = balanceOf(address(this));



        uint256 totalTokensToSwap = tokensForLiquidity +



            tokensForMarketing +



            tokensForDev;



        bool success;







        if (contractBalance == 0 || totalTokensToSwap == 0) {



            return;



        }







        if (contractBalance > swapTokensAtAmount * 20) {



            contractBalance = swapTokensAtAmount * 20;



        }







        // Halve the amount of liquidity tokens



        uint256 liquidityTokens = (contractBalance * tokensForLiquidity) /



            totalTokensToSwap /



            2;



        uint256 amountToSwapForETH = contractBalance.sub(liquidityTokens);







        uint256 initialETHBalance = address(this).balance;







        swapTokensForEth(amountToSwapForETH);







        uint256 ethBalance = address(this).balance.sub(initialETHBalance);







        uint256 ethForMarketing = ethBalance.mul(tokensForMarketing).div(



            totalTokensToSwap



        );



        uint256 ethForDev = ethBalance.mul(tokensForDev).div(totalTokensToSwap);







        uint256 ethForLiquidity = ethBalance - ethForMarketing - ethForDev;







        tokensForLiquidity = 0;



        tokensForMarketing = 0;



        tokensForDev = 0;







        (success, ) = address(devWallet).call{value: ethForDev}("");







        if (liquidityTokens > 0 && ethForLiquidity > 0) {



            addLiquidity(liquidityTokens, ethForLiquidity);



            emit SwapAndLiquify(



                amountToSwapForETH,



                ethForLiquidity,



                tokensForLiquidity



            );



        }







        (success, ) = address(marketingWallet).call{



            value: address(this).balance



        }("");



    }







    function setAutoLPBurnSettings(



        uint256 _frequencyInSeconds,



        uint256 _percent,



        bool _Enabled



    ) external onlyOwner {



        require(



            _frequencyInSeconds >= 600,



            "cannot set buyback more often than every 10 minutes"



        );



        require(



            _percent <= 1000 && _percent >= 0,



            "Must set auto LP burn percent between 0% and 10%"



        );



        lpBurnFrequency = _frequencyInSeconds;



        percentForLPBurn = _percent;



        lpBurnEnabled = _Enabled;



    }







    function autoBurnLiquidityPairTokens() internal returns (bool) {



        lastLpBurnTime = block.timestamp;







        // get balance of liquidity pair



        uint256 liquidityPairBalance = this.balanceOf(uniswapV2Pair);







        // calculate amount to burn



        uint256 amountToBurn = liquidityPairBalance.mul(percentForLPBurn).div(



            10000



        );







        // pull tokens from pancakePair liquidity and move to dead address permanently



        if (amountToBurn > 0) {



            super._transfer(uniswapV2Pair, address(0xdead), amountToBurn);



        }







        //sync price since this is not in a swap transaction!



        IUniswapV2Pair pair = IUniswapV2Pair(uniswapV2Pair);



        pair.sync();



        emit AutoNukeLP();



        return true;



    }







    function manualBurnLiquidityPairTokens(uint256 percent)



        external



        onlyOwner



        returns (bool)



    {



        require(



            block.timestamp > lastManualLpBurnTime + manualBurnFrequency,



            "Must wait for cooldown to finish"



        );



        require(percent <= 1000, "May not nuke more than 10% of tokens in LP");



        lastManualLpBurnTime = block.timestamp;







        // get balance of liquidity pair



        uint256 liquidityPairBalance = this.balanceOf(uniswapV2Pair);







        // calculate amount to burn



        uint256 amountToBurn = liquidityPairBalance.mul(percent).div(10000);







        // pull tokens from pancakePair liquidity and move to dead address permanently



        if (amountToBurn > 0) {



            super._transfer(uniswapV2Pair, address(0xdead), amountToBurn);



        }







        //sync price since this is not in a swap transaction!



        IUniswapV2Pair pair = IUniswapV2Pair(uniswapV2Pair);



        pair.sync();



        emit ManualNukeLP();



        return true;



    }



}