TrustNet Score
The TrustNet Score evaluates crypto projects based on audit results, security, KYC verification, and social media presence. This score offers a quick, transparent view of a project's credibility, helping users make informed decisions in the Web3 space.
Real-Time Threat Detection
Real-time threat detection, powered by Cyvers.io,
is currently not
activated
for this project.
This advanced feature provides continuous monitoring and instant alerts to safeguard your assets from potential security threats. Real-time detection enhances your project's security by proactively identifying and mitigating risks.
For more information, click here.
Security Assessments
Summary and Final Words
No crucial issues found
The contract does not contain issues of high or medium criticality. This means that no known vulnerabilities were found in the source code.
Contract owner cannot mint
It is not possible to mint new tokens.
Contract owner cannot blacklist addresses.
It is not possible to lock user funds by blacklisting addresses.
Contract owner cannot set high fees
The fees, if applicable, can be a maximum of 25% or lower. The contract can therefore not be locked. Please take a look in the comment section for more details.
Contract cannot be locked
Owner cannot lock any user funds.
Token cannot be burned
There is no burning within the contract without any allowances
Ownership is not renounced
The owner retains significant control, which could potentially be used to modify key contract parameters.
Contract is not upgradeable
The contract does not use proxy patterns or other mechanisms to allow future upgrades. Its behavior is locked in its current state.
Scope of Work
This audit encompasses the evaluation of the files listed below, each verified with a SHA-1 Hash. The team referenced above has provided the necessary files for assessment.
The auditing process consists of the following systematic steps:
- Specification Review: Analyze the provided specifications, source code, and instructions to fully understand the smart contract's size, scope, and functionality.
- Manual Code Examination: Conduct a thorough line-by-line review of the source code to identify potential vulnerabilities and areas for improvement.
- Specification Alignment: Ensure that the code accurately implements the provided specifications and intended functionalities.
- Test Coverage Assessment: Evaluate the extent and effectiveness of test cases in covering the codebase, identifying any gaps in testing.
- Symbolic Execution: Analyze the smart contract to determine how various inputs affect execution paths, identifying potential edge cases and vulnerabilities.
- Best Practices Evaluation: Assess the smart contracts against established industry and academic best practices to enhance efficiency, maintainability, and security.
- Actionable Recommendations: Provide detailed, specific, and actionable steps to secure and optimize the smart contracts.
A file with a different Hash has been intentionally or otherwise modified after the security review. A different Hash may indicate a changed condition or potential vulnerability that was not within the scope of this review.
Final Words
The following provides a concise summary of the audit report, accompanied by insightful comments from the auditor. This overview captures the key findings and observations, offering valuable context and clarity.
Smart Contract Analysis Statement
Contract Analysis
The BoxaUniHookV2 contract implements a Uniswap v4 hook that serves every BOXA launch pool on Elysium. It takes a fee of 1% plus an optional creator-defined extra of up to 9% on the quote side of each swap, splits it between the BOXA treasury, the pool creator, the token holders and a buyback-and-burn queue, and pays everyone out through pull-based claims held inside the PoolManager. Holder shares now wait until they are released outside of any trade, and buybacks are limited by a price reference that the hook keeps on chain. The launch liquidity stays locked forever and donations are refused. This re-audit covers version 2 of the contracts at commit d1d5a98, which had not been deployed at the time of the review. The contract cannot be upgraded.
Ownership Privileges
The ownership of the contract will be held by the address chosen at deployment. Because version 2 is not deployed yet, we could not verify whether that address will be a multisig, and the code itself contains no timelock. The owner retains full privileges including:
- Setting the treasury's share of the creators' extra tax, between 0% and 10% of that tax, for pools launched from then on.
- Allowing or removing ERC-20 tokens as quote assets for new launches and choosing their opening price, after a test transfer and a supply check.
- Moving the treasury to a new address in two steps, in which case the treasury's unclaimed credit moves with it.
- Handing ownership to a new address through a two-step process, or renouncing it, which freezes the settings and the treasury.
- The owner cannot change the fees, shares or any other terms of a pool once it has launched, and creators can refuse settings that changed just before their launch.
- The owner cannot add, move or remove liquidity, and nobody can ever remove the launch liquidity.
- The owner cannot touch any creator credit, holder reward or buyback budget, and cannot pause, mint, blacklist or upgrade anything.
- Buybacks can be started by anyone and are limited on chain; neither the owner nor the treasury has any special power over them.
Security Features
The contract implements several positive security features:
- Holder rewards are only shared out while the PoolManager is locked and never in a transaction in which the token moved, so borrowed or briefly held tokens earn nothing.
- Each buyback may only buy up to about 2% above a reference price that cannot be moved within a second and rises slowly; what it cannot spend stays queued.
- Buys that do not fill completely revert, so the fee never exceeds the advertised maximum of 10% of what is swapped; fees are capped, frozen at launch and always split in full.
- Launch liquidity is permanently locked, donations are refused, payouts are pull-based per currency and protected by a reentrancy guard, and the zero address is refused as a recipient.
Auditor's Comments
All issues of the previous version that could be fixed in code have been addressed. The capture of holder rewards with borrowed tokens, the sandwiching of the buyback, the anti-snipe limit that could be bypassed, which has been removed, and the fee charged on unfilled buys are resolved, and we confirmed each fix by repeating the original attacks. One new low-severity point remains: the price reference follows rises at one tick per second, so a party that raises the price and keeps it there long enough, about two hours for a doubling in our test, can still make the buyback buy at the raised price and then sell into it. This requires a large queued budget and nobody trading against the raised price in the meantime. Holder rewards are now only paid out when someone calls the release or claim function, so the team should run a keeper. The owner can now redirect the treasury together with its unclaimed credit, and should therefore be a multisig behind a timelock. The compiler version should be fixed and the build settings published before deployment.
Note - This Audit report consists of a security analysis of the BoxaUniHookV2 smart contract. This analysis did not include economic analysis of the contract's tokenomics. Moreover, we only audited the main contract for the BOXA team; the BOXA launch token and the launcher are covered by their own statements. Other contracts associated with the project, such as the Uniswap v4 PoolManager and the quote tokens, were not audited by our team. We recommend investors do their own research before investing.
Files and details
Findings and Audit result
high Issues | 1 findings
Resolved
#1 high Issue
Holder rewards can be captured with tokens borrowed from the PoolManager inside a single transaction
Holder rewards are split by the token balances that exist at the moment of distribution, and the PoolManager is excluded from earning. Inside a Uniswap v4 unlock, any contract can take the pool's own token reserves at no cost as long as it returns them before the unlock ends. While it holds them it owns almost the whole earning supply, so calling releaseHolderRewards, or any swap, hands it nearly the entire pending holder share, and the credit stays after the tokens are returned. The same works for the holder share of a buyer's own buy, and for a seller who releases the pending share before settling. We reproduced this on the live deployment: one transaction collected 99.7 percent of the pending holder rewards of every live pool that had any. On pools without real holders it collected everything that would otherwise have gone to buyback.
medium Issues | 3 findings
Resolved
#1 medium Issue
Buyback swap has no on-chain price bound and can be sandwiched by the party that triggers it
processBuyback spends the whole queued budget in one swap with the price limit set to the far end of the curve, so the only protection is the minimum output chosen by the caller, and the caller is always the pool creator or the treasury. A creator that controls a contract can buy first, run the buyback with a minimum of zero at the inflated price and sell back in the same transaction, while also earning 70 percent of the base fee on its own trades. The treasury, a single externally owned account, has the same power over every pool. In our test the creator kept 3.6 HYPE of a 6.4 HYPE budget, and the buyback burned 28 million tokens instead of 96 million.
Resolved
#2 medium Issue
Anti-snipe limit is checked per swap and can be bypassed by batching swaps
During the first 60 seconds of an anti-snipe pool, afterSwap only rejects a single swap that returns more than 10 million tokens. A Uniswap v4 unlock can contain any number of swaps, so one transaction can make many swaps just below the cap, and there is no limit per transaction, block or buyer. In our test one transaction at the launch second bought 140 million tokens, fourteen times the cap, while a single large buy was correctly refused. 118 of the 310 live pools rely on this protection.
Resolved
#3 medium Issue
Buy fee is charged on the full requested input even if the swap fills only partly
The buy fee is computed in beforeSwap from the requested input. If the swap then stops early at the caller's price limit, the unused input is returned, but the fee on it is still charged and is lost to the buyer. In our test a 10 HYPE buy with a tight limit swapped about 0.03 HYPE and paid a 1 HYPE fee, an effective rate of 97 percent against the advertised 10 percent maximum. A pool creator, who earns part of every fee, can also push the price just before such a buy so that it fills only a fraction. Users of the standard router are not affected because it never sets a price limit, and a sufficient minimum output makes such a trade revert instead.
low Issues | 3 findings
Acknowledged
#1 low Issue
Quote asset allowlist includes reward-bearing and upgradeable tokens
The hook's documentation limits quote assets to plain ERC-20 tokens, but the owner has allowlisted BOXA and ELYCAT from the earlier BOXA v4 deployment. Their reward bookkeeping excludes a different PoolManager, so the current PoolManager earns their holder rewards on everything it holds for the four live BOXA-quoted pools. Those rewards can never be claimed, which dilutes the real holders of those tokens. KNTQ and wNVDAx are bridge tokens behind an upgradeable beacon whose behaviour can change after allowlisting, and the launcher's check against short deliveries only runs when a launch includes a first buy.
Acknowledged
#2 low Issue
Owner and treasury are single externally owned accounts without a timelock
The owner, an externally owned account, can change the treasury's cut of future extra taxes, the quote asset allowlist and its opening prices with immediate effect. The treasury is an immutable externally owned account that receives 30 percent of every base fee plus its cut of the extra tax, and it may trigger the buyback of every pool with its own slippage setting. A compromised treasury key could therefore drain buyback budgets across all pools, and a lost key would lock its credit for good because the address cannot be changed.
Pending
#3 low Issue
Buyback price bound can be met by holding a raised price until the reference catches up
The buyback reference follows the pool price upward by one tick per second, so after any price rise the bound catches up after as many seconds as the rise has ticks. Anyone who pushes the price up and keeps it there long enough can therefore make the buyback spend its budget at the raised price and then sell into it. In our test a party with no special role bought 25 HYPE of tokens, which doubled the price, held the position for about 110 minutes with nobody trading against it, let the buyback run and sold, and ended 2.29 HYPE ahead on a budget of 6.42 HYPE. As the creator, which gets part of the fees back, it ended 2.66 HYPE ahead. The attack needs a large queued budget and carries real market risk, because any holder can sell into the raised price while it is held.
optimization Issues | 3 findings
Resolved
#1 optimization Issue
Pool struct can be packed into four storage slots
The Pool struct uses five storage slots because the small fields do not fill the free space next to the addresses, and every swap reads fields from all five. Reordering the fields fits the struct into four slots and the fields used during swaps into three.
Resolved
#2 optimization Issue
Reentrancy guard can use transient storage
The guard is a storage variable that is written twice on every claim, reward claim, release and buyback. The chain supports transient storage, which the PoolManager already relies on.
Resolved
#3 optimization Issue
Fee split subtractions can be unchecked
The subtractions in BoxaFeeSplit.split can never underflow, because each share subtracted is bounded by the value it is taken from, and the products are bounded by the amount times 100,000.
informational Issues | 7 findings
Resolved
#1 informational Issue
Allowed opening tick range contains values for which every launch reverts
setQuoteAsset accepts opening ticks down to -400,000. Below -349,200, however, the single-sided launch position needs more liquidity per tick than Uniswap v4 allows, so every launch against such a quote asset would revert. No funds are at risk, but a misconfigured quote asset would be unusable.
Resolved
#2 informational Issue
Missing and misleading events around holder shares and buybacks
FeeTaken always reports the holders' credit, even when that share is later sent to buyback because almost nobody holds the token, or is only pending after a sell. The redirect to buyback emits no event at all, so off-chain accounting cannot follow where the holder share went. The launch time is stored without an event, and the buyback event names its amount nativeSpent even for ERC-20 quotes.
Resolved
#3 informational Issue
Payout functions accept the zero address as recipient
claim and claimRewards send the payout to any recipient, including the zero address. For native HYPE that transfer succeeds, so a mistaken call permanently burns the caller's credit.
Resolved
#4 informational Issue
Misleading errors, duplicated constants and incomplete NatSpec
The constructor reports zero addresses as InvalidPool, and an empty buyback queue reverts with NothingToClaim. BPS, DEAD and TICK_SPACING are declared again in several contracts, although the hook and the launcher must agree on them. The Pool struct field extraCutBps shares its name with a state variable, and most external functions lack parameter and return documentation.
Resolved
#5 informational Issue
Dependence on the PoolManager owner and donations lost to the locked position
The owner of the PoolManager, an externally owned account, can appoint a protocol fee controller that may charge up to 0.1 percent per swap on these pools, which traders would pay on top of the hook's fee. Donations to a BOXA pool are allowed because beforeDonate is not used. They accrue to the permanently locked launch position, so they are lost to the donor.
Pending
#6 informational Issue
Compiler with known bugs and unverified deployed code
Solidity 0.8.26 has several known compiler bugs. We checked their conditions and none apply to this code, although the optimizer bookkeeping issue cannot be excluded by inspection alone. The deployed code carries no source metadata hash and the source is not verified on the block explorer, so users cannot independently confirm what was deployed. We reproduced the deployed bytecode exactly from the audited source with the matching dependency versions.
Pending
#7 informational Issue
Raw transient storage slot, future keyword and missing treasury event
The reentrancy guard writes transient storage slot 0 directly in inline assembly. Solidity places transient state variables from slot 0 onwards, so a transient variable added in a later version would silently share the guard's slot. The PriceReference field named at compiles today, but current compilers already warn that at will become a reserved keyword, which would stop the code from compiling unchanged. The constructor emits no event for the first treasury, although the treasury can now change, and claimable is declared public although it is only called from outside.