// Contract: Berc20Store
// Target function: function createTokenInfo(address tokenAddress,
// SPDX-License-Identifier: MIT

//'########::'########:'########:::'######:::'#######::::'#####:::
//##.... ##: ##.....:: ##.... ##:'##... ##:'##.... ##::'##.. ##::
//##:::: ##: ##::::::: ##:::: ##: ##:::..::..::::: ##:'##:::: ##:
//########:: ######::: ########:: ##::::::::'#######:: ##:::: ##:
//##.... ##: ##...:::: ##.. ##::: ##:::::::'##:::::::: ##:::: ##:
//##:::: ##: ##::::::: ##::. ##:: ##::: ##: ##::::::::. ##:: ##::
//########:: ########: ##:::. ##:. ######:: #########::. #####:::
//........:::........::..:::::..:::......:::.........::::.....::::
pragma solidity ^0.8.9;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, 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 from,
        address to,
        uint256 amount
    ) external returns (bool);
}

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(_msgSender());
    }

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

interface BlackErc20 {
    function getMintedCounts() external view returns (uint256);
    function getAllContractTypes() external view returns (uint256[] memory);
}

contract Berc20Store is Ownable {

    address public authorizedAddress;
    uint256 public maxUrlLength = 50;
    uint256 public maxTextLength = 100;
    string public defaultLogo = "https://s1.ax1x.com/2023/06/18/pC1Sj1A.png";
    string[] private forbiddenNames = ["btc", "eth", "usdt", "bnb", "usdc", "xrp", "steth", "ada", "doge", "sol", "trx", "ltc", "matic", "dot", "dai", "busd", "wbtc", "shiba","avax","uin","link","okb","atom","etc","tusd","ferc"];
    address public devAddress;
    uint256 public payPrice;
    mapping(address => uint256) public oldTokenMintedNums;


    //////////////////////////////////////////////////////////////////////

    struct TokenInfo {
        address tokenAddress;
        string logo;
        string name;
        string symbol;
        uint256 totalSupply;
        uint256 maxMintCount;
        uint256 maxMintPerAddress;
        uint256 mintPrice;
        address creator;
        uint256 progress;
        uint256[4] limits;  // 0 - erc20，1 - erc721，2 - erc1155，3 - white list
    }

    struct TokenMsg {
        string description;
        string logoUrl;
        string bannerUrl;
        string website;
        string twitter;
        string telegram;
        string discord;
        string detailUrl;
    }

    struct Profile {

        uint256 idx;
        TokenMsg msg;
        bytes32 wlRoot;

        mapping(uint256=>uint256) params;
        uint256 paramsCount;

        mapping(uint256=>address) authContracts;
        uint256 authContractsCount;
    }

    struct FoundTokenItem {
        uint128 i;
        uint128 progress;
    }

    //////////////////////////////////////////////////////////////////////

    // tokens
    mapping(uint256 => TokenInfo) public tokens;      // (id=>token), NOTE: begin with 1, or 0 failed 
    uint256 public tokensCount;

    // profile data for uesr
    mapping(address => Profile) public tokenProfiles;
    mapping(string => address) public tokenNames;

    modifier onlyAuthorized() {
        require(msg.sender == authorizedAddress, "Not authorized");
        _;
    }

    receive() external payable {}