// File: erc20.sol



// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

library SafeMath {
    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);
    }
    }
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
    unchecked {
        if (b > a) return (false, 0);
        return (true, a - b);
    }
    }
    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);
    }
    }

    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
    unchecked {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }
    }

    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
    unchecked {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }
    }


    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }


    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }


    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }


    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }


    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }


    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    unchecked {
        require(b <= a, errorMessage);
        return a - b;
    }
    }


    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    unchecked {
        require(b > 0, errorMessage);
        return a / b;
    }
    }


    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
    unchecked {
        require(b > 0, errorMessage);
        return a % b;
    }
    }
}

contract ERC20 {
    using SafeMath for uint256;
   
    string   public name;
    string   public symbol;
    uint8    public decimals;
    uint256  public totalSupply;
 
    mapping (address => uint256) private balances;
    mapping (address => mapping (address => uint256)) private allowances;
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    
    constructor (string memory _name, string memory _symbol, uint8 _decimals) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
    }

    function balanceOf(address owner) public view returns (uint256) {
        return balances[owner];
    }
    
    function allowance(address owner, address spender) public view returns(uint256) {
        return allowances[owner][spender];
    }
    
    function approve(address spender, uint256 amount) external returns(bool) {
        allowances[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    function transfer(address to, uint256 amount) external returns (bool) {
        _transfer(msg.sender, to, amount);
        return true;
    }

    function transferFrom(address owner, address to, uint256 amount) external returns(bool) {
        require(allowances[owner][msg.sender] >= amount, "ERC20: transfer amount exceeds allowance");
        allowances[owner][msg.sender] = allowances[owner][msg.sender].sub(amount);
        _transfer(owner, to, amount);
        return true;
    }

    function _transfer(address from, address to, uint256 amount) internal {
        require(to != address(0), "to address cannot be 0");
        balances[from] = balances[from].sub(amount);
        balances[to] =  balances[to].add(amount);
        emit Transfer(from, to, amount);
    }
    
    function _mint(address to, uint256 amount) internal {
        require(to != address(0), "to address cannot be 0");
        balances[to] = balances[to].add(amount);
        totalSupply = totalSupply.add(amount);
        emit Transfer(address(0), to, amount);
    }

    function _burn(uint256 amount) internal {
        balances[msg.sender] = balances[msg.sender].sub(amount);
        totalSupply = totalSupply.sub(amount);
        emit Transfer(msg.sender, address(0), amount);
    }
}


// File: wluca.sol



// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./erc20.sol";
contract WLUCA is ERC20{
    address public owner;
    address public minter;

    constructor() ERC20("wrap luca", "WLUCA",  18){
        owner = msg.sender;
    }
    
    function setOwner(address user) external{
        require(msg.sender == owner, "WLUCA: only owner");
        require(user != address(0), "user address cannot be 0");
        owner = user;
    }
    
    function setMinter(address user) external{
        require(msg.sender == owner, "WLUCA: only owner");
        require(user != address(0), "user address cannot be 0");
        minter = user;
    }

    function mint(address to, uint256 value) external{
        require(msg.sender == minter, "WLUCA: only minter");
        _mint(to, value);
    }
    
    function burn(uint256 amount) external {
        _burn(amount);
    }
}