CertiK reviewed Haven1 (Haven1 - audit hSwap) on 26 Feb 2025: 10 findings, 0 critical; 3 marked fixed, 7 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 | 1 | 0 | 0 |
| Medium | 1 | 0 | 0 |
| Low | 5 | 0 | 3 |
In the current implementation of `UniversalRouter`, the contract charges the fee once per transaction upon encountering the first swap command (V3_SWAP_EXACT_OUT or V3_SWAP_EXACT_IN), then exits the loop with break. This means if multiple swap commands are present in a single transaction , only the first swap will trigger a fee. Subsequent swaps in the same transaction will not pay additional fees. ```solidity=68 for (uint256 commandIndex = 0; commandIndex < numCommands; ) { bytes1 commandType = commands[commandIndex]; uint256 command = uint8(commandType & Commands.COMMAND_TYPE_MASK); if (command == Commands.V3_SWAP_EXACT_OUT || command == Commands.V3_SWAP_EXACT_IN) { _payH1Fee(); break; } unchecked { commandIndex++; } } ``` If the intended design is to collect only one fee per transaction, then the current logic is correct. If the contract should collect fees for each swap command, the logic should be adjusted.
The contract uses a custom storage slot for `H1NativeBaseStorage`. Using a custom storage slot is typically safe for non-upgradeable deployments, as it ensures the contract writes to a unique location unlikely to overlap with other storage variables. However, in an upgradeable proxy setup, future contract upgrades or modules may introduce new variables that use or overlap with this same slot. ```solidity bytes32 private constant H1NATIVE_STORAGE = 0x8e7ec97a86b55b46cf58cbcd08faba09d3e8d3aec4d6bf8802477f1aa7a4c700; ... function _getH1NativeStorage() private pure returns (H1NativeBaseStorage storage $) { assembly { $.slot := H1NATIVE_STORAGE } } ``` If the contract (or a child contract) is later upgraded and new variables or inherited contracts introduce different storage layouts, it could overwrite or corrupt the existing state stored in `H1NATIVE_STORAGE`. Such collisions may cause unpredictable behavior or loss of state.
The current contract code includes references to the `console` contract from Foundry. It is important to note that the `console` contract is exclusively intended for development and testing purposes, providing developers with debugging capabilities throughout the testing phase. ```solidity=61 function createPool( address tokenA, address tokenB, uint24 fee ) external override noDelegateCall returns (address pool) { console.log('createPool - 1'); require(tokenA != tokenB); console.log('createPool - 2'); (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); console.log('createPool - 3'); require(token0 != address(0)); console.log('createPool - 4'); int24 tickSpacing = feeAmountTickSpacing[fee]; console.log('createPool - 5'); require(tickSpacing != 0); console.log('createPool - 6'); require(getPool[token0][token1][fee] == address(0)); console.log('createPool - 7'); pool = deploy(address(this), token0, token1, fee, tickSpacing); console.log('createPool - 8'); getPool[token0][token1][fee] = pool; console.log('createPool - 9'); // populate mapping in the reverse direction, deliberate choice to avoid the cost of comparing addresses getPool[token1][token0][fee] = pool; console.log('createPool - 10 pool: ', pool); emit PoolCreated(token0, token1, fee, tickSpacing, pool); } ``` While the `console` code may be commented out and thus inactive, its presence within the contract codebase can still negatively impact the overall tidiness and cleanliness of the contract. Comments intended for developers' understanding and debugging purposes should not be present in the final production-ready version of the smart contract.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (105)
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