CertiK reviewed Venombridge (Venom Bridge) on 3 Nov 2022: 33 findings, 0 critical; 19 marked fixed, 5 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 | 0 |
| High | 0 | 5 | 2 |
| Medium | 0 | 0 | 6 |
| Low | 9 | 0 | 11 |
On the Ethereum side, the following contracts(see "Contracts") contain Privileged functions(see "Privileged Function") can only call by privileged roles(See "Privileged Roles"). Privileged functions can be used to modify the bridge's configurations, upgrade contracts and move assets from the bridge. Any compromise to one or more privileged accounts may allow a hacker to take advantage of this authority and alter the bridge configuration, take full control of the bridge, and withdraw assets from the bridge. "Contracts" * DAO.sol * Registry.sol * Bridge.sol * multivault/MultiVault.sol * multivault/MultiVaultToken.sol * ProxyAdmin * TransparentUpgradeableProxy * strategies/BaseStrategy.sol * strategies/Convex3crv.sol * strategies/ConvexCrvLp.sol * strategies/ConvexFrax.sol * vault/Vault.sol, "Privileged Roles" * Owner * roundSubmitter * Keepers * Governance * pendingGovernance * Guardian * strategist * WithdrawGuardian * StrategyRewardsManager * Management "Privileged Functions" * setConfiguration() * setBridge() * setBridge() * setRewards() * setProxyAdmin() * newVaultRelease() * newVault() * endorseVault() * setBanksy() * tagVault() * setConfiguration() * pause() * unpause() * updateMinimumRequiredSignatures() * updateRoundTTL() * forceRoundRelays() * setRoundSubmitter() * banRelays() * unbanRelays() * setPrefix() * blacklistAddToken() * blacklistRemoveToken() * setRewards() * setDefaultNativeDepositFee() * setDefaultNativeWithdrawFee() * setDefaultAlienDepositFee() * setDefaultAlienWithdrawFee() * setTokenDepositFee() * setTokenWithdrawFee() * setConfigurationAlien() * setConfigurationNative() * setGovernance() * acceptGovernance() * setManagement() * setGuardian() * setEmergencyShutdown() * skim() * migrateAlienTokenToVault() * mint() * burn() * changeProxyAdmin() * upgrade() * upgradeAndCall() * changeAdmin() * upgradeTo() * upgradeToAndCall() * setStrategist() * setKeeper() * setMinReportDelay() * setMaxReportDelay() * setProfitFactor() * setDebtThreshold() * setMetadataURI() * tend() * harvest() * migrate() * setEmergencyExit() * sweep() * setPathTarget() * _approveBasic() * _approveDex() * approveAll() * switchDex() * setSlippageFactor() * setIsClaimRewards() * setIsClaimExtras() * withdrawToConvexDepositTokens() * withdrawToWrappedTokens() * claimWantTokens() * claimWrappedWantTokens() * claimRewardTokens() * harvest() * sweep() * setPathTarget() * setDepositFee() * setWithdrawFee() * setConfiguration() * setGovernance() * acceptGovernance() * setManagement() * setGuardian() * setWithdrawGuardian() * setStrategyRewards() * setRewards() * setLockedProfitDegradation() * setDepositLimit() * setPerformanceFee() * setManagementFee() * setWithdrawLimitPerPeriod() * setUndeclaredWithdrawLimit() * setEmergencyShutdown() * setWithdrawalQueue() * addStrategy() * updateStrategyDebtRatio() * updateStrategyMinDebtPerHarvest() * updateStrategyMaxDebtPerHarvest() * updateStrategyPerformanceFee() * migrateStrategy() * revokeStrategy() * revokeStrategy() * skim() * skimFees() * sweep() * setPendingWithdrawalApprove()
On the Everscale side, the following contracts(see "Contracts") contain Privileged functions(see "Privileged Function") can only call by privileged roles(See "Privileged Roles"). Privileged functions can be used to modify the bridge's configurations, upgrade contracts and move assets from the bridge. Any compromise to one or more privileged accounts may allow a hacker to take advantage of this authority and alter the bridge configuration, take full control of the bridge, and withdraw assets from the bridge. "Contracts" * Bridge.sol: * Connector.sol: * MergePool.sol: * MergeRouter.sol: * EthereumEventConfiguration.sol: * EverscaleEventConfiguration.sol: * BaseEvent.sol: * ProxyMultiVaultNative.sol: * ProxyTokenTransfer.sol: * ProxyMultiVaultAlien_V3.sol: * DaoRoot.sol: * Staking.sol: * StakingV1_1.sol: * StakingBase.sol: * StakingUpgradable.sol: "Privileged Roles" * Manager * Owner * Admin * Rewarder * Rescuer "Privileged Functions" * addDelegate() * addToken() * burn() * disableAll() * disablePool() * disableToken() * enable() * enableAll() * enableToken() * forceUpgradeUserData() * installOrUpdateElectionCode() * installOrUpdateRelayRoundCode() * installOrUpdateUserDataCode() * legacyTransferTokenOwnership() * mint() * removeToken() * sendMessage() * sendRelaysToRelayRound() * setActive() * setBridgeEventEthTonConfig() * setBridgeEventTonEthConfig() * setCanon() * setConfiguration() * setEmergency() * setEndBlockNumber() * setEndTimestamp() * setManager() * setMergePool() * setMergePoolPlatform() * setMergeRouter() * setMeta() * setPool() * setStakingRoot() * setTonEventDeployValue() * startNewRewardRound() * transferAdmin() * transferTokenOwnership() * updateActive() * updateConnectorDeployValue() * updateEthereumActionEventConfiguration() * updateGracePeriod() * updateProposalCode() * updateProposalConfiguration() * updateQuorumVotes() * updateThreshold() * updateTimeLock() * updateVotingDelay() * updateVotingPeriod() * upgrade() * upgradeElection() * upgradeMergePool() * upgradeRelayRound() * withdrawTokensEmergency() * withdrawTonsEmergency()
The current bridge design is not compatible with non-standard ERC20 tokens, such as deflationary tokens or rebase tokens. For example:\ When transferring ERC20 deflationary tokens, the input amount may not be equal to the received amount due to the charged transaction fee. As a result, an inconsistency in the amount will occur and the transaction may fail due to the validation checks. For example, if a user sends 100 deflationary tokens (with a 10% transaction fee) to the target contract, only 90 tokens actually arrived in the contract. ```sol IERC20(token).safeTransferFrom( msg.sender, address(this), amount ); _transferToEverscaleAlien(token, recipient, amount - fee); ```
If a user calls `withdraw()` and the balance in this contract is insufficient, the function would trigger `IStrategy(strategyId).withdraw()` which may incur losses that would be undertaken by the user.
Based on the comment("Allows to transfer arbitrary tokens from Everscale to EVM and backwards.") and implementation, the "MultiVault" contract plan to support arbitrary types of ERC20 tokens. The `deposit(EverscaleAddress memory recipient, address token, uint amount)` function takes the user input "token," and the contract performs multiple external calls to the token address, such as: * IERC20(token).safeTransfer() * IERC20(token).balanceOf(address(this)) * IERC20Metadata(_token).name(), * IERC20Metadata(_token).symbol(), * IERC20Metadata(_token).decimals(), * IERC20(pendingWithdrawal.token).safeTransfer() One of the most dangerous behaviors in smart contracts is to perform an external call to an untrusted contract. An attacker can deploy a contract and implement the contract whatever they want. When the "MultiVault" contract performs the external call, the attacker-defined code will be executed.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (133)
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