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: 109/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 cutting-edge decentralized exchange (DEX) built on the Ethereum blockchain, pioneering a revolutionary approach to trading with its Automatic Atomic Arbitrage (AAA) technology. Currently undergoing audit in Code4rena, Salty.IO is set to redefine the landscape of decentralized finance (DeFi) when it launches on March 1, 2024.This Avanced Analysis report provide the detailed Overview & Mechanism of salty Smart conttracts. This report alo provides the associated Centralization and systematic risks related to The salty smart contrats.
Automatic Atomic Arbitrage (AAA)
Salty.IO employs AAA to capitalize on market inefficiencies during swaps, ensuring that profits are generated in real-time. These profits are subsequently distributed to liquidity providers and stakers, forming the foundation of Protocol Owned Liquidity (POL) for the DAO.
Zero Fees and Yield Generation
One of the standout features of Salty.IO is the provision of zero fees on all swaps. This is made possible through the AAA mechanism, creating a unique incentive structure for liquidity providers and stakers to actively participate in the network and share in the generated yield.
USDS Stablecoin
Salty.IO introduces USDS, an overcollateralized ERC20 stablecoin native to the protocol. This stablecoin utilizes WBTC/WETH LP as collateral, adding an additional layer of stability and value to the Salty.IO ecosystem.
Decentralization at its Core
Salty.IO is committed to full decentralization right from its launch. The DAO controls all aspects, including parameters, regional exclusions, whitelisting, and contracts. This ensures a trustless and transparent platform where the community has a direct say in the governance and evolution of the protocol.
SALT Token
The native token of the Salty.IO ecosystem is SALT, an ERC20 token with a capped maximum supply of 100 million tokens. With limited emissions and deflationary mechanics, SALT is designed to be a scarce and valuable asset. Staking SALT enables users to acquire xSALT, a token that serves dual purposes for both yield generation and active participation in governance decisions.
1 . ArbitrageSearch.sol 2 . DAO.sol 3 . DAOConfig.sol 4 . Proposals.sol 5 . Parameters.sol 6 . Airdrop.sol 7 . BootstrapBallot.sol 8 . InitialDistribution.sol 9 . PoolUtils.sol 10 . PoolsConfig.sol 11 . PoolStats.sol 12 . Pools.sol 13 . PoolMath.sol 14 . CoreChainlinkFeed.sol 15 . CoreUniswapFeed.sol 16 . PriceAggregator.sol 17 . CoreSaltyFeed.sol 18 . RewardsConfig.sol 19 . Emissions.sol 20 . RewardsEmitter.sol 21 . SaltRewards.sol 22 . USDS.sol 23 . StableConfig.sol 24 . CollateralAndLiquidity.sol 25 . Liquidizer.sol 26 . StakingConfig.sol 27 . Liquidity.sol 28 . StakingRewards.sol 29 . Staking.sol 30 . ManagedWallet.sol 31 . AccessManager.sol 32 . Salt.sol 33 . SigningTools.sol 34 . Upkeep.sol 35 . ExchangeConfig.sol
ArbitrageSearch is designed to identify profitable arbitrage opportunities within a trading system that involves swapping tokens through a series of pools. The contract is abstract, meaning it is intended to be inherited by other contracts that implement its functionality. The contract focuses on finding a circular trading path that starts and ends with WETH (Wrapped Ether), aiming to capitalize on price discrepancies between different trading pairs.
Immutable Variables
Arbitrage Path Logic
Profitability Estimation
Bisection Search Algorithm
Constants and Assumptions
The DAO contract serves as a governance mechanism for a decentralized platform, allowing stakeholders to propose changes and vote on them.
Proposal and Voting Mechanism
The contract interacts with an IProposals contract, which likely manages the creation and storage of governance proposals. Proposals can be for parameter changes, token whitelisting/unwhitelisting, sending tokens, calling contracts, and updating the website URL.
The contract does not include the voting logic itself but relies on the IProposals contract to track and tally votes. It distinguishes between parameter change votes (increase, decrease, no change) and approval votes (yes or no).
The finalizeBallot function allows anyone to trigger the finalization of a proposal once it meets certain conditions (e.g., minimum end time and quorum). The contract then executes the proposal if it is approved.
Execution of Approved Proposals
If a parameter change is approved, the _finalizeParameterBallot function executes the change by calling _executeParameterChange, which likely adjusts configuration settings in other contracts.
The _finalizeTokenWhitelisting function handles the approval of new tokens to be added to the platform. It ensures that the proposal with the most votes is executed and provides bootstrapping rewards from the DAO's funds.
The _finalizeApprovalBallot function executes various actions based on the type of approval ballot, such as sending tokens, calling contracts, or updating geographical exclusions.
Protocol Owned Liquidity (POL)
The formPOL function allows the DAO to create liquidity pairs using its funds. It assumes the tokens are already transferred to the DAO and uses a collateralAndLiquidity contract to deposit the liquidity.
The processRewardsFromPOL function claims rewards from the liquidity pools owned by the DAO and distributes them, burning a portion as per the DAO's configuration.
The withdrawPOL function allows the DAO to withdraw liquidity from the pools to cover shortfalls in liquidation processes, sending the underlying tokens to a liquidizer contract.
Arbitrage Profits
Access Control and Geographical Exclusions
The contract maintains a list of excluded countries, which can be updated through governance proposals. This affects access to the DEX and is enforced by an AccessManager contract.
The DAOConfig contract is a Solidity smart contract designed to be owned and controlled by a Decentralized Autonomous Organization (DAO). It contains a set of parameters that govern various aspects of the DAO's operations, such as rewards, quorums for voting, proposal requirements, and more.
bootstrappingRewards
percentPolRewardsBurned
baseBallotQuorumPercentTimes1000
ballotMinimumDuration
requiredProposalPercentStakeTimes1000
maxPendingTokensForWhitelisting
arbitrageProfitsPercentPOL
upkeepRewardPercent
The Proposals contract is part Salty system that allows stakeholders of the SALT token to propose and vote on various types of ballots. These include parameter changes, token whitelisting/unwhitelisting, sending tokens, calling contracts, and updating website URLs. The contract ensures the uniqueness of ballots, tracks and validates user voting power, enforces quorums, and allows users to alter their votes.
Proposal Creation
Voting Mechanism
Ballot Types
Quorum and Approval
Finalization
Views and Helpers
Parameters.solincludes an enumeration ParameterTypes that lists various configuration parameters across different modules of the platform, such as PoolsConfig, StakingConfig, RewardsConfig, StableConfig, DAOConfig, and PriceAggregator.
The contract's primary function _executeParameterChange takes a ParameterTypes value, a boolean increase, and interfaces to various configuration modules. Depending on the parameterType provided, the function calls the appropriate method on the corresponding configuration module to either increase or decrease the parameter value.
Airdrop.sol is intended to distribute a token called SALT to users who have participated in certain promotional activities, such as retweeting a launch announcement and voting. The contract is designed to work in conjunction with other contracts, specifically an IExchangeConfig for configuration parameters, an IStaking contract for staking functionality, and a token contract ISalt representing the SALT token.
Initialization
Authorization
Claiming Process
Claiming Airdrop
Views
The BootstrapBallot contract is designed to facilitate a voting process for airdrop participants to decide whether to launch an exchange and establish initial geographic restrictions. The contract is linked to an IExchangeConfig interface to interact with exchange configuration settings and an IAirdrop interface to manage airdrop authorizations.
Initialization
Voting
Airdrop Authorization
Finalization
Event Logging
The InitialDistribution contract is designed to handle the initial distribution of the SALT token to various stakeholders and systems within a Salty ecosystem. The contract is responsible for allocating tokens to emissions, a DAO reserve, the initial development team, airdrop participants, and for liquidity and staking bootstrapping.
The distributionApproved function is the core of this contract, which is called when the BootstrapBallot is approved. It performs the following actions
The PoolUtils contract is intendeds managing liquidity pools and performing token swaps. The library includes functions for generating unique pool identifiers for pairs of ERC20 tokens, and for executing internal swaps within the protocol with certain restrictions to mitigate the profitability of sandwich attacks.
Pool Identifier Generation
_poolID
: Generates a unique identifier (poolID) for a pair of ERC20 tokens by sorting the addresses of the tokens and hashing them together. This ensures that the order of the tokens does not affect the poolID._poolIDAndFlipped
: Similar to _poolID, but also returns a boolean indicating whether the order of the tokens was flipped to generate the poolID.Internal Swap Mechanism
_placeInternalSwap
: This function allows for swapping tokens within the protocol. It takes into account the current reserves of the input token (tokenIn) in the liquidity pool and limits the amountIn to a certain percentage of the reserves, defined by maximumInternalSwapPercentTimes1000. This is designed to reduce the effectiveness of sandwich attacks by limiting the size of the swap and allowing for atomic arbitrage within the same transaction.The PoolsConfig contract is designed to manage the configuration of Salty liquidity pools. It is intended to be owned and controlled by a Decentralized Autonomous Organization (DAO), which has the exclusive authority to modify the contract's state. The contract provides functionality to whitelist and unwhitelist token pairs for liquidity pools, adjust the maximum number of whitelisted pools, and set limits on internal swap sizes as a percentage of the pool's reserves.
Whitelisting Pools
Unwhitelisting Pools
Adjusting Maximum Whitelisted Pools
Adjusting Maximum Internal Swap Size
Views
The PoolStats is designed to work with a set of whitelisted pools that participate in triangular arbitrage opportunities involving a wrapped Ether (WETH) token and two other arbitrary tokens (arbToken2 and arbToken3). The contract is responsible for recording profits from arbitrage, resetting these stats, updating indices of pools involved in arbitrage, and calculating the distribution of rewards based on the profits generated.
Arbitrage Profit Tracking
Profit Resetting
Index Mapping
Updating Arbitrage Indices
Calculating Arbitrage Profits
View Functions
The Pools contract is designed to manage liquidity pools for a Salty (DEX). It handles the addition and removal of liquidity, token swaps, and arbitrage opportunities. The contract is built on the Ethereum blockchain using the Solidity programming language and is compatible with the ERC-20 token standard.
Liquidity Management
Token Deposits and Withdrawals
Swaps and Arbitrage
Contract Initialization and Management
The PoolMath cntract is designed to assist with calculations related to adding liquidity ,specifically for pools that follow the constant product formula (x * y = k). The library is intended to be used with pools where liquidity providers can "zap" in liquidity by depositing uneven amounts of two tokens. The goal is to determine the optimal amount of one token to swap for the other before adding liquidity to ensure that the deposited tokens maintain the same ratio as the pool's reserves, minimizing slippage and leftover funds.
The library contains several functions
_mostSignificantBit
: Finds the most significant bit (MSB) of a non-zero number, which is used to determine the bit length of the number._maximumMSB
: Determines the maximum MSB across four given values, which is used to normalize the values for calculations._zapSwapAmount
: Calculates the amount of token0 that needs to be swapped to token1 before adding liquidity to the pool. This function uses a quadratic equation derived from the constant product formula to find the optimal swap amount that aligns the ratio of the zapped amounts with the pool's reserves ratio._determineZapSwapAmount
: Determines whether a swap is necessary before adding liquidity and, if so, which token and how much of it needs to be swapped.The library uses a quadratic equation to solve for the swap amount and employs bit-shifting to normalize values for calculations, ensuring that the operations do not exceed the 256-bit limit of Solidity integers.
The CoreChainlinkFeed contract is designed to provide the latest price data for Bitcoin (BTC) and Ethereum (ETH) in USD using Chainlink's decentralized oracle network. It implements an interface IPriceFeed which is not shown in the provided code but is expected to define the functions for retrieving price data. The contract uses two immutable public variables, CHAINLINK_BTC_USD and CHAINLINK_ETH_USD, which are references to Chainlink's AggregatorV3Interface for BTC/USD and ETH/USD price feeds, respectively.
Immutable Oracle References
Price Retrieval
Freshness Check
Error Handling
Negative Price Check
The CoreUniswapFeed contract provides time-weighted average price (TWAP) data for WBTC (Wrapped Bitcoin) and WETH (Wrapped Ether) using Uniswap v3 pools. It is designed to fetch prices with a 30-minute TWAP period to mitigate the risk of price manipulation. The contract uses two Uniswap v3 pools: one for WBTC/WETH and another for WETH/USDC (USD Coin).
TWAP Calculation
Token Order Handling
Price Retrieval Functions
External Interface
The PriceAggregator contract is designed to provide reliable price feeds for BTC and ETH by aggregating data from three different external price feed sources. The contract is intended to mitigate the risk of a single point of failure by using multiple feeds and discarding outliers. The contract is updatable, meaning the price feeds can be changed, but with a cooldown period to ensure stability and allow for performance review.
Initial Setup
Updating Price Feeds
Cooldown Management
Price Feed Difference Threshold
Price Aggregation
Price Retrieval
The CoreSaltyFeed contract is designed to provide price feeds for Bitcoin (BTC) and Ethereum (ETH) using the Salty.IO pools. It is intended to be used in a decentralized finance (DeFi) ecosystem where accurate and reliable price information is crucial for various financial instruments and smart contracts. The contract interacts with an external IPools interface to retrieve the reserves of wrapped Bitcoin (WBTC), wrapped Ethereum (WETH), and a stablecoin (USDS) from liquidity pools. The contract assumes that WBTC and WETH are ERC20 tokens with 8 and 18 decimals, respectively, while USDS also has 18 decimals.
Immutable References
The RewardsConfig is designed to manage the distribution of rewards.RewardsConfig includes mechanisms to set the daily and weekly percentages of rewards distribution, the split of rewards between stakers and liquidity providers, and the specific allocation to the SALT/USDS pool.
rewardsEmitterDailyPercentTimes1000
emissionsWeeklyPercentTimes1000
stakingRewardsPercent
percentRewardsSaltUSDS
RewardsConfig provides four functions to adjust these parameters, each of which can only be called by the owner (the DAO):
changeRewardsEmitterDailyPercent(bool increase)
changeEmissionsWeeklyPercent(bool increase)
changeStakingRewardsPercent(bool increase)
changePercentRewardsSaltUSDS(bool increase)
Each function checks whether the increase flag is true or false and adjusts the corresponding variable within the allowed range. After the change, an event is emitted to log the new value.
The Emissions contract is designed to manage and distribute the emissions of the SALT token over time. It interacts with several other contracts, including ISaltRewards, IExchangeConfig, IRewardsConfig, and ISalt. it is intended to distribute SALT tokens to two types of emitters: stakingRewardsEmitter and liquidityRewardsEmitter, which are managed through the SaltRewards contract.
The performUpkeep function is the core of the contract, which is called to distribute the SALT tokens. The function takes timeSinceLastUpkeep as an argument, which is used to calculate the amount of SALT to distribute.
The distribution logic works as follows:
The RewardsEmitter is designed to manage and distribute SALT token rewards to participants in a staking ecosystem. It supports two types of reward distributions:
Reward Addition (addSALTRewards)
Reward Distribution (performUpkeep)
Views
The SaltRewards contract is a utility contract designed to distribute SALT token rewards to participants . It interacts with two types of reward emitters: stakingRewardsEmitter and liquidityRewardsEmitter. The contract is responsible for temporarily holding SALT rewards that are generated from emissions and arbitrage profits, and then distributing these rewards to stakers and liquidity providers.
Initialization: Saltrewards is initialized with references to the stakingRewardsEmitter, liquidityRewardsEmitter, exchangeConfig, and rewardsConfig. It also caches the SALT token contract and the SALT/USDS pool ID for efficiency. The contract sets an unlimited approval for the SALT token to both reward emitters to facilitate reward distribution without requiring repeated approvals.
Reward Distribution
Reward Calculation
Internal Functions
The USDS contract is an ERC20 token that represents a stablecoin, which can be borrowed by users who have deposited collateral in the form of WBTC/WETH liquidity. The contract interacts with another contract, ICollateralAndLiquidity, which handles the collateral management. The USDS contract includes functions to mint new tokens and burn existing tokens.
Minting USDS
Burning USDS
Ownership and Permissions
The StableConfig contract is a parameter configuration designed to be owned and controlled by a Decentralized Autonomous Organization (DAO). It allows the DAO to adjust various parameters related to liquidation rewards, collateral requirements, and profit sharing within the protocol.
rewardPercentForCallingLiquidation
maxRewardValueForCallingLiquidation
minimumCollateralValueForBorrowing
initialCollateralRatioPercent
minimumCollateralRatioPercent
percentArbitrageProfitsForStablePOL
The CollateralAndLiquidity is designed to manage collateralized borrowing and liquidity provision on a decentralized exchange. Users can deposit WBTC (Wrapped Bitcoin) and WETH (Wrapped Ether) as collateral to borrow a stablecoin called USDS. This also allows users to withdraw their collateral and claim rewards, borrow USDS against their collateral, and repay borrowed USDS.
Collateral Deposit and Withdrawal
Borrowing and Repayment
Liquidation
Views and Utility Functions
The Liquidizer contract is designed to maintain the stability of a collateralized lending system by managing the liquidation process and POL . Its primary function is to convert various tokens received from liquidated collateral or withdrawn POL into USDS (a stablecoin) and then burn the USDS to maintain the system's collateral balance.
Token Handling
Contract Initialization
Ownership and Permissions
Liquidation Handling
Burning Mechanism
POL Management
Token Swapping
Event Logging
The StakingConfig contract is designed to manage the configuration parameters for a staking system with the ability to modify certain parameters related to unstaking periods and percentages, as well as cooldowns for modifications to prevent gaming of the system.
minUnstakeWeeks
Each parameter has a specific range and adjustment granularity:
minUnstakeWeeks
: 1 to 12 weeks, adjustable by 1 week.maxUnstakeWeeks
: 20 to 108 weeks, adjustable by 8 weeks.minUnstakePercent
: 10% to 50%, adjustable by 5%.modificationCooldown
: 15 minutes to 6 hours, adjustable by 15 minutes.The contract provides four functions to adjust these parameters, each emitting an event upon a successful change:
changeMinUnstakeWeeks(bool increase)
changeMaxUnstakeWeeks(bool increase)
changeMinUnstakePercent(bool increase)
changeModificationCooldown(bool increase)
The Liquidity contract is designed to manage liquidity provision and withdrawal . The contract allows users to deposit two types of ERC20 tokens into a liquidity pool, potentially using a zapping mechanism to balance the token amounts, and to withdraw their liquidity later on. Users receive liquidity shares that entitle them to a proportion of future rewards.
Liquidity Provision (_depositLiquidityAndIncreaseShare)
Liquidity Withdrawal (_withdrawLiquidityAndClaim)
Public Wrappers
The StakingRewards contract is designed to handle the distribution of rewards, specifically SALT tokens, to users who stake either SALT tokens or liquidity shares. The contract is abstract, meaning it is intended to be inherited by other contracts that define specific behaviors for different types of staking (e.g., staking SALT tokens or liquidity pool shares).
Staking and Unstaking
Reward Calculation
**Cooldown Period*8
Claiming Rewards
Adding Rewards
Staking contract for a token called SALT, which allows users to stake SALT tokens in exchange for xSALT tokens at a 1:1 ratio. The contract includes functionality for staking, unstaking with a cooldown period, expedited unstaking with a fee, and recovering staked tokens after the unstaking period. It also allows for the transfer of xSALT from an airdrop contract to a user.
Staking
Unstaking
Expedited Unstaking
Recovering Staked Tokens
Cancel Unstake
Airdrop Transfers
The ManagedWallet contract is designed to manage two wallet addresses: a main wallet and a confirmation wallet. These wallets can be changed through a specific process that involves proposals, confirmations, and a timelock mechanism. The contract is intended to provide a secure way to update wallet addresses, potentially for a system where these wallets have significant permissions or control over assets.
Proposal Mechanism
Confirmation Mechanism
Timelock Mechanism
Events
The Acessmanger contract is designed to comply with regional regulations by restricting certain actions such as adding liquidity, collateral, and borrowing a stablecoin (presumably USDS) based on the user's geolocation. The contract allows for the removal of assets by users even if their region becomes restricted after depositing, ensuring that users are not locked out of their funds.
DAO Integration
GeoVersioning
Access Granting
Access Verification
Access Storage
Event Logging
The Salt contract is an ERC20 token with an additional burn feature. The contract inherits from OpenZeppelin's ERC20 standard implementation and implements an interface ISalt. The contract is intended to be used on the Ethereum blockchain, as indicated by the use of ether units in the constants.
Initial Supply
Token Burning
Total Burned
The contract SigningTools that contains a single function _verifySignature. This function is designed to verify that a given messageHash has been signed by a specific signer, whose address is hardcoded as EXPECTED_SIGNER. The purpose of this library is to provide a means of verifying the authenticity of messages, ensuring that they have been signed by the expected authority before being processed further.
The _verifySignature function takes two parameters:
a messageHash of type bytes32, which represents the hash of the original message, and a signature of type bytes, which is the signature produced by signing the messageHash with the private key corresponding to EXPECTED_SIGNER.
*The function performs the following steps:
It checks that the length of the signature is exactly 65 bytes, which is the standard length of an Ethereum signature consisting of the r, s components, and the v recovery id.
It uses inline assembly to extract the r, s, and v components from the signature. Inline assembly is used for efficiency and direct access to the EVM's instruction set.
It calls the ecrecover function, which is a built-in Ethereum function that takes a hash and a signature (v, r, s) and returns the address that was used to sign the hash.
It compares the recovered address with the EXPECTED_SIGNER and returns true if they match, indicating that the signature is valid and was indeed signed by the expected signer.
The Upkeep contract is designed to automate various maintenance tasks for a DeFi ecosystem. It interacts with multiple contracts to manage liquidity, rewards, and token emissions. The contract is non-reentrant and uses OpenZeppelin's SafeERC20 library for safe token transfers.
Ukeep.sol performs the following tasks:
Token Swap and Burn
The ExchangeConfig contract is a configuration management contract for a decentralized exchange or DeFi protocol. It is designed to hold references to various components of the protocol, such as token contracts (wbtc, weth, dai, usds), a DAO contract, an upkeep contract, initial distribution and airdrop mechanisms, and vesting wallets for the team and DAO. The contract is owned by a DAO, and only the DAO can modify its parameters.
Immutable References
Contract Initialization
Access Management
Events
Only the DAO can finalize ballots, which means that the DAO has control over when a ballot's results are recognized.
Enforces a delay (firstPossibleProposalTimestamp) before which no proposals can be made. This could be seen as a centralizing factor as it temporarily prevents stakeholders from participating in governance.
The voting mechanism relies on off-chain signature verification, which introduces a centralization risk if the entity responsible for generating signatures acts maliciously or is compromised.
The owner has the power to whitelist and unwhitelist pools, which could be used to favor certain token pairs or exclude others, potentially impacting the protocol's fairness and market dynamics.
The clearProfitsForPools function introduces a centralization risk as it can only be called by the Upkeep contract. If the Upkeep contract is controlled by a single entity, they have the power to reset profits at will.
The CollateralAndLiquidity contract has exclusive rights to call addLiquidity and removeLiquidity, centralizing control over liquidity management to a single contract.
The addSALTRewards function can be a point of centralization if the entity responsible for calling it has too much control over when and how rewards are distributed.
The confirmationWallet has significant power as it can unilaterally confirm or reject proposals. If this wallet is controlled by a single entity, it represents a central point of failure.
The quorum is calculated based on the total SALT staked. If a small group accumulates a large amount of SALT, they could potentially manipulate quorums and influence ballot outcomes.
Voting power is based on the user's share of staked SALT. If a user changes their stake after voting, they must recast their vote. This could lead to discrepancies in vote power if not properly managed.
If the cost of acquiring enough SALT to influence a vote is lower than the potential gain from manipulating a vote, it could incentivize economic attacks.
The voting mechanism relies on off-chain signature verification, which introduces a centralization risk if the entity responsible for generating signatures acts maliciously or is compromised.
All votes are weighted equally, regardless of the number of tokens held by the voter. This could be seen as a risk if the intention was to weight votes by stake size.
The hardcoded limits on the number of whitelisted pools and the internal swap size could lead to systemic issues if they are not set appropriately in response to changing market conditions.
The arbitrage mechanism relies on the assumption that the pools are large and liquid enough to allow for profitable arbitrage without causing significant slippage.
The bit-shifting technique used for normalization can lead to precision loss, especially for very small amounts of tokens. This could result in suboptimal swaps or failure to perform a swap when necessary.
The Uniswap pool addresses are immutable, meaning that if there is a need to switch to different pools due to liquidity concerns or other reasons, the contract cannot be updated and a new contract must be deployed.
The cooldown period is a safety feature, but it also means that if a price feed becomes compromised, it cannot be replaced immediately. This could lead to a period where accurate price data is not available.
If the emissions rate is too high or too low, it could have adverse effects on the token's economy, such as inflation or deflation.
The performUpkeep function's reliance on the timeSinceLastUpkeep parameter means that if the upkeep contract fails to call this function regularly, the reward distribution could be delayed or disrupted.
The balance between the rewardPercentForCallingLiquidation and the minimumCollateralRatioPercent is critical. If the reward is too high relative to the collateral ratio, it could incentivize premature or unnecessary liquidations, destabilizing the protocol.
Adjusting the percentArbitrageProfitsForStablePOL affects how much profit is reinvested into the protocol versus distributed elsewhere. This could impact the protocol's long-term sustainability and growth.
Liquilizer contract attempts to mitigate market impact by burning SALT directly. However, large swaps of WBTC, WETH, or DAI to USDS could still affect market prices, especially if the internal swap limits are not properly configured.
The StakinRewards uses division for calculating rewards, which can lead to precision loss. This is mitigated by favoring the protocol in rounding decisions, but it could still lead to discrepancies over time.
The burnTokensInContract function allows anyone to burn tokens that are sent to the contract. If someone accidentally sends tokens to the contract, those tokens can be burned by anyone, leading to potential loss of funds.
Ukeep contract approves an unlimited amount of WETH to the pools contract, which could be risky if the pools contract is compromised.
Each contract serves a specific purpose, promoting modularity and encapsulation of functionalities. Contracts such as ArbitrageSearch.sol, DAO.sol, and Pools.sol have distinct roles, enhancing code readability and maintainability.
The use of immutable references in contracts like DAO.sol and ArbitrageSearch.sol ensures consistency and minimizes the risk of unintentional changes.
The DAO.sol contract serves as a governance mechanism, enabling stakeholders to propose changes and vote on them. This promotes a decentralized decision-making process.
The DAOConfig.sol contract consolidates parameters governing various aspects of DAO operations. This design choice enhances flexibility and allows for easy adjustments.
The Proposals.sol contract implements a robust voting mechanism with features like proposal creation, quorum requirements, and finalization logic. This organized approach contributes to transparent and democratic governance.
The Pools.sol contract efficiently manages liquidity pools, handling operations such as adding/removing liquidity, token deposits/withdrawals, swaps, and arbitrage opportunities. This modular approach simplifies the implementation and maintenance of liquidity-related functionalities.
The PoolStats.sol contract introduces a well-organized method for tracking arbitrage profits, updating indices, and calculating rewards. This design supports efficient profit distribution and contributes to the overall stability of the system.
Contracts like CoreChainlinkFeed.sol and CoreUniswapFeed.sol expose external interfaces (e.g., IPriceFeed) for seamless integration with other components, promoting interoperability and ease of use.
Contracts incorporate error handling mechanisms, such as try-catch blocks, to gracefully handle potential issues, enhancing the overall robustness of the system.
Naming conventions are consistently applied throughout the codebase, improving code readability and maintainability.
Understanding the architecture of different contracts within Salty.io, such as DAO, Proposals, and Pools, provides insights into how complex systems are structured in decentralized applications. This helps in grasping the principles of modular design and contract interaction.
The review highlights the implementation of governance mechanisms, including proposal creation, voting, and execution. Learning how DAOs manage decision-making and execute proposals adds knowledge about governance in decentralized ecosystems.
The codebase review has shed light on various security measures, such as access control, error handling, and checks for potential vulnerabilities. Learning from these security practices is crucial for writing secure and robust smart contracts.
Examining configurable parameters related to economic incentives, arbitrage profits, and rewards provides insights into the economic models behind decentralized systems. Understanding the economic considerations is essential for designing sustainable and incentivized ecosystems.
The integration of various contracts, such as Uniswap, Chainlink, and staking contracts, demonstrates how smart contracts interact with external systems. This knowledge is crucial for building interoperable and connected decentralized applications.
Understanding how TWAP is calculated using Uniswap v3 pools contributes to skills related to obtaining and processing time-sensitive data in decentralized finance applications.
The use of bit manipulation techniques in the PoolMath contract demonstrates efficiency in dealing with large numbers within the constraints of Solidity. This knowledge is beneficial for optimizing gas usage in smart contracts.
The adoption of a bisection search algorithm in _bisectionSearch for finding the optimal arbitrage amount reflects an efficient approach in handling unimodal profit functions.
Evaluating the clarity of the code and the presence of documentation contributes to an understanding of best practices for code readability and the importance of providing clear documentation for others and future maintainers.
Consider implementing a mechanism where multiple entities or a decentralized network can collectively finalize ballots to avoid concentration of power within the DAO.
Instead of enforcing a fixed delay, explore options for a more flexible proposal timing mechanism that adapts to changing circumstances and prevents undue centralization.
Evaluate the feasibility of moving signature verification on-chain to reduce reliance on off-chain entities, enhancing the security of the voting mechanism.
Restrict the owner's ability to whitelist and unwhitelist pools, possibly through a decentralized governance process, to ensure fair treatment of all token pairs.
Explore ways to decentralize the control over profit resets, ensuring that the ability to invoke clearProfitsForPools is not concentrated in the hands of a single entity.
Consider allowing multiple contracts or entities to participate in liquidity management to avoid concentration of control within the CollateralAndLiquidity contract.
Evaluate options for distributing rewards through a decentralized process, reducing the centralization risk associated with the addSALTRewards function.
Explore a decentralized approach to proposal confirmation to avoid a single point of failure, possibly by involving multiple confirmation wallets.
Introduce mechanisms to prevent a small group from accumulating a disproportionately large amount of SALT to manipulate quorums, such as imposing limits on individual holdings.
Implement a system to automatically recast votes when users change their stake after voting to maintain the integrity of the voting power distribution.
Constantly monitor the cost of acquiring influence and adjust the economic parameters to minimize the risk of economic attacks.
Consider implementing a voting system that weights votes based on the number of tokens held by the voter to better align with stake size.
Instead of hardcoded limits, explore dynamic adjustments for the number of whitelisted pools and internal swap size to adapt to changing market conditions.
Regularly assess and adjust the arbitrage mechanism to ensure its effectiveness, especially in response to changes in pool size and market conditions.
Evaluate alternative techniques to address precision loss in token amounts, ensuring optimal swaps and preventing failures in critical situations.
Instead of approving an unlimited amount, restrict the approval of WETH to the pools contract to a specific and reasonable amount, minimizing potential risks if the pools contract is compromised.
the thorough audit of the Salty.io protocol as part of the Code4Rena Audit Contest has provided valuable insights into the platform's strengths and areas for enhancement. The team's innovative approach to decentralized governance and liquidity management is commendable, showcasing a deep understanding of the evolving landscape of decentralized finance. The identified centralization risks, including concentrated control over certain functions, have been addressed with constructive recommendations aimed at fostering decentralization and minimizing potential vulnerabilities. Additionally, systematic risks related to governance manipulation and voting power discrepancies have been highlighted, prompting recommendations to strengthen these aspects for a fair and secure governance process. The precision and flexibility of various calculations have been examined, and proposed measures seek to enhance the precision of critical operations. The forward-looking recommendations provided are geared towards continuous improvement, emphasizing the importance of adaptability in the dynamic decentralized finance ecosystem. Overall, the Salty.io team's commitment to transparency and security is evident, and we anticipate the implementation of these recommendations will contribute to the platform's long-term success in the decentralized finance space.
Firstly, I would like to express my appreciation for the opportunity to conduct an in-depth audit of the Salty.io protocol as part of the Code4Rena Audit Contest. It has been a rigorous and enlightening process, and your commitment to transparency and security is commendable.
Throughout the audit, we delved deep into the intricacies of your smart contracts, scrutinizing every line of code to ensure the robustness and integrity of the Salty.io protocol. The complexity and innovation embedded in your decentralized governance and liquidity management mechanisms are notable.
Our analysis revealed several strengths in the protocol, such as the well-structured governance model, the implementation of safety features like cooldown periods, and the efforts made to mitigate economic attacks. We acknowledge the thoughtfulness put into the protocol's design and the mechanisms in place to maintain a fair and efficient ecosystem.
However, as with any sophisticated system, we also identified areas where enhancements could be considered to further fortify the protocol. Addressing potential centralization risks, refining voting mechanisms, and ensuring precision in various calculations were among the key recommendations made to optimize the Salty.io protocol.
It is important to recognize that the audit process is not only about identifying weaknesses but also about providing constructive feedback to facilitate continuous improvement. We are confident that with your team's dedication and the community's support, Salty.io has the potential to become a robust and secure platform for decentralized finance.
Thank you once again for entrusting Code4Rena with the audit of Salty.io. We look forward to witnessing the continued evolution of your project and its positive impact on the decentralized finance landscape.
21 hours
#0 - c4-judge
2024-02-03T14:50:00Z
Picodes marked the issue as grade-b