XRGB-Smart contract audit

CertiKFiles named in the report

CertiK reviewed XRGB (XRGB-Smart contract audit) on 19 Mar 2024: 16 findings, 0 critical; 13 marked fixed, 3 acknowledged.

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

Report hosted on skynet.certik.com.

Trustblock does not review code.

Findings16

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

SeverityOpenAcknowledgedFixed
Critical000
High031
Medium003
Low009
HighCentralization Related RisksAcknowledged

In the contract `BRC404` the role `_factory` has authority over the functions shown in the diagram below. ![](https://accelerator-tasks-prod.acc.corp.certik.com/11ee-d58a-584d2d00-8cdc-f19cbb37701e/diagrams/centralization_BRC404-BRC404-_factory.svg) Any compromise to the **_factory** account may allow a hacker to take advantage of this authority and do the following: - burn any amount of `BRC404` token from any account. - mint any amount of `BRC404` token to any account. - add or remove any account to whitelist. - set base token uri for `BRC404` token. In the contract `BRC404Factory` the role `_owner` has authority over the functions shown in the diagram below. ![](https://accelerator-tasks-prod.acc.corp.certik.com/11ee-d58a-584d2d00-8cdc-f19cbb37701e/diagrams/centralization_BRC404Factory-BRC404Factory-_owner.svg) Any compromise to the **_owner** account may allow a hacker to take advantage of this authority and do the following: - add or remove any account to whitelist. - set base token uri for `BRC404` token. - create `BRC404` token. - mint any amount of `BRC404` token to any account. - add support chain. - change the cross-chain fee. - withdraw native tokens from the `BRC404Factory` contract.

HighCentralized Balance ManipulationAcknowledged

In the contract `BRC404Factory`, the role owner has the authority to update the token balance of an arbitrary account without sanity restriction. Any compromise to the owner account may allow a hacker to take advantage of this authority and manipulate users' balances. For example, The hacker could also update his/her balance to a large number, sell these tokens, and cause the token price to drop.

HighPossible Failure on Transferring Small Amount OfAcknowledged

According to the logic of the function `transferFrom()`, if the value of the passed parameter `amountOrId` is less than the value of the state variable `minted`, the transfer operation will be considered as an `ERC721` transfer. A `ERC721` token and unit `ERC20` tokens will be transferred. ```solidity function transferFrom( address from, address to, uint256 amountOrId ) public virtual { if (amountOrId <= minted) { if (from != _ownerOf[amountOrId]) { revert InvalidSender(); } if (to == address(0)) { revert InvalidRecipient(); } if ( msg.sender != from && !isApprovedForAll[from][msg.sender] && msg.sender != getApproved[amountOrId] ) { revert Unauthorized(); } balanceOf[from] -= units; unchecked { balanceOf[to] += units; } _ownerOf[amountOrId] = to; delete getApproved[amountOrId]; // update _owned for sender uint256 updatedId = _owned[from][_owned[from].length - 1]; _owned[from][_ownedIndex[amountOrId]] = updatedId; // pop _owned[from].pop(); // update index for the moved id _ownedIndex[updatedId] = _ownedIndex[amountOrId]; // push token to to owned _owned[to].push(amountOrId); // update index for to owned _ownedIndex[amountOrId] = _owned[to].length - 1; emit Transfer(from, to, amountOrId); emit ERC20Transfer(from, to, units); } else { uint256 allowed = allowance[from][msg.sender]; if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amountOrId; _transfer(from, to, amountOrId); } } ``` However, if a transfer operation intends to send a small quantity of `ERC20` tokens, the amount will be treated as an `NFT ID`, which is unexpected. **[CertiK, 03/06/2024]** The team updated the codebase in the commit [e978ce7e804b2476d840e003784502bae77bcc82](https://github.com/XRGB/xrgb-contracts-v1/tree/e978ce7e804b2476d840e003784502bae77bcc82/contracts) with a new design. The function uses `_isValidTokenId` to check if the transfer is an ERC721 transfer or an ERC20 transfer. For example, in the `trasnferFrom()` function ```solidity function transferFrom( address from_, address to_, uint256 valueOrId_ ) public virtual returns (bool) { if (_isValidTokenId(valueOrId_)) { erc721TransferFrom(from_, to_, valueOrId_); } else { // Intention is to transfer as ERC-20 token (value). return erc20TransferFrom(from_, to_, valueOrId_); } return true; } ``` The `_isValidTokenId` checks if the id is smaller than `minted`, which is the biggest number of the token id. ```solidity function _isValidTokenId(uint256 id_) internal view returns (bool) { return id_ <= minted && id_ != type(uint256).max; } ``` Therefore, the amount that is smaller than the value of `minted` will be treated as an ERC721 transfer, using `erc721TransferFrom()` to transfer. However, since the sender may not hold the NFT with such an ID, the token transfers will fail.

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 (10)

  • contracts/libraries/DoubleEndedQueue.sol
  • contracts/libraries/Events.sol
  • contracts/libraries/Errors.sol
  • contracts/storage/BRC404FactoryStorage.sol
  • contracts/libraries/ERC20Events.sol
  • contracts/libraries/ERC721Events.sol
  • contracts/BRC404Factory.sol
  • contracts/libraries/DataTypes.sol
  • contracts/BRC404.sol
  • contracts/ERC404.sol

Part of XRGB’s security record

XRGB
Audits1 audit by 1 firmLast audit Mar 2024, by CertiK.
Critical findingsNo open critical findingsIn 1 report.
Open XRGB’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