Overview

GBM Contract
Rank #N/A

Skynet Trust Score

100%
  • Project is Relatively Decentralized
  • Large Market Cap (top 25%)
  • Long-running Project
  • Trust Score is #1 amongst all projects
Security Score
100 / 100
Market & Community
/ 100

GBM Contract Info

GC Scan is the ultimate blockchain tool, revolutionizing the way you interact with decentralized networks. This innovative platform seamlessly combines the power of smart contracts with advanced analytics and an intuitive block explorer, offering you an all-in-one solution for your blockchain exploration and analysis needs.

Audits

Onboarded Date

28/Sep/2023

Contracts

0xbB7...8a3A1

How do you feel about this project's security?
Documents
File Name Type Size Upload Date Action
Zip File 4.57 MB 12 Dec 2021
PDF File 8.89 MB 24 Nov 2021
MP4 File 14.62 MB 19 Nov 2021
XSL File 2.38 KB 14 Nov 2021
Floder File 87.24 MB 08 Nov 2021
PNG File 879 KB 02 Nov 2021
Activities
Oliver Phillips New

We talked about a project on linkedin.

Today
N
Nancy Martino In Progress

Create new project Buildng product

Yesterday
Natasha Carey Completed

Adding a new event with attachments

25 Nov
Bethany Johnson

added a new member to velzon dashboard

19 Nov
Your order is placed Out of Delivery

These customers can rest assured their order has been placed.

16 Nov
Lewis Pratt

They all have something to say beyond the words on the page. They can come across as casual or neutral, exotic or graphic.

22 Oct
Monthly sales report

2 days left notification to submit the monthly sales report. Reports Builder

15 Oct
New ticket received Completed

User Erica245 submitted a ticket.

26 Aug
Nancy Martino

Team Leader & HR

225

Projects

197

Tasks

HB
Henry Baird

Full Stack Developer

352

Projects

376

Tasks

Frank Hook

Project Manager

164

Projects

182

Tasks

Jennifer Carter

UI/UX Designer

225

Projects

197

Tasks

ME
Megan Elmore

Team Leader & Web Developer

201

Projects

263

Tasks

Alexis Clarke

Backend Developer

132

Projects

147

Tasks

NC
Nathan Cole

Front-End Developer

352

Projects

376

Tasks

Joseph Parker

Team Leader & HR

64

Projects

93

Tasks

Erica Kernan

Web Designer

345

Projects

298

Tasks

DP
Donald Palmer

Wed Developer

97

Projects

135

Tasks

Showing 1 to 10 of 12 entries

Code Audit History

1 Audit available
Last Audit was delivered on 03 April 2024

GBM Contract -Audit

View Findings
5

All Findings

0

Acknowledge

0

Partially

5

Resolved

0
Critical none
0
Major none
1
Medium privilege
2
Minor privilege
0
Optimization none
2
Informational privilege
0
Discussion none

Method

Audited Files/SHA256

Contracts

0xbB742D764c...8a3A1

Manual Review Static Analysis
Audit Timeline
Requested on
28 September 2023
Revisioned on
03 April 2024

Formal Verification Result

9 / 38 Properties True
80%

Token Standard

ERC-20

Functions

6

Verified Contract

GBM Contract (GBMContract.sol) 1

GBM Contract Smart Contract Code

                        
                        

    // pragma solidity ^0.8.7;


contract Initializable {


    bool private _initialized;


    bool private _initializing;


    modifier initializer() {

        require(_initializing || !_initialized, "Initializable: contract is already initialized");


        bool isTopLevelCall = !_initializing;

        if (isTopLevelCall) {

            _initializing = true;

            _initialized = true;

        }

        _;


        if (isTopLevelCall) {

            _initializing = false ;

        }

    }

}


 contract GlobalCoinStaking is Initializable   {


    address public owner;

    address public adminreferal;

    uint256 public Idprovider;

    uint256 public returnPercent ; // in days

    uint256 public timeForStaking ; // sec

    uint256 [] public ReferalPercent ;

    uint256 public totalStaking;

    uint256 public totalReferalRewarded;

    uint256 public userDirectPercent;



    struct userDetail{

        uint256 userId;

        // address userAddress;

        uint256 totalDirects;

        uint256 totalRefralIncome;

        uint256 totalClaim;

        address userReferalAddress;

        uint256 userReferalID;

    


        // uint256 userTotalPurchased;



    }

    struct userStakingDetail{

        uint256 amountStaked;

        uint256 timeOfstaking;

        uint256 userLastTimeClaimed;

        uint256 endTimeofStaking;

        uint256 stakePercent;

        bool isStaked;


    }

        

    mapping(uint256 => address) public idToAddress;

    mapping(address => uint256) public AddressToId;    

    mapping(address => bool) public  isUserExist;

    mapping(address => userDetail) public UserData;

    mapping(uint256 => uint256 ) public  returnValue;

    mapping(address => userStakingDetail)public UserStakingData; 

    

    modifier onlyOwner() {

        require(msg.sender == owner,"not Owner");

        _;

    }


    event adminReferalChange(address NewReferal,uint256 time);

    event register(address user , uint256 time ,address refAddress);

    event stakingEvent(address user , uint256 amount , uint256 time ,uint256 returnPercnt, address refAddress );

    event userClaimedRecord(address user , uint256 amount , uint256 time );

    event refralInfo(address user, address referalAddress , uint256 time, uint256 amount,uint256 level);

    event levelIncomeClaimed(address user, uint256 amount, uint256 time);


 

    function initialize(address _owner) external initializer { 


        adminreferal = 0xEF8a958d1730AaE4025E543bA7F44Dc1A7A73D60; /// custom id can be changed 

        UserData[adminreferal].userId = 1;  

        idToAddress[1] = adminreferal ;

        isUserExist[adminreferal] =true;

        returnPercent = 300;

        timeForStaking = 51840000;

        owner = _owner;

        Idprovider=2;

        ReferalPercent =  [120,100,50,40,30,20,10,5,5,5,5,5,5,10,10,10,10,10,10,10,10,10,10,20,30];

        returnValue[0]=0;

        returnValue[1]=3;

        returnValue[2]=3;

        returnValue[3]=5;

        returnValue[4]=5;

        returnValue[5]=5;

        returnValue[6]=5;

        returnValue[7]=7;

        returnValue[8]=7;

        returnValue[9]=7;

        returnValue[10]=7;

        returnValue[11]=7;

        returnValue[12]=10;

        returnValue[13]=10;

        returnValue[14]=10;

        returnValue[15]=10;

        returnValue[16]=10;

        returnValue[17]=10;

        returnValue[18]=15;

        returnValue[19]=15;

        returnValue[20]=15;

        returnValue[21]=15;

        returnValue[22]=15;

        returnValue[23]=15;

        returnValue[24]=15;


        userDirectPercent = 5;


    }


    function changeAdminReferalId(address adr) public onlyOwner {


        adminreferal =adr;

        emit adminReferalChange(adr,block.timestamp);

        

    } 

    

    function stakeGlobalCoin(uint256 amount , address refAddresss) public payable {


        if(UserStakingData[msg.sender].amountStaked > 0){

           uint256 max =  (UserStakingData[msg.sender].amountStaked*300)/100;

             if(UserData[msg.sender].totalClaim <= max){

                revert("Please Claim Previous Amount");

             }

        }

      

        require(UserStakingData[msg.sender].isStaked!= true ,"already in staked");


        require(amount>0," Amount Zero");

        require(isUserExist[refAddresss] == true,"Referal Not Found");

        require(msg.value==amount,"Invalid Amount" );

        

        if(UserData[msg.sender].userReferalAddress == address(0) && UserData[msg.sender].userReferalID == 0 ){

            UserData[msg.sender].userReferalAddress = refAddresss;

            UserData[msg.sender].userReferalID = AddressToId[refAddresss];

            UserData[refAddresss].totalDirects++;


                if (refAddresss != address(0)){  

                        if(UserData[refAddresss].totalDirects >= returnValue[0]){

                        UserData[refAddresss].totalRefralIncome += ((amount * userDirectPercent)/100); 

                        emit refralInfo(msg.sender,refAddresss,block.timestamp,((amount * userDirectPercent)/100),0);

                        totalReferalRewarded+=  ((amount * userDirectPercent)/100);

                        }

                

                  }


        }

       

       


        if(UserData[msg.sender].userId==0){

            UserData[msg.sender].userId=Idprovider;

            idToAddress[Idprovider]=msg.sender;

            AddressToId[msg.sender]=Idprovider;

            isUserExist[msg.sender]=true;

            emit register(msg.sender,block.timestamp,refAddresss);

            Idprovider++;

               

        }

        

       

        UserStakingData[msg.sender].amountStaked = amount;

        UserStakingData[msg.sender].timeOfstaking = block.timestamp;

        UserStakingData[msg.sender].userLastTimeClaimed= block.timestamp;

        UserStakingData[msg.sender].endTimeofStaking = block.timestamp+timeForStaking;

        UserStakingData[msg.sender].stakePercent= returnPercent;

        UserStakingData[msg.sender].isStaked = true;


        

        

  


        emit stakingEvent(msg.sender,amount,block.timestamp,returnPercent,refAddresss);


        totalStaking++;


        // address ref; 

        // ref = UserData[msg.sender].userReferalAddress;

        // for(uint256 i = 0 ; i < 25; i++){


        

    }

    

    function calculateRoi(address useraddress) public view returns(uint256) {


        uint256 returnAmount;

         if(UserStakingData[msg.sender].amountStaked > 0){

           uint256 max =  (UserStakingData[msg.sender].amountStaked*300)/100;

            if(  UserStakingData[msg.sender].isStaked == true){

                    if(UserData[msg.sender].totalClaim < max){

                        

                        if (UserStakingData[useraddress].endTimeofStaking >= block.timestamp){

                        uint256 time = block.timestamp - UserStakingData[useraddress].userLastTimeClaimed;

                        uint256 perSecPercent = ((UserStakingData[useraddress].amountStaked * UserStakingData[useraddress].stakePercent) /100) / timeForStaking;

                        returnAmount += time * perSecPercent;

                        } 

                            else if (UserStakingData[useraddress].endTimeofStaking < block.timestamp){

                                uint256 time = UserStakingData[useraddress].endTimeofStaking;

                                if (time > UserStakingData[useraddress].userLastTimeClaimed) {

                                    time =time - UserStakingData[useraddress].userLastTimeClaimed;

                                }

                                else {

                                    time = 0;

                                }

                                    uint256 perSecPercent = ((UserStakingData[useraddress].amountStaked * UserStakingData[useraddress].stakePercent) /100) / timeForStaking; 

                                        returnAmount += time * perSecPercent;    


                            }  

                    }       

                         return  returnAmount;

                    

            }

                else{

                     return 0 ;

                }

     }

         }



    function claimRoi() public {

     require(msg.sender != adminreferal,"This type of call can be done by users Only ,check: claimReferalIncomeOnlyForAdminRefralId ");

     uint256  checker =  checkUserMax();

     uint256 amountToClaim  = calculateRoi(msg.sender);

     uint256 toCliam =  amountToClaim + UserData[msg.sender].totalRefralIncome;  


        if(toCliam<=checker){ 

        uint256 adminFees =  (toCliam*5)/100 ;

        uint256 AfterdeductingFees = toCliam-adminFees;

            payable(msg.sender).transfer(AfterdeductingFees);

            UserStakingData[msg.sender].userLastTimeClaimed= block.timestamp;

            emit  userClaimedRecord(msg.sender,amountToClaim,block.timestamp); 

            emit levelIncomeClaimed(msg.sender,UserData[msg.sender].totalRefralIncome,block.timestamp);

            UserData[msg.sender].totalClaim += toCliam;



          // roi of roi  of upper level income trnasfer



        address ref; 

        ref = UserData[msg.sender].userReferalAddress;

        for(uint256 i = 0 ; i < 25; i++){

            if (ref != address(0)){  

                if(UserData[ref].totalDirects >= returnValue[i]){

                   UserData[ref].totalRefralIncome += ((amountToClaim * ReferalPercent[i])/100)/10; 

                   emit refralInfo(msg.sender,ref,block.timestamp,((amountToClaim * ReferalPercent[i])/100)/10,i);

                   totalReferalRewarded+=  ((amountToClaim * ReferalPercent[i])/100)/10;

                }

            }

            ref = UserData[ref].userReferalAddress;

            if (ref == address(0))

                break;

                

        }



            UserData[msg.sender].totalRefralIncome =0;

        } else if(toCliam > checker){

            

             uint256 adminFees =  (checker*5)/100 ;

             uint256 AfterdeductingFees = checker-adminFees;

             

            payable(msg.sender).transfer(AfterdeductingFees);

            UserStakingData[msg.sender].userLastTimeClaimed= block.timestamp;

            emit  userClaimedRecord(msg.sender,amountToClaim,block.timestamp); 

            emit levelIncomeClaimed(msg.sender,UserData[msg.sender].totalRefralIncome,block.timestamp);


        // roi of roi  of upper level income trnasfer


            address ref; 

             ref = UserData[msg.sender].userReferalAddress;

                for(uint256 i = 0 ; i < 25; i++){

                    if (ref != address(0)){  

                        if(UserData[ref].totalDirects >= returnValue[i]){

                        UserData[ref].totalRefralIncome += ((amountToClaim * ReferalPercent[i])/100)/10; 

                        emit refralInfo(msg.sender,ref,block.timestamp,((amountToClaim * ReferalPercent[i])/100)/10,i);

                        totalReferalRewarded+=  ((amountToClaim * ReferalPercent[i])/100)/10;

                        }

                    }

                    ref = UserData[ref].userReferalAddress;

                    if (ref == address(0))

                        break;

                        

                }




            UserData[msg.sender].totalClaim += checker;

            UserData[msg.sender].totalRefralIncome =0;

            

        }   



        checkUserMax();

    }



    function checkUserMax() private  returns(uint256) {

        

        uint256 max =  (UserStakingData[msg.sender].amountStaked*300)/100;

        

        if(UserData[msg.sender].totalClaim >= max){

                UserStakingData[msg.sender].amountStaked = 0;

                UserStakingData[msg.sender].timeOfstaking =0;

                UserStakingData[msg.sender].userLastTimeClaimed=0;

                UserStakingData[msg.sender].endTimeofStaking =0;

                UserStakingData[msg.sender].stakePercent = 0;

                UserData[msg.sender].totalClaim=0;

                UserStakingData[msg.sender].isStaked = false;

                return 0;

        }else{

                return max-UserData[msg.sender].totalClaim;

        }

        


    } 


    function rescueCoinFormContract(uint256 amt) public onlyOwner{

        require(address(this).balance >= amt, "insufficient contract balance");

        payable(msg.sender).transfer(amt);

    }

    function changeOwnerAddress(address _ownerAddress) public onlyOwner { 

        owner = _ownerAddress;

    } 

    function changeStakingTimePeriodForNewUser(uint256 timeInSeconds) public onlyOwner{

        timeForStaking = timeInSeconds ;

    }

   

    // function claimLevelIncentive() public {

        

    //  require(UserData[msg.sender].totalRefralIncome > 0,"Balance 00");

    //  payable(msg.sender).transfer(UserData[msg.sender].totalRefralIncome);

    //  emit levelIncomeClaimed(msg.sender,UserData[msg.sender].totalRefralIncome,block.timestamp);

    //  UserData[msg.sender].totalRefralIncome =0;


    // } 

    function UpdateArrayValue(uint256 index , uint256 value ) public onlyOwner {

        ReferalPercent[index] = value;

    } 

    function newArrayValue( uint256 value ) public onlyOwner {

        ReferalPercent.push(value);

    } 

    function upateReferalReq( uint256 key,uint256 value ) public onlyOwner {

        returnValue[key] =value;     

    } 

    receive() external payable {

    }

    function claimReferalIncomeOnlyForAdminRefralId () public onlyOwner{

         require(UserData[adminreferal].totalRefralIncome>0,"Balance Zero 00 ");

         payable(owner).transfer(UserData[adminreferal].totalRefralIncome);

         UserData[adminreferal].totalRefralIncome =0;

    }

   

 }

Code Audit Findings

Audits Overview

Context
Project Name
GBM Contract
Platform
Language
Codebase
Commit
About Xamer Audits
Delivery Date
Audit Methodology
Core Components
Vulnerability Summary
VULNERABILITY LEVEL PENDING DECLINED ACKNOWLEDGED PARTIALLY RESOLVED MITIGATED RESOLVED TOTAL
Critical 0 0 0 0 0 0 0
Major 0 0 0 0 0 0 0
Medium 0 0 0 0 0 1 1
Minor 0 0 0 0 0 2 2
Optimization 0 0 0 0 0 0 0
Informational 0 0 0 0 0 2 2
Discussion 0 0 0 0 0 0 0
Review Notes

Overview

The provided Solidity code defines a smart contract, named `GlobalCoinStaking`, which facilitates a staking and referral system. Users can stake a specified amount of a token (GlobalCoin), and the contract calculates the return on investment (ROI) based on the staking duration. Additionally, users can earn referral rewards, and the contract owner has exclusive functions, such as adjusting parameters, updating arrays, and rescuing funds.

The code employs structs, mappings, modifiers, and events to organize and log user and staking information. It is important to thoroughly test and audit the contract for security considerations before deployment on the blockchain.

Privileged Roles

In the provided Solidity code, the following privileged roles and their associated functionalities are identified:

Owner:

  • The `owner` is the contract owner with special privileges.
  • Functions restricted to the owner include `onlyOwner` modifier, allowing exclusive access to certain critical operations like changing the admin referral ID, updating array values, changing the owner's address, and rescuing funds from the contract.

Admin Referal:

  • The `adminreferal` address is designated for administrative referral purposes.
  • The `changeAdminReferalId` function allows the owner to change the admin referral address.

Initialization:

  • The `initialize` function is an initializer function that sets up the initial state of the contract. It can only be called once during contract deployment and is typically called by the owner.

These privileged roles are essential for the proper functioning and maintenance of the contract. The owner, in particular, has control over critical aspects, providing the ability to update parameters, manage addresses, and handle emergencies through functions like `rescueCoinFormContract`. It is crucial to ensure that these roles are responsibly managed and secure to prevent unauthorized access and potential vulnerabilities.

Audits Scope

ID FILE SHA256 CHECKSUM
GBM GBMContract.sol 2F50DD71FB722717B70C497C3C99D4EBAC99C5BDDC56CEFB17F3D89F7F2FDAB8

GBM-01 | Ethical Consideration

CATEGORY SEVERITY LOCATIONS STATUS
privilege Informational

 function rescueCoinFormContract(uint256 amt) public onlyOwner{

        require(address(this).balance >= amt, "insufficient contract balance");

        payable(msg.sender).transfer(amt);

    }

RESOLVED
Description

Location in code: Inside the  function rescueCoinFormContract(uint256 amt) public onlyOwner{
Line number: 608-614
Description:
The rescueCoinFormContract function allows the contract owner to rescue funds, which may raise ethical considerations. Ensure that the intention aligns with the contract's purpose and user expectations.

GBM-02 | Limited Access Control

CATEGORY SEVERITY LOCATIONS STATUS
privilege Minor

 modifier onlyOwner() {

        require(msg.sender == owner,"not Owner");

        _;

    }

RESOLVED
Description

Location in code: Inside the onlyOwner modifier
Line number: 127-133
Description:
The onlyOwner modifier is used to restrict access to certain functions, but additional access controls, such as role-based access or multi-signature schemes, could enhance security.

GBM-03 | Unprotected Ether Transfer

CATEGORY SEVERITY LOCATIONS STATUS
privilege Medium

 function stakeGlobalCoin(uint256 amount , address refAddresss) public payable {
     if(UserStakingData[msg.sender].amountStaked > 0){
    uint256 max =  (UserStakingData[msg.sender].amountStaked*300)/100;
    if(UserData[msg.sender].totalClaim <= max){
      revert("Please Claim Previous Amount"); }
            }
require(UserStakingData[msg.sender].isStaked!= true ,"already in staked");
 require(amount>0," Amount Zero");
 require(isUserExist[refAddresss] == true,"Referal Not Found");
 require(msg.value==amount,"Invalid Amount" );
 if(UserData[msg.sender].userReferalAddress == address(0) && UserData[msg.sender].userReferalID == 0 ){
  UserData[msg.sender].userReferalAddress = refAddresss;
   UserData[msg.sender].userReferalID = AddressToId[refAddresss];
   UserData[refAddresss].totalDirects++;
     if (refAddresss != address(0)){  
  if(UserData[refAddresss].totalDirects >= returnValue[0]){
UserData[refAddresss].totalRefralIncome += ((amount * userDirectPercent)/100);
emit refralInfo(msg.sender,refAddresss,block.timestamp,((amount * userDirectPercent)/100),0);
  totalReferalRewarded+=  ((amount * userDirectPercent)/100);  }
                     }
             }
 if(UserData[msg.sender].userId==0){
    UserData[msg.sender].userId=Idprovider;
     idToAddress[Idprovider]=msg.sender;
   AddressToId[msg.sender]=Idprovider;
        isUserExist[msg.sender]=true;
      emit register(msg.sender,block.timestamp,refAddresss);
          Idprovider++; }
UserStakingData[msg.sender].amountStaked = amount;
 UserStakingData[msg.sender].timeOfstaking = block.timestamp;
 UserStakingData[msg.sender].userLastTimeClaimed= block.timestamp;
 UserStakingData[msg.sender].endTimeofStaking = block.timestamp+timeForStaking;
 UserStakingData[msg.sender].stakePercent= returnPercent;
 UserStakingData[msg.sender].isStaked = true;
 emit stakingEvent(msg.sender,amount,block.timestamp,returnPercent,refAddresss);
           totalStaking++;
           // address ref;
  // ref = UserData[msg.sender].userReferalAddress;
  // for(uint256 i = 0 ; i < 25; i++){
        }

RESOLVED
Description

Location in code: Inside the function stakeGlobalCoin
Line number: 242-360
Description:
The payable(msg.sender).transfer(AfterdeductingFees) statement may be susceptible to a reentrancy attack. Consider using the ReentrancyGuard modifier or the reentrancyGuard pattern to secure this transfer.

GBM-04 | Potential Integer Overflow

CATEGORY SEVERITY LOCATIONS STATUS
privilege Minor

 function calculateRoi(address useraddress) public view returns(uint256) {
   uint256 returnAmount;
if(UserStakingData[msg.sender].amountStaked > 0){
uint256 max =  (UserStakingData[msg.sender].amountStaked*300)/100;
 if(  UserStakingData[msg.sender].isStaked == true){
 if(UserData[msg.sender].totalClaim < max){
if (UserStakingData[useraddress].endTimeofStaking >= block.timestamp){
uint256 time = block.timestamp - UserStakingData[useraddress].userLastTimeClaimed;
uint256 perSecPercent = ((UserStakingData[useraddress].amountStaked * UserStakingData[useraddress].stakePercent) /100) / timeForStaking;
    returnAmount += time * perSecPercent; }
 else if (UserStakingData[useraddress].endTimeofStaking < block.timestamp){
 uint256 time = UserStakingData[useraddress].endTimeofStaking;
 if (time > UserStakingData[useraddress].userLastTimeClaimed) {
 time =time - UserStakingData[useraddress].userLastTimeClaimed; }
else { time = 0; }
uint256 perSecPercent = ((UserStakingData[useraddress].amountStaked * UserStakingData[useraddress].stakePercent) /100) / timeForStaking;
          returnAmount += time * perSecPercent;     }  
                    }       
    return  returnAmount; }
         else{ return 0 ; }
            }
      }

RESOLVED
Description

Location in code: Inside the function calculateRoi
Line number: 364-428
Description:
The returnAmount variable may be susceptible to integer overflow if the staking amounts or percentages are extremely high. Consider adding checks or using safe math operations.

GBM-05 | Lack of Validation

CATEGORY SEVERITY LOCATIONS STATUS
privilege Informational

function changeStakingTimePeriodForNewUser(uint256 timeInSeconds) public onlyOwner{

        timeForStaking = timeInSeconds ;

    }

RESOLVED
Description

Location in code: Inside the function changeStakingTimePeriodForNewUser
Line number: 622-626
Description:
Changing the staking time period without proper validation may have unintended consequences. Consider adding checks to ensure that the new time period is reasonable and won't negatively impact users.