SyndicateOfVigilantesTokenProxyable

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

// lib/cyphermate/src/access/Blocklistable.sol

abstract contract Blocklistable {

    event Blocklisted(address indexed operator, address indexed wallet, bool blocklisted);

    mapping(address => bool) internal _blocklisted;

    function _setBlocklist(address[] memory wallets_, bool blocklisted_) internal virtual {
        for (uint256 i; i < wallets_.length;) {
            _blocklisted[wallets_[i]] = blocklisted_;
            emit Blocklisted(msg.sender, wallets_[i], blocklisted_);
            unchecked { ++i; }
        }
    }

    function _isBlocklisted(address wallet_) internal virtual view returns (bool) {
        return _blocklisted[wallet_];
    }

    modifier notBlocklisted(address wallet_) {
        require(!_blocklisted[wallet_], "WALLET_BLOCKLISTED");
        _;
    }

    bytes32[50] private __padding;
}

// lib/cyphermate/src/access/Ownable.sol

// ERC-173 Compliant -> https://eips.ethereum.org/EIPS/eip-173
abstract contract Ownable {

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    address public owner; 

    modifier onlyOwner() virtual {
        require (msg.sender == owner, "Ownable::onlyOwner: NOT_OWNER");
        _;
    }

    constructor (address owner_) {
        _transferOwnership(owner_);
    }

    function _transferOwnership(address newOwner_) internal virtual {
        address _oldOwner = owner; 
        owner = newOwner_;
        emit OwnershipTransferred(_oldOwner, newOwner_);
    }

    function transferOwnership(address newOwner_) public virtual onlyOwner {
        require(newOwner_ != address(0), 
            "Ownable::transferOwnership: ZERO_ADDRESS_TRANSFER");
            
        _transferOwnership(newOwner_);
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    bytes32[50] private __padding;
}

// src/dependencies/ERC20.sol

// EIP-20 Compliant -> https://eips.ethereum.org/EIPS/eip-20
// Forked from CypherLabz/Cyphermate
abstract contract ERC20 {

    event Transfer(address indexed from, address indexed to, uint256 amount);
    event Approval(address indexed owner, address indexed spender, uint256 amount);

    string public name;
    string public symbol;

    // Override decimals using a function override here
    function decimals() public view virtual returns (uint8) {
        return 18; 
    }

    constructor(string memory name_, string memory symbol_) {
        name = name_;
        symbol = symbol_;
    }

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    function _mint(address to_, uint256 amount_) internal virtual {
        require(to_ != address(0), "ERC20: _mint to zero");

        totalSupply += amount_;
        
        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked { 
            balanceOf[to_] += amount_; 
        }
        
        emit Transfer(address(0), to_, amount_);
    }

    function _burn(address from_, uint256 amount_) internal virtual {
        require(from_ != address(0), "ERC20: _burn from zero");

        // Fork: added verbose errors
        uint256 _bal = balanceOf[from_];
        require(_bal >= amount_, "ERC20: _burn insufficient balance");

        balanceOf[from_] -= amount_;
        
        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount_;
        }
        
        emit Transfer(from_, address(0), amount_);
    }

    function _transfer(address from_, address to_, uint256 amount_) internal virtual {
        require(from_ != address(0), "ERC20: _transfer from_ zero");
        require(to_ != address(0), "ERC20: _transfer to_ zero");

        // Fork: added verbose errors
        uint256 _bal = balanceOf[from_];
        require(_bal >= amount_, "ERC20: _transfer insufficient balance");

        balanceOf[from_] -= amount_; // underflow-as-require

        // Cannot overflow because the sum of all user 
        // balances can't exceed max uint256 value.
        unchecked { 
            balanceOf[to_] += amount_;
        }

        emit Transfer(from_, to_, amount_);
    }

    function _spendAllowance(address from_, address operator_, uint256 amount_) 
    internal virtual {
        if (allowance[from_][operator_] != type(uint256).max) {
            allowance[from_][operator_] -= amount_; // underflow-as-require
        }
    }

    function _approve(address owner_, address spender_, uint256 amount_) internal virtual {
        allowance[owner_][spender_] = amount_;
        emit Approval(owner_, spender_, amount_);
    }
    
    function approve(address spender_, uint256 amount_) public virtual returns (bool) { 
        _approve(msg.sender, spender_, amount_);
        return true;
    }

    function transfer(address to_, uint256 amount_) public virtual returns (bool) {
        _transfer(msg.sender, to_, amount_);
        return true;
    }

    function transferFrom(address from_, address to_, uint256 amount_) public virtual returns (bool) {
        _spendAllowance(from_, msg.sender, amount_);
        _transfer(from_, to_, amount_);
        return true;
    }

    bytes32[50] private __padding;
}

// lib/cyphermate/src/access/2step/Ownable2Step.sol

// Last update: 2024-02-12

// An extension of EIP-173 for a 2-step verification of ownership transfer.
abstract contract Ownable2Step is Ownable {

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    address public pendingOwner;

    // Override Functions
    function transferOwnership(address newOwner_) public virtual override(Ownable) onlyOwner {
        pendingOwner = newOwner_;
        emit OwnershipTransferStarted(msg.sender, newOwner_); 
    }

    function _transferOwnership(address newOwner_) internal virtual override(Ownable) {
        delete pendingOwner;
        Ownable._transferOwnership(newOwner_);
    }

    // Non-Override Functions
    function acceptOwnership() public virtual {
        require(pendingOwner == msg.sender, "Ownable2Step: NOT_PENDING_OWNER");
        Ownable2Step._transferOwnership(msg.sender);
    }

    function renounceOwnership() public virtual override(Ownable) onlyOwner {
        delete pendingOwner;
        Ownable.renounceOwnership();
    }

    bytes32[50] private __padding;
}

// lib/cyphermate/src/access/2step/Controllerable2Step.sol

// Last update: 2024-01-20

/**
 * @title Controllerable: Dynamic Controller System
 * @author 0xInuarashi
 * @notice Controllerable is a role validation smart contract that expands ownable style roles into configurable roles, identified by a string. 
 * Solidity automatically converts a string key in a mapping into a bytes32 type automatically.
 * Each controller type is identified by a string, so you can make an unlimited amount of controller types, such as "MINTER", "BURNER", "OPERATOR", then you can verify internally with onlyController("MINTER") or externally with isController("MINTER", <addressToLookup>)
 */

abstract contract Controllerable2Step is Ownable2Step {

    event ControllerSet(address indexed owner, address indexed controller, string controllerType, bool status);
    
    mapping(string => mapping(address => bool)) internal __controllers;

    function isController(string memory type_, address controller_) public view virtual returns (bool) {
        return __controllers[type_][controller_];
    }

    modifier onlyController(string memory type_) { 
        require(isController(type_, msg.sender), "Controllerable: NOT_CONTROLLER");
        _;
    }

    function setController(string memory type_, address controller_, bool bool_) public virtual onlyOwner {
        __controllers[type_][controller_] = bool_;
        emit ControllerSet(msg.sender, controller_, type_, bool_);
    }

    bytes32[50] private __padding;
}

// src/SyndicateOfVigilantesTokenProxyable.sol

/**

---------------------------------------------------------------------------------------------------
| Group                       | Alloc% | Token Allocation | TGE%  | Cliff (months) | Vesting (months) |
|-----------------------------|--------|------------------|-------|----------------|------------------|
| Player Incentives & Rewards | 27%    | 270,000,000      | 0%    | 2              | 36               |
| Ecosystem Treasury          | 20%    | 200,000,000      | 0%    | 5              | 30               |
| Core Team                   | 10%    | 100,000,000      | 0%    | 16             | 36               |
| Private Seed Round          | 9%     | 90,000,000       | 0%    | 4              | 9                |
| Strategic Advisory          | 9%     | 90,000,000       | 0%    | 12             | 36               |
| TGE                         | 5%     | 50,000,000       | 50%   | 0              | 4                |
| Liquidity                   | 20%    | 200,000,000      | 5%    | 0              | 18               |
| Total                       | 100%   | 1,000,000,000    |       |                |                  |
---------------------------------------------------------------------------------------------------

 */

contract SyndicateOfVigilantesTokenProxyable is ERC20, Controllerable2Step, Blocklistable {

    // The constructor in this contract is intentionally empty.
    // Initialization happens via the initialize() function when deployed through a proxy.
    constructor()
        Ownable(msg.sender)
        ERC20("", "")
    {
        // Empty - actual initialization happens in initialize()
    }

    // Total MAX Supply of Tokens. All the constants add up to this.
    uint256 public constant TOTAL_MAX_MINTED = 1_000_000_000 ether;

    // Total MAX tokens and tracker for minted of each category
    // Aligned with tokenomics XLSX: contract.xlsx
    uint256 public constant PLAYER_INCENTIVES_MAX_MINTED = 270_000_000 ether; // 27% - Player Incentives & Rewards
    uint256 public constant ECOSYSTEM_TREASURY_MAX_MINTED = 200_000_000 ether; // 20% - Ecosystem Treasury
    uint256 public constant TEAM_MAX_MINTED = 100_000_000 ether; // 10% - Core Team
    uint256 public constant PRIVATE_TOKEN_SALE_MAX_MINTED = 90_000_000 ether; // 9% - Private Seed Round
    uint256 public constant ADVISORS_MAX_MINTED = 90_000_000 ether; // 9% - Strategic Advisory

    /**
     * @dev MONTH definition for vesting calculations
     * TESTNET → 5 minutes for quick testing (e.g., 5 month cliff = 25 minutes, 30 months = 2.5 hours)
     * MAINNET → Change to 30 days for production (e.g., 16 month cliff = 480 days)
     */
    uint256 public constant MONTH = 30 days; // TODO: Change to 30 days for mainnet

    // Total VEST time in seconds for each category (from XLSX)
    uint256 public constant PLAYER_INCENTIVES_VEST = 36 * MONTH; // 36 months (3 years)
    uint256 public constant ECOSYSTEM_TREASURY_VEST = 30 * MONTH; // 30 months (2.5 years)
    uint256 public constant TEAM_VEST = 36 * MONTH; // 36 months (3 years)
    uint256 public constant PRIVATE_TOKEN_SALE_VEST = 9 * MONTH; // 9 months
    uint256 public constant ADVISORS_VEST = 36 * MONTH; // 36 months (3 years)
    uint256 public constant TGE_VEST = 4 * MONTH; // 4 months (for remaining 50% of TGE)
    uint256 public constant LIQUIDITY_VEST = 18 * MONTH; // 18 months (for remaining 95% of Liquidity)

    // Cliff periods in seconds for each category (time before vesting starts)
    uint256 public constant PLAYER_INCENTIVES_CLIFF = 2 * MONTH; // 2 months cliff
    uint256 public constant ECOSYSTEM_TREASURY_CLIFF = 5 * MONTH; // 5 months cliff
    uint256 public constant TEAM_CLIFF = 16 * MONTH; // 16 months cliff
    uint256 public constant PRIVATE_TOKEN_SALE_CLIFF = 4 * MONTH; // 4 months cliff
    uint256 public constant ADVISORS_CLIFF = 12 * MONTH; // 12 months cliff
    uint256 public constant TGE_CLIFF = 0; // No cliff for TGE
    uint256 public constant LIQUIDITY_CLIFF = 0; // No cliff for Liquidity

    // Total TPS (Tokens Per Second) of each category
    uint256 public constant PLAYER_INCENTIVES_TPS = PLAYER_INCENTIVES_MAX_MINTED / PLAYER_INCENTIVES_VEST;
    // uint256 public constant ECOSYSTEM_TREASURY_TPS = ECOSYSTEM_TREASURY_MAX_MINTED / ECOSYSTEM_TREASURY_VEST;
    uint256 public constant TEAM_TPS = TEAM_MAX_MINTED / TEAM_VEST;
    uint256 public constant PRIVATE_TOKEN_SALE_TPS = PRIVATE_TOKEN_SALE_MAX_MINTED / PRIVATE_TOKEN_SALE_VEST;
    uint256 public constant ADVISORS_TPS = ADVISORS_MAX_MINTED / ADVISORS_VEST;

    // TGE and Liquidity vesting amounts and TPS
    uint256 public constant TGE_MAX_MINTED = 50_000_000 ether; // 5% total (50M tokens)
    uint256 public constant TGE_VESTING_AMOUNT = 25_000_000 ether; // 50% vests over 4 months
    uint256 public constant TGE_TPS = TGE_VESTING_AMOUNT / TGE_VEST;

    uint256 public constant LIQUIDITY_MAX_MINTED = 200_000_000 ether; // 20% total (200M tokens)
    uint256 public constant LIQUIDITY_VESTING_AMOUNT = 190_000_000 ether; // 95% vests over 18 months
    uint256 public constant LIQUIDITY_TPS = LIQUIDITY_VESTING_AMOUNT / LIQUIDITY_VEST;
    
    /**
     * @dev TGE unlock addresses and amounts
     * TGE: 50% unlocked immediately (25M), 50% vests over 4 months (25M)
     * Liquidity: 5% unlocked immediately (10M), 95% vests over 18 months (190M)
     */

    // TGE and Liquidity immediate unlock addresses (set during initialize)
    address public TGE_RECEIVER;
    address public LIQUIDITY_RECEIVER;

    uint256 public constant TGE_IMMEDIATE_UNLOCK = 25_000_000 ether; // 50% of TGE (2.5% of total supply)
    uint256 public constant LIQUIDITY_IMMEDIATE_UNLOCK = 10_000_000 ether; // 5% of Liquidity (1% of total supply)

    /** @dev YIELD_START_TIME - TESTNET: Set to current time for immediate testing */
    uint256 public constant YIELD_START_TIME = 1759827600; // 2025-10-07 09:00:00 - CHANGE FOR MAINNET

    /**
     * @dev SSTORE trackers for minted counts of vested tokens
     */

    uint256 public playerIncentivesTokensMinted;
    uint256 public ecosystemTreasuryTokensMinted;
    uint256 public teamTokensMinted;
    uint256 public privateTokenSaleTokensMinted;
    uint256 public advisorsTokensMinted;
    uint256 public tgeTokensMinted;
    uint256 public liquidityTokensMinted;

    /**
     * @dev the initialize paradigm for upgradeable proxies. It is used by proxies to initialize.
     */

    bool public proxyInitialized;

    function initialize(
        address owner_,
        address tgeReceiver_,
        address liquidityReceiver_,
        string memory name_,
        string memory symbol_
    ) public {
        require(!proxyInitialized, "PROXY_INITIALIZED");
        require(tgeReceiver_ != address(0), "INVALID_TGE_RECEIVER");
        require(liquidityReceiver_ != address(0), "INVALID_LIQUIDITY_RECEIVER");
        require(bytes(name_).length > 0, "INVALID_NAME");
        require(bytes(symbol_).length > 0, "INVALID_SYMBOL");

        // Sanity check - verify total allocations equal max supply
        require(
            TOTAL_MAX_MINTED == (
                PLAYER_INCENTIVES_MAX_MINTED +
                ECOSYSTEM_TREASURY_MAX_MINTED +
                TEAM_MAX_MINTED +
                PRIVATE_TOKEN_SALE_MAX_MINTED +
                ADVISORS_MAX_MINTED +
                TGE_MAX_MINTED +
                LIQUIDITY_MAX_MINTED
            ),
            "TOTAL_SUPPLY_NOT_EQUAL"
        );

        // Set receiver addresses
        TGE_RECEIVER = tgeReceiver_;
        LIQUIDITY_RECEIVER = liquidityReceiver_;

        // Ownable (Uses Controller2Step overridden _transferOwnership function)
        _transferOwnership(owner_);

        // ERC20
        name = name_;
        symbol = symbol_;

        // Mint immediate unlock tokens
        _mint(TGE_RECEIVER, TGE_IMMEDIATE_UNLOCK); // 25M TGE immediate
        _mint(LIQUIDITY_RECEIVER, LIQUIDITY_IMMEDIATE_UNLOCK); // 10M Liquidity immediate

        // Lock the initialization
        proxyInitialized = true;
    }

    /**
     * @dev _mint is overrided from ERC20 in order to add a TOTAL_MAX_MINTED check
     */
    function _mint(address to_, uint256 amount_) internal virtual override(ERC20) notBlocklisted(to_) {
        require(TOTAL_MAX_MINTED >= (totalSupply + amount_), 
            "SyndicateOfVigilantesToken: _mint exceeds MAX");
        
        ERC20._mint(to_, amount_);
    }

    /**
     * @dev blocklistable functionality and overrides for the token
     */
    function adminSetBlocklist(address[] calldata wallets_, bool blocklisted_) public virtual 
    onlyController("ADMIN") {
        _setBlocklist(wallets_, blocklisted_);
    }

    function _transfer(address from_, address to_, uint256 amount_) internal virtual 
    override(ERC20) notBlocklisted(from_) notBlocklisted(to_) {
        ERC20._transfer(from_, to_, amount_);
    }

    /**
     * @dev internal helper functions for calculations of values
     */
    function _min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? b : a;
    }

    function _getSecondsElapsed() internal view returns (uint256) {
        return block.timestamp > YIELD_START_TIME ?
            (block.timestamp - YIELD_START_TIME) : 0;
    }

    function _getAvailableTokens(uint256 maxTokens_, uint256 categoryTPS_,
    uint256 currMinted_, uint256 cliffDuration_) internal view returns (uint256) {
        uint256 _secondsElapsed = _getSecondsElapsed();

        // Check if cliff period has passed
        if (_secondsElapsed < cliffDuration_) {
            return 0; // No tokens available during cliff period
        }

        // After cliff: tokens accumulate only from cliff end onwards
        // Vesting starts AFTER the cliff period
        uint256 _secondsSinceCliffEnd = _secondsElapsed - cliffDuration_;
        uint256 _mintableTokensPerSecond = categoryTPS_;

        uint256 _totalMintableTokens =
            _min(
                maxTokens_,
                (_mintableTokensPerSecond * _secondsSinceCliffEnd)
            );

        uint256 _availableMintableTokens = _totalMintableTokens - currMinted_;
        return _availableMintableTokens;
    }

    /**
     * @dev abstracted _getAvailableTokens functions for each category.
     * Created for code cleanliness.
     */

    function availablePrivateSaleTokens() public view returns(uint256) {
        return _getAvailableTokens(
            PRIVATE_TOKEN_SALE_MAX_MINTED,
            PRIVATE_TOKEN_SALE_TPS,
            privateTokenSaleTokensMinted,
            PRIVATE_TOKEN_SALE_CLIFF
        );
    }

    function availablePlayerIncentivesTokens() public view returns (uint256) {
        return _getAvailableTokens(
            PLAYER_INCENTIVES_MAX_MINTED,
            PLAYER_INCENTIVES_TPS,
            playerIncentivesTokensMinted,
            PLAYER_INCENTIVES_CLIFF
        );
    }

    function availableEcosystemTreasuryTokens() public view returns (uint256) {
        // Custom vesting schedule for Ecosystem Treasury
        // Month 1 (after 5mo cliff): 16,666,667
        // Months 2-29 (28 months): 6,333,333 each
        // Month 30 (final): 6,000,000
        // Total: 16,666,667 + (28 × 6,333,333) + 6,000,000 = 200,000,000

        if (block.timestamp < YIELD_START_TIME) {
            return 0;
        }

        uint256 timeSinceStart = block.timestamp - YIELD_START_TIME;

        // Check cliff period (5 months)
        if (timeSinceStart < ECOSYSTEM_TREASURY_CLIFF) {
            return 0;
        }

        uint256 timeSinceCliff = timeSinceStart - ECOSYSTEM_TREASURY_CLIFF;
        uint256 monthsSinceCliff = timeSinceCliff / MONTH;

        uint256 vestedAmount;

        if (monthsSinceCliff == 0) {
            // Still in first month after cliff, nothing vested yet
            vestedAmount = 0;
        } else if (monthsSinceCliff == 1) {
            // Month 1: 16,666,667 tokens
            vestedAmount = 16_666_667 ether;
        } else if (monthsSinceCliff <= 29) {
            // Months 2-29: 16,666,667 + (monthsSinceCliff - 1) * 6,333,333
            vestedAmount = 16_666_667 ether + ((monthsSinceCliff - 1) * 6_333_333 ether);
        } else if (monthsSinceCliff == 30) {
            // Month 30 (final): 16,666,667 + (28 * 6,333,333) + 6,000,000
            vestedAmount = 16_666_667 ether + (28 * 6_333_333 ether) + 6_000_000 ether;
        } else {
            // Month 31+: All tokens (cap at 200M)
            vestedAmount = ECOSYSTEM_TREASURY_MAX_MINTED;
        }

        // Return available (vested - already minted)
        if (vestedAmount <= ecosystemTreasuryTokensMinted) {
            return 0;
        }

        return vestedAmount - ecosystemTreasuryTokensMinted;
    }

    function availableAdvisorsTokens() public view returns (uint256) {
        return _getAvailableTokens(
            ADVISORS_MAX_MINTED,
            ADVISORS_TPS,
            advisorsTokensMinted,
            ADVISORS_CLIFF
        );
    }

    function availableTeamTokens() public view returns (uint256) {
        return _getAvailableTokens(
            TEAM_MAX_MINTED,
            TEAM_TPS,
            teamTokensMinted,
            TEAM_CLIFF
        );
    }

    function availableTGETokens() public view returns (uint256) {
        return _getAvailableTokens(
            TGE_VESTING_AMOUNT,
            TGE_TPS,
            tgeTokensMinted,
            TGE_CLIFF
        );
    }

    function availableLiquidityTokens() public view returns (uint256) {
        return _getAvailableTokens(
            LIQUIDITY_VESTING_AMOUNT,
            LIQUIDITY_TPS,
            liquidityTokensMinted,
            LIQUIDITY_CLIFF
        );
    }

    /**
     * @dev minting functions for each category. Split into individual
     * functions per category for code cleanliness.
     */
    function privateTokenSaleMint(address to_, uint256 amount_) public
    onlyController("PRIVATE_TOKEN_SALE_MINTER") {

        require(availablePrivateSaleTokens() >= amount_,
            "SyndicateOfVigilantesToken: privateTokenSale exceeds AVAILABLE");

        uint256 _newMintedAmount = privateTokenSaleTokensMinted + amount_;

        require(PRIVATE_TOKEN_SALE_MAX_MINTED >= _newMintedAmount,
            "SyndicateOfVigilantesToken: privateTokenSaleMint exceeds MAX");

        privateTokenSaleTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    function playerIncentivesMint(address to_, uint256 amount_) public
    onlyController("PLAYER_INCENTIVES_MINTER") {

        require(availablePlayerIncentivesTokens() >= amount_,
            "SyndicateOfVigilantesToken: playerIncentives exceeds AVAILABLE");

        uint256 _newMintedAmount = playerIncentivesTokensMinted + amount_;

        require(PLAYER_INCENTIVES_MAX_MINTED >= _newMintedAmount,
            "SyndicateOfVigilantesToken: playerIncentivesMint exceeds MAX");

        playerIncentivesTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    function ecosystemTreasuryMint(address to_, uint256 amount_) public
    onlyController("ECOSYSTEM_TREASURY_MINTER") {

        require(availableEcosystemTreasuryTokens() >= amount_,
            "SyndicateOfVigilantesToken: ecosystemTreasury exceeds AVAILABLE");

        uint256 _newMintedAmount = ecosystemTreasuryTokensMinted + amount_;

        require(ECOSYSTEM_TREASURY_MAX_MINTED >= _newMintedAmount,
            "SyndicateOfVigilantesToken: ecosystemTreasuryMint exceeds MAX");

        ecosystemTreasuryTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    function advisorsMint(address to_, uint256 amount_) public
    onlyController("ADVISORS_MINTER") {

        require(availableAdvisorsTokens() >= amount_,
            "SyndicateOfVigilantesToken: advisorTokens exceeds AVAILABLE");

        uint256 _newMintedAmount = advisorsTokensMinted + amount_;

        require(ADVISORS_MAX_MINTED >= _newMintedAmount,
            "SyndicateOfVigilantesToken: advisorsTokensMinted exceeds MAX");

        advisorsTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    function teamMint(address to_, uint256 amount_) public
    onlyController("TEAM_MINTER") {

        require(availableTeamTokens() >= amount_,
            "SyndicateOfVigilantesToken: teamTokens exceeds AVAILABLE");

        uint256 _newMintedAmount = teamTokensMinted + amount_;

        require(TEAM_MAX_MINTED >= _newMintedAmount,
            "SyndicateOfVigilantesToken: teamTokensMinted exceeds MAX");

        teamTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    function tgeMint(address to_, uint256 amount_) public
    onlyController("TGE_MINTER") {

        require(availableTGETokens() >= amount_,
            "SyndicateOfVigilantesToken: tgeTokens exceeds AVAILABLE");

        uint256 _newMintedAmount = tgeTokensMinted + amount_;

        require(TGE_VESTING_AMOUNT >= _newMintedAmount,
            "SyndicateOfVigilantesToken: tgeMint exceeds MAX");

        tgeTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    function liquidityMint(address to_, uint256 amount_) public
    onlyController("LIQUIDITY_MINTER") {

        require(availableLiquidityTokens() >= amount_,
            "SyndicateOfVigilantesToken: liquidityTokens exceeds AVAILABLE");

        uint256 _newMintedAmount = liquidityTokensMinted + amount_;

        require(LIQUIDITY_VESTING_AMOUNT >= _newMintedAmount,
            "SyndicateOfVigilantesToken: liquidityMint exceeds MAX");

        liquidityTokensMinted = _newMintedAmount;

        _mint(to_, amount_);
    }

    // ERC20 "Safe" Functions
    function increaseAllowance(address spender_, uint256 amount_) external 
    returns (bool) {
        uint256 _currAllowance = ERC20.allowance[msg.sender][spender_];
        _approve(msg.sender, spender_, (_currAllowance + amount_));
        return true;
    }

    function decreaseAllowance(address spender_, uint256 amount_) external 
    returns (bool) {
        uint256 _currAllowance = ERC20.allowance[msg.sender][spender_];
        _approve(msg.sender, spender_, (_currAllowance - amount_));
        return true;
    }
}

Tags:
Proxy, Liquidity, Yield, Upgradeable, Factory|addr:0x7fe48897b0ffb36e16de84cfc1bb2b7b2d76abf1|verified:true|block:23517970|tx:0xf336ae6e08da3e796b6f612b4d8dde8eaba5c9b67dbc6ef0039b957524c6aae9|first_check:1759762559

Submitted on: 2025-10-06 16:56:00

Comments

Log in to comment.

No comments yet.