Yeti Finance YETI/WAVAX Swapper
Smart Contract Security Assessment
Dec 07, 2023

SUMMARY
ABSTRACT
Dedaub was commissioned to perform a security audit of Yeti Finance’s contract for swapping YETI to WAVAX tokens.
SETTING & CAVEATS
This audit report mainly covers the code of the Swapper.sol contract of the vault repository found here. Two auditors worked on the contract for 1 day.
The audit report covers commit hash 855f610a18d4f3526f8ff2d7ccaf4fe7d6d57b26.
The audit’s main target is security threats, i.e., what the community understanding would likely call "hacking", rather than the regular use of the protocol. Functional correctness (i.e. issues in "regular use") is a secondary consideration. Typically it can only be covered if we are provided with unambiguous (i.e. full-detail) specifications of what is the expected, correct behavior. In terms of functional correctness, we often trusted the code’s calculations and interactions, in the absence of any other specification. Functional correctness relative to low-level calculations (including units, scaling and quantities returned from external protocols) is generally most effectively done through thorough testing rather than human auditing.
PROTOCOL-LEVEL CONSIDERATIONS
The contract features a sendToken function callable only by the contract's owner. This function aims to prevent the accidental permanent locking of tokens within the contract. For instance, if users fail to claim the entire amount of tokens B in the contract, the owner can reclaim them. Additionally, if someone accidentally sends directly some tokens to the contract, the owner can return them.
However, there is no restriction on the type of token the owner can retrieve from the contract. Notably, the owner can also retrieve tokens A held by the contract. This raises concerns given the contract's intended purpose. While the contract technically exchanges tokens of one type for another at a specified rate, the YETI team designed it to enable YETI (tokenA) holders to redeem them for WAVAX (tokenB) as part of a winding-down procedure.
Despite the Yeti-finance team's intention not to remove YETI from the contract, a malicious owner could acquire YETI and misuse them. We recommend incorporating a require(_address != address(tokenA)) condition in the sendToken function. This modification ensures that tokenA, when swapped through the contract, remains permanently locked there, simulating a burn, which aligns with the expected behavior.
VULNERABILITIES & FUNCTIONAL ISSUES
This section details issues affecting the functionality of the contract. Dedaub generally categorizes issues according to the following severities, but may also take other considerations into account such as impact or difficulty in exploitation:
- User or system funds can be lost when third-party systems misbehave
- DoS, under specific conditions
- Part of the functionality becomes unusable due to a programming error
- Breaking important system invariants but without apparent consequences
- Buggy functionality for trusted users where a workaround exists
- Security issues which may manifest when the system evolves
Issue resolution includes “dismissed” or “acknowledged” but no action taken, by the client, or “resolved”, per the auditors.
CRITICAL SEVERITY
[No critical severity issues]
HIGH SEVERITY
[No high severity issues]
MEDIUM SEVERITY
[No medium severity issues]
LOW SEVERITY
[No low severity issues]
CENTRALIZATION ISSUES
It is often desirable for DeFi protocols to assume no trust in a central authority, including the protocol’s owner. Even if the owner is reputable, users are more likely to engage with a protocol that guarantees no catastrophic failure even in the case the owner gets hacked/compromised. We list issues of this kind below. (These issues should be considered in the context of usage/deployment, as they are not uncommon. Several high-profile, high-value protocols have significant centralization threats.)
The Swapper contract allows the owner to change the exchangeRate through the function setExchangeRate. It is understood that YETI will be swapped for WAVAX at a fixed rate. Therefore this setter function poses a centralisation concern for users of the Swapper contract, as the exchange rate can be changed mid-way through the use of the contract. It is recommended that the exchangeRate be made immutable and assigned in the constructor.
Alternatively, if the development team deems some flexibility necessary to adjust the exchangeRate based on varying market conditions, a minAmountOut argument could be introduced in the swap function. This modification would provide a more controlled and secure means of adjusting the exchangeRate while mitigating the risks associated with potential frontrunning.
OTHER / ADVISORY ISSUES
This section details issues that are not thought to directly affect the functionality of the project, but we recommend considering them.
The tokenA, tokenB and endTime variables do not change after initialisation and can thus be declared immutable.
The constructor should check that _tokenA and _tokenB are not address(0), and that _exchangeRate and _lengthActiveSeconds are non-zero. The function sendToken should check that the recipient is not address(0). The function setExchangeRate should check that _exchangeRate is non-zero.
Due to the way the swap function works, this contract is only usable for swaps where both tokenA and tokenB have the same number of decimal places. It is understood that tokenA will be YETI and tokenB will be WAVAX, which both have 18 decimal places. But we thought we would point out this limitation in case it will be used with different token pairs.
The ERC20 contract is imported twice and one reference can be removed.
In the tests composed for the contract, an inconsistency is observed between the comments and the actual values of the variables. Specifically, there is a comment stating that for the test, 0.01 YETI should be swapped for 1 WAVAX. However, the exchangeRate is set to 1e16, equivalent to 0.01 with 18 decimal precision. Consequently, the accurate calculation results in 1 YETI being swapped for 0.01 WAVAX.
The code is compiled with Solidity 0.8.10. Version 0.8.10, in particular, has some known bugs, which we do not believe affect the correctness of the contracts.
DISCLAIMER
The audited contracts have been analyzed using automated techniques and extensive human inspection in accordance with state-of-the-art practices as of the date of this report. The audit makes no statements or warranties on the security of the code. On its own, it cannot be considered a sufficient assessment of the correctness of the contract. While we have conducted an analysis to the best of our ability, it is our recommendation for high-value contracts to commission several independent audits, a public bug bounty program, as well as continuous security auditing and monitoring through Dedaub Security Suite.
ABOUT DEDAUB
Dedaub offers significant security expertise combined with cutting-edge program analysis technology to secure some of the most prominent protocols in DeFi. The founders, as well as many of Dedaub's auditors, have a strong academic research background together with a real-world hacker mentality to secure code. Protocol blockchain developers hire us for our foundational analysis tools and deep expertise in program analysis, reverse engineering, DeFi exploits, cryptography and financial mathematics.