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 |
The `Bridge._chainID` is set in the constructor and can be arbitrary. It is not used by the contract. According to the parameter description: ```sol=113 @param chainID ID of chain the Bridge contract exists on. ``` The `chainID` should represent the ID of the chain on which the contract is deployed. To ensure accuracy, it is recommended to use: ```sol uint256 chainId; assembly { chainId := chainid() } ```
The specific role is assigned with `DEFAULT_ADMIN_ROLE` as the role admin. However, the assignment here is redundant, as `DEFAULT_ADMIN_ROLE` will be the role admin for any role by default.
The `approve()` and `transferFrom()` functions are vulnerable to front-run attacks. This is because the `approve()` method overwrites the current allowance without checking if the spender has already used it. Consequently, if the spender has already spent the amount, the `approve` function will still approve a new amount.
The smart contract contains assembly code blocks, which enable direct interaction with the Ethereum Virtual Machine (EVM) and permits developers to write low-level code that manipulates the EVM. This low-level access is error-prone and can introduce complexity, vulnerabilities, and logic errors. ```sol=102 assembly { amount := calldataload(0xC4) recipientAddress := mload(0x40) lenRecipientAddress := calldataload(0xE4) mstore(0x40, add(0x20, add(recipientAddress, lenRecipientAddress))) calldatacopy( recipientAddress, // copy to destinationRecipientAddress 0xE4, // copy from calldata @ 0x104 sub(calldatasize(), 0xE) // copy size (calldatasize - 0x104) ) } ``` The code contains bugs: 0xE used instead of 0xE4. Offsets in GenericHandler are wrong. Some comments are misleading and contradict the code.
The use of function `_setupRole()` from inherited contract `AccessControlEnumerable` is deprecated in favor of directly calling internal function `_grantRole()`. Since function `_setupRole()` only calls function `_grantRole()`, it is more direct to use the latter function instead.
There should always be events emitted in the sensitive functions that are controlled by centralization roles.
```sol=469 require(proposal._status != ProposalStatus.Cancelled, "Proposal already cancelled"); ``` If expired, the proposal can be cancelled by the admin or relayer even if it was already executed. The status will be changed to Cancelled and the misleading event emitted.
In the `WEMC` token implementation the lack of validation on the `to` parameter in the `transfer()` and `transferFrom()` functions allows tokens to be sent to the zero address. This may result in lost tokens or unexpected behavior.
The linked variables assigned in the constructor can be declared as `immutable`. Immutable state variables can be assigned during contract creation but will remain constant throughout the lifetime of a deployed contract. A big advantage of immutable variables is that reading them is significantly cheaper than reading from regular state variables since they will not be stored in storage.
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