CertiK reviewed Edge Matrix Computing (EMC Finance & Bridge) on 15 Oct 2024: 50 findings, 1 critical; 34 marked fixed, 7 acknowledged, 9 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 | 1 |
| High | 0 | 4 | 4 |
| Medium | 0 | 3 | 3 |
| Low | 9 | 0 | 26 |
### Bridge In the contract `Bridge`, the role `_admin` has authority over the functions shown in the diagram below. Any compromise to the `_admin` account may allow the hacker to take advantage of this authority and add or remove a relayer, set the handler address, renounce, transfer, grant or revoke `_admin` role, pause or unpause the contract, set a generic resource, withdraw tokens via admin handler, set a token as burnable, set resource for admin, change the relayer threshold, transfer funds to multiple addresses, and change the fee.  ---- In the contract `Bridge`, the role `_adminorrelayer` has authority over the functions shown in the diagram below. Any compromise to an `_admin` or `relayer` account may allow the hacker to take advantage of this authority and cancel a proposal.  ---- In the contract `Bridge`, the role `_relayers` has authority over the functions shown in the diagram below. Any compromise to the `_relayers` account may allow the hacker to take advantage of this authority and create a new proposal, vote on a proposal, and execute a passed proposal.  ### Bridge_emc In the contract `Bridge`, the role `_admin` has authority over the functions shown in the diagram below. Any compromise to the `_admin` account may allow the hacker to take advantage of this authority and add or remove a relayer, set the handler address, renounce, transfer, grant or revoke `_admin` role, pause or unpause the contract, set a generic resource, withdraw tokens via admin handler, set a token as burnable, set resource for admin, change the relayer threshold, transfer funds to multiple addresses, and change the fee.  ---- In the contract `Bridge`, the role `_adminorrelayer` has authority over the functions shown in the diagram below. Any compromise to an `_admin` or `relayer` account may allow the hacker to take advantage of this authority and cancel a proposal.  ---- In the contract `Bridge`, the role `_relayers` has authority over the functions shown in the diagram below. Any compromise to the `_relayers` account may allow the hacker to take advantage of this authority and create a new proposal, vote on a proposal, and execute a passed proposal.  ### ERC721MinterBurnerPauser In the contract `ERC721MinterBurnerPauser`, the role `MINTER_ROLE` has authority over the functions shown in the diagram below. Any compromise to the `MINTER_ROLE` account may allow the hacker to take advantage of this authority and mint a new token with metadata.  --- In the contract `ERC721MinterBurnerPauser`, the role `PAUSER_ROLE` has authority over the functions shown in the diagram below. Any compromise to the `PAUSER_ROLE` account may allow the hacker to take advantage of this authority and unpause or pause the contract.  ### ERC20Handler In the contract `ERC20Handler`, the role `_bridge` has authority over the functions shown in the diagram below. Any compromise to the `_bridge` account may allow the hacker to take advantage of this authority and execute a proposal based on resource ID and data, perform token deposit with recipient details, and withdraw a specified token amount to the recipient.  ### ERC721Handler In the contract `ERC721Handler`, the role `_bridge` has authority over the functions shown in the diagram below. Any compromise to the `_bridge` account may allow the hacker to take advantage of this authority and process a deposit transaction, execute the proposal, and withdraw a specified token to a recipient.  --- In the contract `FinancePriceOracle`, the role `whitelisted` has authority over the functions shown in the diagram below. Any compromise to the `whitelisted` account may allow the hacker to take advantage of this authority and set the direct price and set underlying prices for cTokens.  ### Financetroller In the contract `Financetroller`, the role `admin` has authority over the functions shown in the diagram below. Any compromise to the `admin` account may allow the hacker to take advantage of this authority and pause or unpause the borrowing of a specific token, the minting of a specific token, fix bad finance accruals if proposal 65 has not been executed yet, change the borrow cap guardian address, change the borrowing cap for a specific token, pause or unpause transfers, pause or unpause seizes, and change the close factor.  --- In the contract `Financetroller`, the role `borrowCapGuardian` has authority over the functions shown in the diagram below. Any compromise to the `borrowCapGuardian` account may allow the hacker to take advantage of this authority and set market borrow caps.  ---- In the contract `Financetroller`, the role `pauseGuardian` has authority over the functions shown in the diagram below. Any compromise to the `pauseGuardian` account may allow the hacker to take advantage of this authority and pause or unpause borrowing, pause or unpause seizes, pause or unpause transfer, and pause or unpause minting. 
All of the ERC20 tokens are sent to the contract deployer. This is a centralization risk because the deployer or the owner(s) of the EOAs can distribute tokens without obtaining the consensus of the community. Any compromise to these addresses may allow a hacker to steal and sell tokens on the market, resulting in severe damage to the project.
```sol=489 function executeProposal(uint8 chainID, uint64 depositNonce, bytes calldata data, bytes32 resourceID) external onlyRelayers whenNotPaused { address handler = _resourceIDToHandlerAddress[resourceID]; uint72 nonceAndID = (uint72(depositNonce) << 8) | uint72(chainID); bytes32 dataHash = keccak256(abi.encodePacked(handler, data)); Proposal storage proposal = _proposals[nonceAndID][dataHash]; require(proposal._status != ProposalStatus.Inactive, "proposal is not active"); require(proposal._status == ProposalStatus.Passed, "proposal already transferred"); require(dataHash == proposal._dataHash, "data doesn't match datahash"); proposal._status = ProposalStatus.Executed; IDepositExecute depositHandler = IDepositExecute(_resourceIDToHandlerAddress[proposal._resourceID]); depositHandler.executeProposal(proposal._resourceID, data); emit ProposalEvent(chainID, depositNonce, proposal._status, proposal._resourceID, proposal._dataHash); } ``` `Bridge.executeProposal()` and `voteProposal()` don't carefully check the provided `resourceID`. The relayer can create the proposal with expensive fake `resourceID`, other relayers will vote for the same proposal with correct cheap `resourceID`, then the relayer will `executeProposal()` with expensive `resourceID`, practically stealing the locked tokens from the Bridge.
```sol=788 rewardSummary.pendingRewards = new PendingReward[](cTokens.length); return rewardSummary; ``` `FinanceLens.pendingRewards()` returns the empty `PendingReward` array.
The current code contains hardcoded `resourceID` and `chainId` values, which reduces flexibility and maintainability. Utilizing constants or configuration variables instead of hardcoded values will enhance supportability and adaptability to change. The code uses testnet chain IDs. Bridge_emc.sol uses 6678 (Edge Matrix Chain) in both `fallback()` and `_deposit2()`. But Bridge.sol uses 6678 (Edge Matrix Chain) in `_deposit2()` only. 99876 (Edge Matrix Chain Testnet) and 84532 (Base Sepolia Testnet) are used in `fallback()`. 99876 (Edge Matrix Chain Testnet) is used `deposit()`. ```solidity if (resourceID == 0x0000000000000000000000000000000000000000000000000000000000000000 || resourceID == 0x0000000000000000000000000000000000000000000000000000000000000002) { uint256 chainId; assembly { chainId := chainid() } if(chainId != 16688 && resourceID == 0x0000000000000000000000000000000000000000000000000000000000000002){ ``` The code should replace the specific `resourceID` and `chainId` with predefined, configurable constants. For example: ```solidity uint256 constant NATIVE_RESOURCE_ID = 0x0000000000000000000000000000000000000000000000000000000000000000; uint256 constant NATIVE_TESTNET_RESOURCE_ID = 0x0000000000000000000000000000000000000000000000000000000000000002; uint256 constant IRIShubTestnet = 16688; if (resourceID == NATIVE_RESOURCE_ID || resourceID == NATIVE_TESTNET_RESOURCE_ID) { uint256 chainId; assembly { chainId := chainid() } if (chainId != IRIShubTestnet && resourceID == NATIVE_TESTNET_RESOURCE_ID) { // Additional logics and conditions } } ``` This approach fosters better readability, maintainability, and adaptability for future updates or different deployment environments.
The `_fee` variables in the contract have no set limits, allowing fees to be set to extreme values.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (16)
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