XYRO - audits

CertiKRepository at commit 0a08cfa

CertiK reviewed XYRO (XYRO - audits) on 10 Jan 2025: 43 findings, 0 critical; 34 marked fixed, 9 open.

No open critical findings
Open the reportOpen XYRO’s security record

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings43

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High303
Medium1010
Low5021
HighCentralization Related RisksOpen

**Important Note:** Certain identification procedures were attempted to be applied to the project team in order to better understand the centralization situation and potential risks of the project. We strongly advise end users to conduct further research and exercise due diligence before engaging with the project given the centralization related risks. It is crucial for end users to independently verify and assess all available information to make informed decisions. ### Treasury #### ACCOUNTANT_ROLE In the contract `Treasury`, the role `ACCOUNTANT_ROLE` has authority over the functions listed below. - withdrawFees() Any compromise to the `ACCOUNTANT_ROLE` account may allow the hacker to take advantage of this authority and withdraw specified fees in a given token. #### DEFAULT_ADMIN_ROLE In the contract `Treasury`, the role `DEFAULT_ADMIN_ROLE` has authority over the functions listed below. - grantRole() - revokeRole() - setToken() - setSetupFee() - withdrawFees() - setUpkeep() - changeMinDepositAmount() Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority and set or unset token approval status, withdraw fees to a specified address, set the setup fee, change the minimum deposit amount, and set the upkeep address. **For example, if the `upkeep` address is not trusted, the game results could be manipulated.** #### DISTRIBUTOR_ROLE In the contract `Treasury`, the role `DISTRIBUTOR_ROLE` has authority over the functions listed below. - setGameToken() - depositAndLock() - depositAndLockWithPermit() - lock() - refund() - refundWithFees() - universalDistribute() - withdrawGameFee() - calculateRate() - withdrawInitiatorFee() - distributeBullseye() - bullseyeResetLockedAmount() - withdrawRakebackSetup() - setGameFinished() Any compromise to the `DISTRIBUTOR_ROLE` account may allow the hacker to take advantage of this authority and set the game token, lock the specified amount in the game account, set the game as finished, reset the locked amount for a game ID, deposit and lock tokens with a permit, withdraw rakeback setup, deposit and lock tokens with a permit, withdraw the initiator fee, refund tokens to a specified address, distribute funds to a specified address, refund amount with fees and conditions, distribute bullseye rewards to a specified address, calculate the rate for a given game ID, and withdraw the game fee and update the collected amount. ### Bullseye #### DEFAULT_ADMIN_ROLE In the contract `Bullseye`, the role `DEFAULT_ADMIN_ROLE` has authority over the functions listed below. - grantRole() - revokeRole() - setMaxPlayers() - setTreasury() - setExactRange() - setFee() - setRate() Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority and set the treasury address, set the rate for specific player configurations, set the fee to a new value, set the maximum number of players, and set the exact range. #### GAME_MASTER_ROLE In the contract `Bullseye`, the role `GAME_MASTER_ROLE` has authority over the functions listed below. - startGame() - finalizeGame() - closeGame() Any compromise to the `GAME_MASTER_ROLE` account may allow the hacker to take advantage of this authority and close the current game, finalize the game and distribute prizes, and start a new game session. ### OneVsOneExactPrice #### DEFAULT_ADMIN_ROLE In the contract `OneVsOneExactPrice`, the role `DEFAULT_ADMIN_ROLE` has authority over the functions listed below. - grantRole() - revokeRole() - changeGameDuration() - setTreasury() - setFee() - setRefundFee() - toggleActive() Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority and set the treasury address, change game duration, toggle the active status, set the fee and emit event, and set the refund fee. #### GAME_MASTER_ROLE In the contract `OneVsOneExactPrice`, the role `GAME_MASTER_ROLE` has authority over the functions listed below. - liquidateGame() - finalizeGame() Any compromise to the `GAME_MASTER_ROLE` account may allow the hacker to take advantage of this authority and liquidate a game if conditions are met, finalize game outcomes, and distribute rewards. ### Setup #### DEFAULT_ADMIN_ROLE In the contract `Setup`, the role `DEFAULT_ADMIN_ROLE` has authority over the functions listed below. - grantRole() - revokeRole() - changeGameDuration() - setTreasury() - setFee() - setInitiatorFee() - toggleActive() Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority and toggle the active state, change the game's duration limits, set the fee and emit event, set the initiator fee, and set the treasury address. #### GAME_MASTER_ROLE In the contract `Setup`, the role `GAME_MASTER_ROLE` has authority over the functions listed below. - closeGame() - finalizeGame() Any compromise to the `GAME_MASTER_ROLE` account may allow the hacker to take advantage of this

HighCentralized Control of Contract UpgradeOpen

In the contract `Treasury`, the admin role has the authority to update the implementation contract behind the proxy contract. Any compromise to the admin account may allow a hacker to take advantage of this authority and change the implementation contract which is pointed by proxy and therefore execute potential malicious functionality in the implementation contract. **Important Note:** Certain identification procedures were attempted to be applied to the project team in order to better understand the centralization situation and potential risks of the project. We strongly advise end users to conduct further research and exercise due diligence before engaging with the project given the centralization related risks. It is crucial for end users to independently verify and assess all available information to make informed decisions.

HighCentralized Withdrawal RiskOpen

In the contract `Treasury`, the role `DISTRIBUTOR_ROLE` has authority over the functions listed below. - setGameToken() - depositAndLock() - depositAndLockWithPermit() - lock() - refund() - refundWithFees() - universalDistribute() - withdrawGameFee() - calculateRate() - withdrawInitiatorFee() - distributeBullseye() - bullseyeResetLockedAmount() - withdrawRakebackSetup() - setGameFinished() Any compromise to the `DISTRIBUTOR_ROLE` account may allow the hacker to take advantage of this authority and directly withdraw tokens from the treasury. --- In the contract `Treasury`, the role `DEFAULT_ADMIN_ROLE` has authority over the functions listed below. - setToken() Any compromise to the `DEFAULT_ADMIN_ROLE` account may allow the hacker to take advantage of this authority and prevent players from withdrawing assets. **Important Note:** Certain identification procedures were attempted to be applied to the project team in order to better understand the centralization situation and potential risks of the project. We strongly advise end users to conduct further research and exercise due diligence before engaging with the project given the centralization related risks. It is crucial for end users to independently verify and assess all available information to make informed decisions.

MediumManipulable Rakeback Calculation Based on Token BOpen

The `calculateRakebackAmount` function calculates the rakeback based on the balance of `xyroToken` held by a user. This approach is vulnerable to manipulation, as users can temporarily transfer `xyroToken` to their account to increase their balance and receive a higher rakeback rate, thus reducing their asset loss. Below is the relevant code snippet: ```solidity function calculateRakebackAmount( address target, uint256 initialDeposit ) public view returns (uint256) { uint256 targetBalance = IERC20(xyroToken).balanceOf(target); if ( targetBalance < rakebackRate[0] * 10 ** IERC20Mint(xyroToken).decimals() ) { return 0; } uint256 rate; for (uint256 i = 10; i > 0; i--) { if ( targetBalance >= rakebackRate[i - 1] * 10 ** IERC20Mint(xyroToken).decimals() ) { rate = i; break; } rate = 0; } return (initialDeposit * rate * 100) / FEE_DENOMINATOR; } ```

LowIncorrect Handling of Top Player Timestamps in `fOpen

In the `finalizeGame` function, there are two issues related to the handling of top player timestamps when determining the winners based on their guess differences. The relevant code snippet is: ```solidity for (uint256 i = 0; i < 3; i++) { if (currentDiff < closestDiff[i]) { for (uint256 k = 2; k > i; k--) { closestDiff[k] = closestDiff[k - 1]; topPlayers[k] = topPlayers[k - 1]; topIndexes[k] = topIndexes[k - 1]; } closestDiff[i] = currentDiff; topPlayers[i] = playerGuessData.player; topTimestamps[i] = playerGuessData.timestamp; topIndexes[i] = j; break; } else if ( currentDiff == closestDiff[i] && playerGuessData.timestamp < topTimestamps[i] ) { for (uint256 k = 2; k > i; k--) { closestDiff[k] = closestDiff[k - 1]; topPlayers[k] = topPlayers[k - 1]; topIndexes[k] = topIndexes[k - 1]; } topIndexes[i] = j; topPlayers[i] = playerGuessData.player; // Missing topTimestamps update break; } } ``` 1. **Issue with Moving Top Player Info:** When shifting the top player information, the `topTimestamps` array is not updated correspondingly. This may lead to incorrect evaluations of timestamp conditions. 2. **Missing Update of `topTimestamps`:** Under the condition `currentDiff == closestDiff[i] && playerGuessData.timestamp < topTimestamps[i]`, the `topTimestamps` array is not updated. This oversight can result in inaccurate timestamp comparisons in subsequent iterations.

LowMissing Emit EventsOpen

There should always be events emitted in the sensitive functions that are controlled by centralization roles.

LowPotential Duplicate Rakeback Calculation for TopOpen

In the `Bullseye` contract, a player can join the game multiple times, and each entry is considered valid. However, during the game's finalization, if a player secures multiple positions within the `topPlayers` array, their rakeback is calculated multiple times. This may result in the winner's rewards inadvertently including portions of the losers' rakeback. This issue, while extreme, can occur under specific conditions. ```solidity for (uint i = 0; i < 3; i++) { if (currentRates[i] != 0) { winnersRakeback += ITreasury(treasury).lockedRakeback( currentGameId, topPlayers[i] ); } }

LowThe game's `createGame()` function does not returOpen

When the game master or a user calls the game's `createGame()` function and successfully creates a game, it does not return the corresponding `gameId`, which is very inconvenient.

LowThird-Party Dependency UsageOpen

The game contracts (`Bullseye`, `UpDown`, `Setup` and `OneVsOneExactPrice`) are serving as the underlying entity to interact with Chainlink data stream protocol. The scope of the audit treats third party entities as black boxes and assumes their functional correctness. However, in the real world, third parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of third parties can possibly create severe impacts, such as increasing fees of third parties, migrating to new LP pools, etc. ```solidity import {IDataStreamsVerifier} from "./interfaces/IDataStreamsVerifier.sol"; ... (int192 startingPrice, uint32 startTime) = IDataStreamsVerifier( ITreasury(treasury).upkeep() ).verifyReportWithTimestamp(unverifiedReport, feedNumber); ``` Besides, the `ITreasury(treasury).upkeep()` should be set as the trusted `DataStreamsVerifier` contract by the `DEFAULT_ADMIN_ROLE` of `Treasury` contract.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (15)

  • https://github.com/xyro-io/smart-contracts/contracts/Setup.sol at commit 0a08cfae3ad04994241553312aa406350ebb3c73
  • https://github.com/xyro-io/smart-contracts/contracts/Treasury.sol at commit 740df06eed24a04f0e739c7c6332466dc6bae295
  • https://github.com/xyro-io/smart-contracts/contracts/Treasury.sol at commit 0a08cfae3ad04994241553312aa406350ebb3c73
  • https://github.com/xyro-io/smart-contracts/contracts/UpDown.sol at commit 0a08cfae3ad04994241553312aa406350ebb3c73
  • https://github.com/xyro-io/smart-contracts/contracts/OneVsOneExactPrice.sol at commit c72c06a3c1ceb178d0c9c887fcb9afcb04e44a4e
  • https://github.com/xyro-io/smart-contracts/contracts/UpDown.sol at commit c72c06a3c1ceb178d0c9c887fcb9afcb04e44a4e
  • https://github.com/xyro-io/smart-contracts/contracts/Bullseye.sol at commit 0a08cfae3ad04994241553312aa406350ebb3c73
  • https://github.com/xyro-io/smart-contracts/contracts/Setup.sol at commit 740df06eed24a04f0e739c7c6332466dc6bae295
  • https://github.com/xyro-io/smart-contracts/contracts/Bullseye.sol at commit 740df06eed24a04f0e739c7c6332466dc6bae295
  • https://github.com/xyro-io/smart-contracts/contracts/OneVsOneExactPrice.sol at commit 740df06eed24a04f0e739c7c6332466dc6bae295
  • https://github.com/xyro-io/smart-contracts/contracts/Setup.sol at commit c72c06a3c1ceb178d0c9c887fcb9afcb04e44a4e
  • https://github.com/xyro-io/smart-contracts/contracts/UpDown.sol at commit 740df06eed24a04f0e739c7c6332466dc6bae295
  • https://github.com/xyro-io/smart-contracts/contracts/Bullseye.sol at commit c72c06a3c1ceb178d0c9c887fcb9afcb04e44a4e
  • https://github.com/xyro-io/smart-contracts/contracts/OneVsOneExactPrice.sol at commit 0a08cfae3ad04994241553312aa406350ebb3c73
  • https://github.com/xyro-io/smart-contracts/contracts/Treasury.sol at commit c72c06a3c1ceb178d0c9c887fcb9afcb04e44a4e

Part of XYRO’s security record

XYRO
Audits4 audits by 2 firmsLast audit Jan 2025, by CertiK.
Critical findings1 critical acknowledged, not fixedReported in “Xyro” by Zokyo, Aug 2024. The team acknowledged it.
Open XYRO’s security record

Security firm

CertiK

1,044 projects reviewed · 1,375 reports · latest May 2025

See CertiK’s audits

Something 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