Platform: Code4rena
Start Date: 16/01/2024
Pot Size: $80,000 USDC
Total HM: 37
Participants: 178
Period: 14 days
Judge: Picodes
Total Solo HM: 4
Id: 320
League: ETH
Rank: 110/178
Findings: 1
Award: $39.34
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: peanuts
Also found by: 0xAsen, 0xHelium, 0xSmartContract, 0xepley, DedOhWale, K42, LinKenji, Sathish9098, ZanyBonzy, catellatech, fouzantanveer, foxb868, hassanshakeel13, hunter_w3b, jauvany, kaveyjoe, kinda_very_good, klau5, niroh, rspadi, yongskiws
39.3353 USDC - $39.34
Salty.IO is a Decentralized Exchange built on the Ethereum blockchain, employing Automatic Atomic Arbitrage (AAA) to generate yield and offer Zero Fees on all swaps. Through AAA, market inefficiencies are during the swapping process, resulting in profits that are subsequently distributed to liquidity providers and stakers. These earnings are utilized to establish Protocol Owned Liquidity (POL) for the DAO.
Furthermore, Salty.IO introduces USDS, an overcollateralized ERC20 stablecoin native to the protocol, backed by the WBTC/WETH liquidity pool. The exchange is launched with 100% decentralization, where all parameters, regional exclusions, whitelisting, and contracts are under the control of the DAO itself.
Structuring the code is crucial for conducting a thorough analysis of the code base. This enables auditors to predict the level of contract difficulty, identify critical contracts, and determine security-critical features such as payment functions or assembly usage. Additionally, this approach accurately measures the time required to perform a detailed audit and helps determine the cost of a project audit. To achieve efficiency, clarity, and improvements, it is essential to have a comprehensive view of the entire architecture. This enables the identification of the basic structure, relationships between modules, and key design patterns. By understanding the big picture, we can analyze the complexity of the code and reveal its strengths and potential for improvement with confidence.
Lines: total lines of the source unit
nLines: normalized lines of the source unit (e.g. normalizes functions spanning multiple lines)
nSLOC: normalized source lines of code (only source-code lines; no comments, no blank lines)
Comment Lines: lines containing single or block comments
Complexity Score: a custom complexity score derived from code statements that are known to introduce code complexity (branches, loops, calls, external interfaces, ...)
Type | File | Lines | nLines | nSLOC | Comment Lines | Complex. Score | Capabilities |
---|---|---|---|---|---|---|---|
๐ | USDS.sol | 61 | 58 | 30 | 10 | 27 | |
๐ | Upkeep.sol | 291 | 277 | 155 | 48 | 151 | โป๏ธ |
๐จ | StakingRewards.sol | 306 | 294 | 157 | 62 | 170 | |
๐ | StakingConfig.sol | 100 | 96 | 66 | 12 | 37 | |
๐ | Staking.sol | 213 | 202 | 106 | 37 | 106 | |
๐ | StableConfig.sol | 153 | 147 | 98 | 20 | 53 | |
๐ | SigningTools.sol | 30 | 29 | 19 | 2 | 24 | ๐ฅ๐ |
๐ | SaltRewards.sol | 149 | 143 | 82 | 25 | 110 | |
๐ | Salt.sol | 40 | 38 | 22 | 4 | 19 | |
๐ | RewardsEmitter.sol | 151 | 148 | 87 | 29 | 89 | |
๐ | RewardsConfig.sol | 101 | 97 | 66 | 15 | 37 | |
๐ | Proposals.sol | 446 | 421 | 242 | 63 | 243 | ๐งฎ |
๐ | PriceAggregator.sol | 197 | 187 | 123 | 23 | 68 | โป๏ธ |
๐ | PoolUtils.sol | 69 | 66 | 30 | 18 | 35 | ๐งฎ |
๐จ | PoolStats.sol | 147 | 140 | 82 | 21 | 73 | |
๐ | PoolsConfig.sol | 156 | 147 | 87 | 20 | 69 | |
๐ | Pools.sol | 427 | 410 | 212 | 94 | 147 | |
๐ | PoolMath.sol | 228 | 224 | 65 | 131 | 29 | |
๐จ | Parameters.sol | 123 | 122 | 92 | 14 | 53 | |
๐ | ManagedWallet.sol | 90 | 88 | 46 | 20 | 36 | ๐ฐ |
๐ | Liquidizer.sol | 153 | 148 | 88 | 28 | 73 | |
๐จ | Liquidity.sol | 163 | 158 | 80 | 37 | 68 | |
๐ | InitialDistribution.sol | 75 | 74 | 50 | 8 | 34 | |
๐ | ExchangeConfig.sol | 86 | 83 | 55 | 15 | 38 | |
๐ | Emissions.sol | 62 | 61 | 34 | 11 | 22 | |
๐ | DAOConfig.sol | 198 | 190 | 126 | 35 | 69 | |
๐ | DAO.sol | 388 | 376 | 239 | 47 | 237 | ๐งฎ |
๐ | CoreUniswapFeed.sol | 145 | 139 | 81 | 23 | 67 | โป๏ธ |
๐ | CoreSaltyFeed.sol | 54 | 52 | 32 | 6 | 18 | |
๐ | CoreChainlinkFeed.sol | 73 | 70 | 44 | 14 | 20 | โป๏ธ |
๐ | CollateralAndLiquidity.sol | 352 | 338 | 176 | 71 | 183 | |
๐ | BootstrapBallot.sol | 86 | 84 | 49 | 11 | 36 | ๐งฎ |
๐จ | ArbitrageSearch.sol | 137 | 134 | 69 | 38 | 44 | ฮฃ |
๐ | Airdrop.sol | 101 | 96 | 51 | 17 | 49 | |
๐ | AccessManager.sol | 79 | 75 | 31 | 21 | 20 | ๐งฎ |
๐๐๐จ | Totals | 5630 | 5412 | 3072 | 1050 | 2554 | ๐ฅ๐ฐ๐งฎ๐โป๏ธฮฃ |
๐Public | ๐ฐPayable |
---|---|
174 | 1 |
External | Internal | Private | Pure | View |
---|---|---|---|---|
131 | 205 | 0 | 11 | 72 |
Total | ๐Public |
---|---|
217 | 196 |
Solidity Versions observed | ๐งช Experimental Features | ๐ฐ Can Receive Funds | ๐ฅ Uses Assembly | ๐ฃ Has Destroyable Contracts |
---|---|---|---|---|
=0.8.22 | - | yes | (1 asm blocks) | - |
๐ค Transfers ETH | โก Low-Level Calls | ๐ฅ DelegateCall | ๐งฎ Uses Hash Functions | ๐ ECRecover | ๐ New/Create/Create2 |
---|---|---|---|---|---|
- | - | - | yes | yes | - |
โป๏ธ TryCatch | ฮฃ Unchecked |
---|---|
yes | yes |
Dependency / Import Path | Count |
---|---|
chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol | 1 |
openzeppelin-contracts/contracts/access/Ownable.sol | 10 |
openzeppelin-contracts/contracts/finance/VestingWallet.sol | 2 |
openzeppelin-contracts/contracts/security/ReentrancyGuard.sol | 8 |
openzeppelin-contracts/contracts/token/ERC20/ERC20.sol | 7 |
openzeppelin-contracts/contracts/token/ERC20/IERC20.sol | 4 |
openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol | 1 |
openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol | 12 |
openzeppelin-contracts/contracts/utils/Strings.sol | 1 |
openzeppelin-contracts/contracts/utils/math/Math.sol | 4 |
openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol | 4 |
v3-core/interfaces/IUniswapV3Pool.sol | 1 |
v3-core/libraries/FixedPoint96.sol | 1 |
v3-core/libraries/FullMath.sol | 1 |
v3-core/libraries/TickMath.sol | 1 |
We began by thoroughly reviewing and read docs Salty procotol the provided documentations, as well as reviewing the video provided. Here, we made note of important information, noted down unclear parts and overall tried to fully understand how the protocol should function. We also took notes of integrated and inherited protocols and mapped out possible risk areas.
While we were studying the docs, we had ran static analyzers and linters through the contracts to detect basic vulnerabilities and other non critical errors. The result of our static analysis was then compared to the provided bot reports and those deemed known were removed.
After the documentation review and static analysis, we started the process of manual code inspection. We noted how the contracts were divided into different modules and we inspected the contracts in each module carefully. We stuidied each of the contracts, tested how each function behaves and compared that to how they're expected to behave. We then tried out various attack ideas, including the ones provided by the sponsors. We noted the dependencies, inheritancies, and possible vulnerabilities that can arise from them. We made comparisons to issues found in protocols of the same kind (including older commits) to see if the same mistakes were repeated and how effective the provided fixes were.
After this was done, we made notes on the issues we found and prepared the analysis report.
Overall, I consider the quality of the Salty codebase to be excellent. The code appears to be very mature and well-developed. We have noticed the implementation of various standards adhere to appropriately. Details are explained below:
Codebase Quality Categories | Comments |
---|---|
Code Maintainability and Reliability | The codebase demonstrates moderate maintainability with well-structured functions and comments, promoting readability. It exhibits reliability through defensive programming practices, parameter validation, and handling external calls safely. The use of internal functions for related operations enhances code modularity, reducing duplication. Libraries improve reliability by minimizing arithmetic errors. Adherence to standard conventions and practices contributes to overall code quality. However, full reliability depends on external contract implementations like openzeppelin & uniswap V3 Core |
Code Comments | The contracts have comments that are used to explain the purpose and functionality of different parts of the contracts, making it easier for developers to understand and maintain the code. The comments provide descriptions of methods, variables, and the overall structure of the contract.For-Exmaple: The code comments in the "DAO" contract provide essential information. The imported interfaces and contracts are declared, and the contract's title and purpose are described. |
Testing | The audit scope of the contracts to be audited is 99% and it should be aimed to be 100%. |
Codebase Aspect | Description | Explanation |
---|---|---|
1. Folder Structure | Well-organized folder structure. | - The folder structure facilitates easy navigation. <br> - Each folder has a clear responsibility. |
2. Modularization | Code is divided into logical modules. | - Each section has a primary responsibility. <br> - Modularization facilitates maintenance. |
3. Documentation | Comprehensive code documentation. | - Each function has a clear explanation. <br> - Contracts and critical functions are well-documented. |
4. Security Measures | Prevention and mitigation of security attacks. | - Ongoing audit for potential vulnerabilities. <br> - Protection against reentrancy and overflows. |
5. DAO Governance | Code related to DAO governance. | - DAO adjustable parameters are stored correctly. <br> - Voting functions and proposal handling are documented. |
6. Smart Contract Interaction | Clear smart contract interfaces. | - Functions and parameters are easily understandable. <br> - Inter-contract communication is well-explained. |
7. Price Feeds and Oracle Integration | Use of price aggregators and oracle integration. | - Use of Chainlink and Uniswap TWAP is explained. <br> - Redundancy mechanism and reliability of price aggregator. |
8. Staking and Rewards | Implementation of staking and reward mechanisms. | - Clear explanation of the use of "userShare". <br> - Management of SALT emissions and reward distribution to liquidity providers. |
Exemplary unit test coverage: The codebase shines with its meticulous unit testing strategy. The comprehensive suite of unit tests ensures the reliability and resilience of the system's core functionality, providing confidence in its performance under various scenarios.
Artful integration of Natspec: A commendable strength is the thoughtful integration of Natspec. The use of this documentation format not only improves code readability, but also exemplifies a commitment to providing clear and human-friendly documentation that fosters a more collaborative and accessible development environment.
Opportunities to improve documentation: While the codebase stands out in many ways, there is an opportunity for refinement in the documentation. Addressing this area of improvement can increase the overall clarity of the codebase, make it more accessible, and facilitate seamless collaboration among developers. In essence, the codebase demonstrates proficiency in testing methodologies and documentation practices. Strengthening the documentation further would strengthen the codebase's comprehensibility and contribute to an even more polished and developer-friendly ecosystem.
Upkeep
a complex set of maintenance steps for various contracts and operations within them, including token swaps, arbitrage, reward distribution, and liquidity management.
StakingRewards
StakingRewards abstract contract that provides staking functionality for SALT and issuance of rewards in the form of SALT tokens. These contracts allow for increases and decreases in user stakes, claim of rewards, as well as addition of SALT rewards into a specific pool.
Airdrop
maintains a list of users eligible to claim Salty airdrops. Authorized users can claim a certain amount of SALT after a successful BootstrappingBallot contract. Claims can be made after authorization and when airdrop claims are permitted.
CollateralAndLiquidity
functions as a liquidity and collateral manager on an exchange. Users can deposit collateral (WBTC and WETH), borrow USDS, withdraw collateral, and liquidate user positions that do not meet the minimum collateral ratio. The contract also monitors the amount of USDS borrowed by each user and provides various display functions for value information in USD.
DAO
manages different aspects of the system and provides flexibility to change parameters and perform other management actions through a decentralized voice and decision-making system.
Proposals
to manage voting and proposals in the SALT DAO ecosystem
The DAO has exclusive control over an extensive list of exchange parameters. For safety, parameters are adjusted incrementally or decrementally within a specified range.
bootstrappingRewards
: The amount of SALT provided as a bootstrapping reward for a new pool when a new token is whitelisted. Default: 200k SALT
percentPolRewardsBurned
: For rewards distributed to the DAO, the percentage of SALT that is burned with the remaining staying in the DAO for later use. Default: 50%
baseBallotQuorumPercent
: The minimum amount of xSALT required for ballot quorum. Default: 10%
ballotMinimumDuration
: How many days minimum a ballot has to exist before it can be taken action on. Default: 10 days
requiredProposalPercentStake
: The percent of staked SALT that a user has to have to make a proposal. Default: 0.50%
maxPendingTokensForWhitelisting
: The maximum number of tokens that can be pending for whitelisting at any time. Default: 5
arbitrageProfitsPercentPOL
: The share of the arbitrage profits that are sent to the DAO to form SALT/USDS Protocol Owned Liquidity. Default: 20%
upkeepRewardPercent
: The share of the WETH arbitrage profits sent to the DAO that are sent to the caller of DAO.performUpkeep(). Default: 5%
maximumWhitelistedPools
: The maximum number of pools that can be whitelisted at any one time. Default: 50
maximumInternalSwapPercent
: For swaps internal to the protocol, the maximum swap size as a percent of the reserves. Default: 1%
rewardsEmitterDailyPercentTimes1000
: The target daily percent of rewards distributed by the stakingRewardsEmitter and liquidityRewardsEmitter. Default: 1%
emissionsWeeklyPercentTimes1000
: The weekly percent of SALT emissions that will be distributed from the Emissions contract. Default: 0.5%
stakingRewardsPercent
: The percentage of rewards received by SALT stakers (compared to liquidity providers). Default: 50%
percentRewardsSaltUSDS
: The percent of SALT Rewards that will be sent directly to the SALT/USDS pool. Default: 10%
minUnstakeWeeks
: The minimum number of weeks for an unstake request at which point minUnstakePercent of the original staked SALT is reclaimable. Default: 2 weeks
maxUnstakeWeeks
: The maximum number of weeks for an unstake request at which point 100% of the original staked SALT is reclaimable. Default: 52 weeks
minUnstakePercent
: The percentage of the original staked SALT that is reclaimable when unstaking the minimum number of weeks. Default: 20%
modificationCooldown
: The minimum time between staking and unstaking or between depositing and withdrawing liquidity (to avoid rewards sniping). Default: 1 hour
rewardPercentForCallingLiquidation
: The collateral percent that a user receives for instigating the liquidation process. Default: 5%
maxRewardValueForCallingLiquidation
: The maximum reward value (in USD) that a user receives for instigating the liquidation process. Default: $500 USD
minimumCollateralValueForBorrowing
: The minimum USD value of collateral - to borrow an initial amount of USDS. Default: $2500 USD
initialCollateralRatioPercent
: The initial maximum collateral / borrowed USDS ratio. Default: 200%
minimumCollateralRatioPercent
: The minimum ratio of collateral / borrowed USDS below which positions can be liquidated. Default: 110%
percentArbitrageProfitsForStablePOL
: The percent of arbitrage profits that are used to form USDS/DAI Protocol Owned Liquidity. Default: 5%
maximumPriceFeedPercentDifference
: The maximum percent difference between two non-zero PriceFeed prices when aggregating price. Default: 3%
setPriceFeedCooldown
: The required cooldown between calls to setPriceFeed. Default: 35 days
which could introduce additional risks related to price volatility, liquidity, and slippage. Ensuring adequate liquidity and monitoring gas currency prices is essential to maintain the contract's functionality.
Review gas usage in each function and ensure there are no significant gas leaks.
Evaluate whether the Bisection Search and algebra implementations have been optimized efficiently.
The contract interacts with various external contracts, which could contain bugs or vulnerabilities. Regularly updating the contract and its dependencies can help minimize this risk.
external libraries and interfaces, which could introduce additional risks related to version compatibility, security, and maintenance. Ensuring that the dependencies are up-to-date, well-maintained, and secure is crucial for the contract's long-term viability.
Review governance mechanisms, especially the role of DAOs. Ensure decision-making and asset management policies are well defined.
Review and evaluate oracle security against various types of attacks, including price manipulation attacks or fake data intrusions. Consider using multiple oracles to reduce the risk of a single point of failure. Implement a continuous monitoring system to detect suspicious or unusual price changes. Set early warnings and emergency actions if there are indications of price manipulation or oracle failure.
In general, the Salty project exhibits an interesting and well-developed architecture we believe the team has done a good job regarding the code, but the identified risks need to be addressed, and measures should be implemented to protect the protocol from potential malicious use cases. Additionally, it is recommended to improve the documentation and comments in the code to enhance understanding and collaboration among developers. It is also highly recommended that the team continues to invest in security measures such as mitigation reviews, audits, and bug bounty programs to maintain the security and reliability of the project.
36 hours
#0 - c4-judge
2024-02-03T14:51:43Z
Picodes marked the issue as grade-b