CertiK reviewed Rangers Protocol (Rangersprotocol-CrossContract) on 18 Dec 2024: 16 findings, 0 critical; 7 marked fixed, 5 acknowledged, 4 open.
Report hosted on skynet.certik.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 3 | 1 |
| Medium | 0 | 2 | 2 |
| Low | 4 | 0 | 4 |
In the contract `CrossContractEx` the role `_owner` has authority over the function shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and: - `ChangeMutisign_CM`, to set the `g_MutiSignContract_CM`  In the contract `CrossContractEx` the role `g_Parent` has authority over the functions shown in the diagram below. Any compromise to the `g_Parent` account may allow the hacker to take advantage of this authority and: - `TryownerOf`, to check whether the owner of `_nftid` is the parameter `owneraddr`. - `FormatDecimal`, to convert the amount to the target decimal. - `VerifyCrossErc20Sign`, to verify the sign. - `VerifyCrossErc20Sign2`, to verify the sign. - `VerifyCrossErc721Sign_batch`, to batch verify the sign. - `VerifyCrossErc1155Sign`, to verify the sign. - `DoCross1155_CM`, to check whether the `_fromaddr` approve the `g_Parent` contract for the ERC1155 tokens. - `WithdrawErc1155_CM`, to verify the sign.  In the contract `CrossContract` the role `g_Setter` has authority over the functions shown in the diagram below. Any compromise to the `g_Setter` account may allow the hacker to take advantage of this authority and: - `init`, to set the values of sensitive state variables initially. - `AddPoolFts`, to add an address to the `g_pool_fts` array. - `DelPoolFts`, to set an existing address to zero address in the `g_pool_fts` array. - `SetEventCfg`, to set the `g_EventConfigContract`. - `SetCrossEx`, to set the `g_CrossEx`.  In the contract `EventConfig` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and: - `AddCfg`, to add a new cfg to the `g_Events` array. - `DelCfg`, to set one cfg in the `g_Events` array to empty.  In the contract `MutiSign_CM` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and: - `DelCheckGroup`, to remove an existing address from the `g_CheckAddrs` array. - `SetGroupId`, to add or modify a groupId in the `g_CheckAddrs` array. The role `g_CheckAddrs[0]` has authority over the function `AddCheckGroup` to add other addresses to the `g_CheckAddrs` array.  In the contract `MutiSign` the role `_owner` has authority over the function shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and: - `updateCheckAddr`, to update the `g_CheckAddr` address.  In the contract `Ownable` the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and: - `transferOwnership`, to transfer ownership to newOwner. - `renounceOwnership`, to renounce the ownership. 
The `MutiSign_CM`, `EventConfig`, and `CrossContractEx` are upgradable contracts, therefore centralized roles have the authority to update the implementation contracts of their proxy contracts. Any compromise to those centralized roles account may allow a hacker to take advantage of this authority and change the implementation contracts and therefore execute potential malicious functionality.
The function on the specified line is responsible for modifying critical or sensitive contract variables. However, it lacks access restrictions, allowing anyone to call it. This vulnerability can be exploited by malicious actors to perform unauthorized modifications. ```solidity=860 function init(address owner,address groupid) external { require(owner != address(0) ,'init para owner err'); initOwner(owner); g_CheckAddrs.push(groupid); g_Expired[groupid] = block.timestamp+3153600000; //86400*365*100,100 years } ``` In the `CrossContract`, if the `g_MutiSignContract` is not zero address, only the `g_Setter` can call the `init` function. However, if the `g_MutiSignContract` is zero address, it lacks access restrictions, allowing anyone to call it. ```solidity=1107 function init(string memory _name,address payable _addr,address _setter,address payable _feeaddr,address payable _rpg,address _muti_cm,address ec,address ex) public { require(bytes(_name).length > 0 ,'must has name'); require(_addr != address(0) ,'_addr'); require(_setter != address(0) ,'_setter'); require(_feeaddr != address(0) ,'_feeaddr'); if(address(g_MutiSignContract)!=address(0)) { require(msg.sender == g_Setter, 'init not setter calling'); } g_Name = _name; g_MutiSignContract = MutiSign(_addr); g_Setter = _setter; g_FeeAddr = _feeaddr; g_RPG = _rpg; g_MutiSignContract_CM = MutiSign_CM(_muti_cm); g_BusiName = "Bridge"; g_EventConfigContract = EventConfig(ec); g_CrossEx = CrossContractEx(ex); emit event_init(_name,_addr,_setter,_feeaddr); } ``` The `init()` function in the `EventConfig` contract shares the same issue.
The `initOwner` function in the Ownable contract is rendered unusable under normal circumstances due to conflicting logic in its implementation: ### Initial Owner Already Set in Constructor: The `_owner` is assigned to the deployer in the constructor. The `initOwner` function requires `_owner` to be address(0) to execute successfully, making it incompatible with the constructor's behavior. ### Risk After Renouncing Ownership: If the deployer renounces ownership to set `_owner` to address(0), the `initOwner` function becomes callable by anyone, allowing unauthorized parties to take over ownership. ### Dependencies in Other Contracts: The `initOwner` function is intended for use in the `init` functions of other contracts like `MultiSign_CM` and `CrossContractEx`. However, it cannot function correctly without renouncing ownership, creating a flawed design dependency. If these contracts will be deployed by proxy, pay attention to the front run risk.
There is no storage gap preserved in the logic contract. Any logic contract that acts as a base contract that needs to be inherited by other upgradeable child should have a reasonable size of storage gap preserved for the new state variable introduced by the future upgrades.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (1)
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us