🧵 Top 10 Security Issues Discovered by ZokyoFrom subtle rounding errors to potential denial-of-service attacks, the flaws listed reveal just how critical thorough audits are. Remember: A smart contract is only as strong as its weakest link.Here are the top 10 issues we’ve found and resolved for our clients in 2024. 👇1️⃣ Betting Game Precision Loss:In a betting game, if a huge majority bets on the winning side (e.g., 1e4 tokens vs. 1e7 tokens), the reward rate can round to zero due to precision loss in the contract's calculation. This leads to winners receiving less than their initial deposit since winning side gains got cancelled and reward was (initialDeposit + gains - someFee), causing them to lose rewards instead of gaining. The bug was caused by a rounding issue in calculateUpDownRate() and similar functions, resulting in unfair outcomes for winning players.2️⃣ Interest Rate Rounding to Zero:In an updateBalances function, the interest formula can round to 0 if the calculation is done with very small intervals. For example, with a 3e3 borrow rate and 1e10 borrowed amount, if the contract is deployed on SEI (with 1-second block times) and an attacker calls it every second (cheap gas cost), the interest calculated becomes numeratorLess / denominatorLarger, which rounds down to 0.3️⃣ LoanVault Denial-of-Service (DoS):In a LoanVault contract, the liquidation function checks if debtAmount == IERC20(debt).balanceOf(address(this)), which opens up a vulnerability. An attacker can manipulate this by sending extra debt tokens to the contract, causing the balance to exceed debtAmount. This blocks the liquidation process as the strict equality condition fails, resulting in a denial-of-service (DoS) and preventing legitimate liquidations.4️⃣ Raffle Function Precision Loss:In a raffle-like function of the betting contract, if there are two players, the deposited amount is distributed based on ratios like 75/25. When calculating wonAmountFirst and wonAmountSecond, precision loss occurs. For example, with a deposit of 233 and a 75/25 split, the total distributed is 465, leading to a loss of 1 unit. When this value is later multiplied by token.decimals(), the actual loss could amount to an entire token, like 1 ETH.5️⃣ Betting Game Price Bias:In a betting game, players bet on whether an asset's price will rise or fall compared to its starting price. However, the current finalizeGame() function unfairly increases the probability of 'down betters' winning. If the price is the same or lower, 'down betters' win, whereas 'up betters' only win if the price increases. This bias gives 'down betters' a higher chance of winning.6️⃣ Fee Miscalculation in activateLoan():In a activateLoan() function, after calculating the initial fee (e.g., 100), a referral fee is deducted (e.g., 20). The remaining fee should then be 80. However, when the _takeFee() function is called, the fee is incorrectly recalculated as 100 instead of using the updated value (80). This results in an overpayment of fees—120 instead of 100 (initial fee + referral fee), which leads to users paying more than intended.7️⃣ XSS Vulnerability in Vault Contract:In a vault contract, while creating a vault, a pool owner can create a new vault for two tokens, and the token names and symbols are displayed on the frontend. However, these inputs are unsanitized, allowing an attacker to inject malicious JavaScript code, potentially leading to Cross-Site Scripting (XSS). This vulnerability can result in the execution of arbitrary code, which could trick users into signing malicious transactions or aid phishing attempts. This highlights that Web2 attack vectors, such as XSS, remain crucial to address in Web3 applications, as they can directly impact the security of smart contracts and user funds.8️⃣ Token TransferFrom Vulnerability:A token forked from WETH had a vulnerability in the transferFrom function. Attackers could transfer tokens without allowance due to improper validation of src and msg.sender. Fix: Ensure the correct allowance logic and validation for src to prevent unauthorized transfers.9️⃣ Subnet Reward Distribution Exploit:A reward distribution function can be exploited to drain subnet funds. Attackers, acting as previous relayers, can craft messages selecting a past checkpoint, triggering the reward distribution through another function. This bypasses key security checks, allowing the attacker to assign arbitrary rewards and siphon off funds undetected.🔟 Array Deletion Before Reading:A vulnerability was identified in a function where an array is deleted before its values are read. The issue occurs when an array storing quorum-related data is deleted, and then the values from that same array are accessed afterward, resulting in empty or invalid reads. To resolve this, the deletion should be moved to occur after the values are read to ensure the data is properly accessed before removal.