CertiK reviewed JAM (JamAI) on 10 Jan 2025: 13 findings, 0 critical; 6 marked fixed, 7 acknowledged.
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 | 2 | 0 |
| Medium | 0 | 0 | 1 |
| Low | 0 | 5 | 5 |
In the contract `JamAI`, the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and set the threshold, set the jammer address, set the buy fee rate, update token information, set the sell fee rate, enable or disable selling, set the fee recipient address, and set the trade approver address.  --- In the contract `Jammer`, the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and set the LP treasury address, set the default locking period, set the fee recipient address, and set the JamAI address.  --- In the contract `LPTreasury`, the role `_owner` has authority over the functions shown in the diagram below. Any compromise to the `_owner` account may allow the hacker to take advantage of this authority and rescue a specified ERC721 token for a given receiver, set the token recipient address, set the fee recipient address, and release the token to the recipient after a time check. It should be noted that the recipient can remove liquidity from the pool at any time, which could even lead to the depletion of liquidity in the pool.  --- The owners of `JamAI`/`Jammer`/`LPTreasury` also have authority over the functions shown below. Any compromise to the owners' account may allow the hacker to take advantage of this authority and transfer ownership to any account or renounce ownership maliciously. - transferOwnership() - renounceOwnership() Additionally, the LP of the activated pools will also be locked in the `LPTreasury` contract and can be transferred to a `tokenRecipient` account. If this account is compromised, a hacker could exploit this authority to remove the LP, potentially disrupting the token market.
All of the tokens are sent to the contract deployer or one or several externally-owned account (EOA) addresses. 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.
In the `startTrading()` function, a ticket is generated for the creator when trading begins. According to the `sellTickets()` function, the last remaining ticket cannot be sold. If the creator sells their ticket before all the buyers have done so, the final ticket held by a buyer cannot be sold, potentially resulting in a loss.
In the `_buyTickets()` function, the function requires users to pay an amount of native tokens no less than the ticket price plus the protocol fee. ```solidity function _buyTickets(address buyer, uint256 aiAgentId, uint256 amount) internal { if (!tradeEnabled[aiAgentId]) revert TradeNotEnabled(); if (pools[aiAgentId] != address(0)) revert PoolLaunched(); uint256 supply = ticketsSupply[aiAgentId]; uint256 price = getPrice(supply, amount); uint256 protocolFee = price * buyFeeRate / 1000; if (msg.value < price + protocolFee) revert InsufficientPayment(); ticketsBalance[aiAgentId][buyer] = ticketsBalance[aiAgentId][buyer] + amount; ticketsSupply[aiAgentId] = supply + amount; emit Trade(buyer, aiAgentId, true, amount, price, protocolFee, supply + amount); if (price > 0) { (bool success, ) = feeTo.call{value: msg.value - price}(""); if(!success) revert TransferFailed(); } } ``` However, any excess amount is treated as a protocol fee and sent entirely to `feeTo`, which may result in a loss for the user.
The `startTrading()` function allows users with a valid signature to purchase tickets using `ETH`. However, the verified message does not include the buyer's address. Consequently, other accounts are able to front-run the buyer's transaction and purchase the tickets themselves.
In the design of the `JamAI` contract, users are allowed to buy and sell tickets before the associated Uniswap v3 pool is activated. When purchasing tickets, the payment amount is calculated using the `getPrice()` function, which takes `ticketsSupply[aiAgentId]` and `amount` as input parameters. When selling tickets, users can receive their investment back, minus a fee. The value of the investment is also determined by the `getPrice()` function, which takes `ticketsSupply[aiAgentId]-amount` and `amount` as input parameters. This function employs a sum of squares formula to compute the amount to be paid or refunded. The formula creates an opportunity for exploitation, as users can potentially gain by executing buy and sell transactions due to variations in the sum of squares during these operations.
The contract is serving as the underlying entity to interact with one or more third party protocols. The scope of the audit treats third party entities as black boxes and assumes their functional correctness. However, in the real world, third parties can be compromised and this may lead to lost or stolen assets. In addition, upgrades of third parties can possibly create severe impacts, such as increasing fees of third parties, migrating to new LP pools, etc. ```solidity=27 address public immutable WETH; ``` - The contract `Jammer` interacts with third party contract with `WETH`. ```solidity=28 IPancakeV3Factory public immutable pancakeV3Factory; ``` - The contract `Jammer` interacts with third party contract with `IPancakeV3Factory` interface via `pancakeV3Factory`. ```solidity=29 INonfungiblePositionManager public immutable positionManager; ``` - The contract `Jammer` interacts with third party contract with `INonfungiblePositionManager` interface via `positionManager`. ```solidity=30 IPancakeV3SwapRouter public immutable swapRouter; ``` - The contract `Jammer` interacts with third party contract with `IPancakeV3SwapRouter` interface via `swapRouter`. ```solidity=19 INonfungiblePositionManager public immutable positionManager; ``` - The contract `LPTreasury` interacts with third party contract with `INonfungiblePositionManager` interface via `positionManager`.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (4)
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