Contract Details

What exactly does QMatic do?

Beware of Scammers, QPoker's team never ask your wallet private key or extra information about you.

$QMatic is using AccessControl strategy to create roles, it's public data and you can check which wallet address has the accessibility to the $QMatic.

$QMatic Smart Contract

  • Polygon Mainnet : ( Coming soon).

  • Github Repository: QPokerLTD/QMatic.

  • Audit Paper: (Coming soon).

  • Audit Company: (Coming soon).

  • Solidity Versions: ^0.8.9, ^0.8.0, ^0.8.1 .

  • Solidity Compiler Version: 0.8.17 .

  • Optimizer runs: 200.

List of Smart Contracts and interfaces use for $QMatic:

QPokerToken.sol

This contract inherited from ERC20, ERC20Burnable, Pausable, AccessControl .

Stored Variables:

bytes32 public constant TOKEN_MECHANISM_MANAGER

this variable is related to the AccessControl contract and it contains the valuation of keccak256("TOKEN_MECHANISM_MANAGER");

Mechanism Manager is the access of QPoker economy team to change the state of mechanism that used in the $QMatic contract, we describe it fully on ERC20.sol file.

bytes32 public constant ECONOMIC_MANAGER

this variable is related to the AccessControl contract and it contains the valuation of keccak256("ECONOMIC_MANAGER");

also in the economy team there is a Key member who decides at the final for minting the token.

bytes32 public constant QPOKER_ORACLE

this variable is related to the AccessControl contract and it contains the valuation of keccak256("QPOKER_ORACLE")

QPoker Oracle is the access of QPoker Automated Service named Oracle, this service has the access to manage the $QMatic ecosystem.

Functions:

function pause() public onlyRole(TOKEN_MECHANISM_MANAGER)

Token Mechanism manager can pause the contract in order to change the state of current used mechanism in the contract.

pause will lock all the token transfers (get more information on ERC20.sol)

more information about pause system is available on Pausable.sol (See on OpenZeppelin)

function unpause() public onlyRole(TOKEN_MECHANISM_MANAGER)

Token Mechanism manager can pause the contract in order to change the state of current used mechanism in the contract.

unpause will unlock the previous locking state of contract.

more information about pause system is available on Pausable.sol (See on OpenZeppelin)

function mint(address to, uint256 amount) public onlyRole(ECONOMIC_MANAGER)

QPoker project will mint the tokens step by step, we won't release all the $QMatic tokens at the begining and every minting transaction will be detailed in QPoker Oracle service.

also every minting events will announced in QPoker Telegram Channel.

function _beforeTokenTransfer( address from, address to, uint256 amount) internal override whenNotPaused

As OpenZeppelin said:

" 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 Using Hooks. "

and we used this function to just putting the rule of whenNotPaused and this function is required that not paused state.

function _beforeChangeMechanism() internal override onlyRole(TOKEN_MECHANISM_MANAGER)

At this time this hook is used just to verify that the sender must be TOKEN_MECHANISM_MANAGER .

function _beforeWalletRelatedAction() internal override onlyRole(QPOKER_ORACLE)

At this time this hook is used just to verify that the sender must be QPOKER_ORACLE .

ERC20.sol

This file contains all the abilities of $QMatic token and it inherited from Context, IERC20, IERC20Metadata.

Structures:

WalletInformationAndStatus
struct WalletInformationAndStatus {
    uint256 id;
    bool is_lock;
    uint256 locked_balance;
}
  • uint256 id : every wallet has an assigned id, it's a part of our business logic in oracle service.

  • bool is_lock : If this attribute has the valuation equal to true , the mapped wallet address cannot transfer any of his $QMatic.

  • uint256 locked_balance : this attribute will clarify the amounts of locked token in a wallet, based on QPoker whitepaper everyone who bought token in got token in Pre-sale Round phase or Seed Round phase have a vesting schedule,also the people who got winning prize in airdrop events will have a vesting schedule and at the end of each campaign the schedule will be announced.

locked_balance value will change by the Oracle service during the time and everyone can notice it from their panel.

ActiveMechanism
struct ActiveBurningMechanism {
    bool is_active;
    address treasury_middleman;
    uint256 treasury_share_in_part_of_decimal;
    uint256 burn_share_in_part_of_decimal;
    uint256 total_mechanism_share_in_part_of_decimal;
    uint256 share_cap_in_token;
    uint256 total_share_decimal;
    uint256 each_share_decimal;
}
  • bool is_active : describes that is QPoker project activated the mechanism or not

  • address treasury_middleman : describes the address of the treasury, it can be a automated wallet or Smart Contract. and the treasury strategy will be announced in QPoker Official Telegram Channel.

  • uint256 treasury_share_in_part_of_decimal : based on total share that will be calculated by total_mechanism_share_in_part_of_decimal or share_cap_in_token, Smart Contract will calculate amount of $QMatic that should transfer to the treasury on every transaction.

  • uint256 burn_share_in_part_of_decimal : based on total share that will be calculated by total_mechanism_share_in_part_of_decimal or share_cap_in_token, Smart Contract will calculate amount of $QMatic that should burn on every transaction.

  • uint256 total_mechanism_share_in_part_of_decimal : describes the amount of token that mechanism affects on that.

  • uint256 share_cap_in_token : if calculated part of the transfer amount went greater than the share_cap_in_token the amount of affected by mechanism will change to the share_cap_in_token.

  • uint256 total_share_decimal : in solidity we don't have decimals so if project decides to affect on 0.1% of the transactions total_share_decimal will be equaled to 1000 and the affected amount will calculated by this formula => affected_amount = (transfer_amount * total_mechanism_share_in_part_of_decimal)/total_share_decimal

  • uint256 each_share_decimal : in solidity we don't have decimals so if project decides to burn on 0.01% of the affected share, total_share_decimal will be equaled to 1000 and the burn amount will calculated by this formula => burn_amount = (affected_amount * burn_share_in_part_of_decimal)/each_share_decimal and the rest of 99.99% of treasury share will transfer to treasury

Stored Variables:

_totalSupply
uint256 private _totalSupply;

Describes total minted token by the smart contract and the FUNCTIONNAME will returns the amount of _totalSupply

more information is available at here.

_cap
uint256 private immutable _cap;

to avoiding of minting token more than we describe in the QPoker Whitepaper we created this variable and it will be checked on every minting event and the amount of minting + the amount of total supply must be equal or lower than the _cap

_name
string private _name;

Stores the name of the token for this project it's "QPoker Token"

more information is available at here.

_symbol
string private _symbol;

Stores the symbol of the token => for this project it's "QMatic"

more information is available at here.

_mechanism
ActiveMechanism private _mechanism;

it will stores the mechanism of the smart contract.

more information is available at here.

_wallet_id_counter
uint256 private _wallet_id_counter = 1;

Safe counter to assign the id to each new wallet.

more information is available at here.

_whiteListZeroMechanism
mapping(address => bool) private _whiteListZeroMechanism;

every transfers of $QMatic will happened between two wallets and in this scenario we called it from wallet and to wallet, if one of them exists in the _whiteListZeroMechanism, the mechanism will not affect on that transaction.

for example: the game platform contract address is one of the items in the _whiteListZeroMechanism, and the transactions to/from the gameplatform doesen't have any affects of mechanism. also for some of the exchanges that we announce the list of them in QPoker Oracle.

_wallets
mapping(address => WalletInformationAndStatus) private _wallets;

contains list of wallet addresses with the information that we described in here.

_balances
mapping(address => uint256) private _balances;

Stores the balance value of each wallet address

more information is available at here.

_allowances
mapping(address => mapping(address => uint256)) private _allowances;ol

Stores 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.

Functions:

function cap() public view returns (uint256)

returns the stored value in _cap variable.

function incrementWalletId() internal

increments the stored value in _wallet_id_counter by 1.

function approveNewWallet(address account) internal

this function will add the account value from argument to the _wallets , increments wallet id and announced it with WalletId event.

function lockWalletByAdmin(address account) public

this function will executed by the QPOKER_ORACLE and locks the target wallet address that got from the argument (account).

this function placed here in order to ban scammers, from the community reports.

function unlockWalletByAdmin(address account) public

this function will executed by the QPOKER_ORACLE and unlocks the target wallet address that got from the argument (account).

function _isWalletLocked(address account) internal view returns (bool)

will check locking state of the wallet address that got from the argument and returns true/false based on the logic.

function getMoreDataFromWallet(address account) public view returns (WalletInformationAndStatus memory)

will returns the WalletInformationAndStatus of the specific wallet address that got from the argument.

function _beforeWalletRelatedAction() internal virtual

executes logic befor any logic in lockWalletByAdmin, unlockWalletByAdmin, addWalletWhiteList, removeWalletFromWhiteList, batchWalletBalanceLock and transferWithVestingSchedule

function addWalletWhiteList(address target) public

adds the target address to the _whiteListZeroMechanism.

function removeWalletFromWhiteList(address target) public

removes the target from the _whiteListZeroMechanism.

function _walletBalanceLock( uint256 qpoker_oracle_id, address account, uint256 amount ) internal

it's will lock amounts of the balance that Oracle mentioned by the arguments.

more information is here.

function batchWalletBalanceLock( uint256[] memory qpoker_oracle_id, address[] memory account, uint256[] memory amount) public

same as _walletBalanceLockbut it will get array of wallets.

NOTE: the first rule of execution the logic in this function is : qpoker_oracle_id.length == account.length == amount.length

function _canTransferToken(address from, uint256 amount) internal view

this Hook will check that _balances[from] - _wallets[from].locked_balance >= amount

function _beforeChangeMechanism() internal virtual

this Hook will execute the logic at the start of updateActiveMecanism, disableActiveMecanism .

function updateActiveMecanism( address treasury_middleman_, uint256 treasury_share_in_percentage_, uint256 burn_share_in_percentage_, uint256 total_mechanism_share_in_percentage_, uint256 share_cap_in_token_ ) public

will update the ActiveMechanism state by the arguments and announce the changed version by MechanismStateevent.

function disableActiveMecanism() public

will disables the ActiveMechanism state by the arguments and announce the changed version by MechanismStateevent.

function getActiveMecanismStatus() public view returns (ActiveMechanism memory)

will returns current ActiveMecanism state.

function activeMechanismProcess( address from, uint256 amount, uint256 accountBalance ) internal returns (uint256)

this function will be called by _transfermethod and calculates the burn and trasury mechanisms, at the end returns the remaining amount for transfer to the _transfer method.

function name() public view virtual override returns (string memory)

returns the stored value in _name variable.

function symbol() public view virtual override returns (string memory)

returns the stored value in _symbol variable.

function decimals() public view virtual override returns (uint8)

returns the decimal of token (it will return 18)

function totalSupply() public view virtual override returns (uint256)

returns the stored value in _totalSupply variable.

function balanceOf(address account) public view virtual override returns (uint256)

returns the current balance of the account .

function transfer(address to, uint256 amount) public virtual override returns (bool)

will transfers specific amount of the $QMatic from the caller to target wallet address.

NOTE: this function will send the tokens by _transfermethod.

function transferWithVestingSchedule( address to, uint256 amount, uint256 block_amount, uint256 oracel_id ) public returns (bool)

this function will used by oracle for transferring the specific amount of token to the target with vesting schedule mechanism.

function allowance(address owner, address spender) public view virtual override returns (uint256)

Returns the amount which _spender is still allowed to withdraw from _owner.

more information here.

function approve(address spender, uint256 amount) public virtual override returns (bool)

Allows _spender to withdraw from your account multiple times, up to the _value amount. If this function is called again it overwrites the current allowance with _value.

more information here.

function transferFrom( address from, address to, uint256 amount ) public virtual override returns (bool)

Transfers _value amount of tokens from address _from to address _to, and MUST fire the Transfer event.

The transferFrom method is used for a withdraw workflow, allowing contracts to transfer tokens on your behalf. This can be used for example to allow a contract to transfer tokens on your behalf and/or to charge fees in sub-currencies. The function SHOULD throw unless the _from account has deliberately authorized the sender of the message via some mechanism.

more information here.

function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool)

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.

more information here.

function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool)

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.

more information here.

function _transfer( address from, address to, uint256 amount ) internal

almost same with the EIP-20 standard but the diffrence is :

this function will executes the _canTransferToken, approveNewWallet and calculates the amount to transfer by the activeMechanismProcess method.

function _burn(address account, uint256 amount) internal virtual

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 _approve( address owner, address spender, uint256 amount ) internal virtual

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 _spendAllowance( address owner, address spender, uint256 amount ) internal virtual

Updates owner s allowance for spender based on spent amount.

Does not update the allowance amount in case of infinite allowance. Revert if not enough allowance is available.

Might emit an Approval event.

function _beforeTokenTransfer( address from, address to, uint256 amount ) internal virtual

Hook that is called before any transfer of tokens. This includes minting and burning.

function _afterTokenTransfer( address from, address to, uint256 amount ) internal virtual

Hook that is called after any transfer of tokens. This includes minting and burning.

Events:

event Transfer(address indexed from, address indexed to, uint256 value);

Emitted when value tokens are moved from one account (from) to another (to).

Note that value may be zero.

event Approval( address indexed owner, address indexed spender, uint256 value );

Emitted when the allowance of a spender for an owner is set by a call to approve. value is the new allowance.

event MechanismState( uint256 event_date, bool is_active, address treasury_middleman, uint256 treasury_share_in_percentage, uint256 burn_share_in_percentage, uint256 total_mechanism_share_in_percentage, uint256 share_cap_in_token);

Emitted when the ActiveMecanism changed.

event WalletTokenLockVesting( uint256 indexed oracle_id, address user, uint256 blocked_amount, uint256 event_date);
event WalletId(uint256 indexed id, address indexed user);

Emitted when new wallet account pushes to the _wallets list.

AccessControl.sol

manages the AccessControls of specific addresses.

Stored Variables:

mapping(bytes32 => address) private _roles;

mapping the bytes of the role name to the address.

bytes32 public constant SUPER_ADMIN_ROLE = keccak256("SUPER_ADMIN");

key of the SUPER_ADMIN_ROLE

bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

key of the default admin.

NOTE: SUPER_ADMIN_ROLE can change DEFAULT_ADMIN_ROLE but DEFAULT_ADMIN_ROLE cannot change SUPER_ADMIN_ROLE.

bool private is_inited = false;

it will be used for initializing the AccessControl , after the initializing finished the stored value of is_inited will change to true .

Modifiers:

modifier onlyRole(bytes32 role)

checks that only user can access to the rest of the logic who mapped in the _roles.

modifier onlyForInit()

only allows to execute the rest of the logics if is_initedwas equal to false.

Functions:

function initRole() public onlyForInit

will sets the admin and superadmin then changes the is_inited to true.

this function depends on the decision of onlyForInit.

function hasRole(bytes32 role, address account) public view returns (bool)

checks the role and the wallet address if the target wallet address has the role this function will return true otherwise it will return false.

function _checkRole(bytes32 role) internal view

checks the role of the transaction sender address.

function getAdmin() public view returns (address)

will returnes the address of DEFAULT_ADMIN_ROLE.

function getSuperAdmin() public view returns (address)

will returns the address of SUPER_ADMIN_ROLE.

function grantRole(bytes32 role, address account) public onlyRole(DEFAULT_ADMIN_ROLE)

super admin can grant the role to the address.

function revokeRole(bytes32 role, address account) public onlyRole(SUPER_ADMIN_ROLE)

super admin can revoke the assigned role from a wallet address.

Last updated