Introduction
We express our gratitude to the Odin Liquidity Network team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Odin Liquidity Network is a decentralized liquidity network designed to provide sustainable yield, reduce token supply through deflation, and empower a thriving, self-sustaining ecosystem.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for Odin Liquidity Network |
Audited By | Viktor Lavrenenko, Viktor Raboshchuk |
Approved By | Ataberk Yavuzer |
Website | https://www.odinliquidity.network→ |
Changelog | 18/12/2024 - Preliminary Report |
20/12/2024 - Final Report | |
Platform | Ethereum |
Language | Solidity |
Tags | ERC20, Ownable, UniswapV2 |
Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Odin Liquidity Network
- Audited By
- Viktor Lavrenenko, Viktor Raboshchuk
- Approved By
- Ataberk Yavuzer
- Changelog
- 18/12/2024 - Preliminary Report
- 20/12/2024 - Final Report
- Platform
- Ethereum
- Language
- Solidity
- Tags
- ERC20, Ownable, UniswapV2
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
---|---|
Repository | https://etherscan.io/token/0xDfC5964141c018485b4d017634660f85aa667714#code→ |
Commit | N/A |
Review Scope
- Commit
- N/A
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are complete:
The project's purpose is described.
Business logic is provided.
Features of the project are described.
Technical description is partially provided:
Natspecs are missing for the
DejitaruOdin
contract.Architectural overview is missing.
Detailed explanation for roles and authorization are missing (E.g. Described roles and their access rights within the system).
No information on used technologies provided(E.g. implemented standards, utilized libraries, etc).
Code quality
The code duplicates commonly known contracts instead of reusing them.
The development environment is missing since the code was already deployed.
System Overview
The initial goal of this assessment involved verifying that the contract possesses no ownership and is unlikely to perform any malicious actions. This included confirming the renouncement of ownership and ensuring the absence of hidden functionalities that could be exploited. It is important to note that the overall security of the code is not assured, as the contract is immutable and was never intended to be modified post-deployment. The evaluation was limited to verifying the contract's behavior, as requested by the client, without addressing or fixing any potential vulnerabilities.
Odin Liquidity Network is a decentralized liquidity network with the following contracts in the scope:
DejitaruOdin.sol - an ERC-20 token that mints all initial supply to the deployer. Additional minting is not allowed. The token contract contains additional functionality to exclude addresses from paying the fees, as well as setting the limits for user balances and transaction amounts.
It has the following attributes:
Name: Dejitaru Odin
Symbol: ODIN
Decimals: 18
Total supply: 500M tokens.
Privileged roles
The owner of the
DejitaruOdin
contract can:transfer ownership to another address.
enable trading via
enableTrading()
function.remove limits after the token is stable via the
removeLimits()
function.change the minimum amount of tokens to sell from fees via the
updateSwapTokensAtAmount()
function.update the max transaction amount via the
updateMaxTxnAmount()
function.update the max wallet amount via the
updateMaxWalletAmount()
function.exclude the address from the max transaction amount via the
excludeFromMaxTransaction()
function.disable the swap operations via
updateSwapEnabled()
function.update buy and sell fees via
updateBuyFees()
andupdateSellFees()
functions.exclude the address from fees via the
excludeFromFees()
function.update the developer wallet via
updateDevWallet()
function.
The currently deployed version of the contract is renounced, meaning the current owner of the contract is
address(0)
, which means that all of the functions above cannot be called anymore. The code of the contract can be deployed with varying settings. In such instances, a new contract will be created with its own address and different configurations, allowing the functionalities described above to be utilized. However, for the current contract, certain specified functions cannot be accessible.
Potential Risks
Interactions with External DeFi Protocols: The DejitaruOdin
contract interacts with several out-of-scope contracts including TSUKA
and UniswapV2Router02
. Dependence on external DeFi contracts and protocols inherits their risks and vulnerabilities. This might lead to direct financial losses if these protocols are exploited, indirectly affecting the audited project.
Risk of Using Hardcoded Addresses: The contract DejitaruOdin
contains a hardcoded address (TSUKA = 0xc5fB36dd2fb59d3B98dEfF88425a3F425Ee469eD) that lacks a setter function or mechanism for modification. This presents an operational risk, as the inability to update the address can lead to problems in the future.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2024-7749 | Incorrect Comment Regarding WETH in swapTokensForTSUKA() | accepted | Observation | |
F-2024-7738 | Lock of Native Tokens | accepted | Observation | |
F-2024-7708 | Redundant Use of SafeMath Leads to Unnecessary Gas Costs in Arithmetic Operations | accepted | Observation |
Identify vulnerabilities in your smart contracts.
Appendix 1. Definitions
Severities
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
Potential Risks
The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
---|---|
Repository | https://etherscan.io/token/0xDfC5964141c018485b4d017634660f85aa667714#code→ |
Commit | N/A |
Whitepaper | Whitepaper→ |
Requirements | Requirements→ |
Technical Requirements | Technical Requirements→ |
Scope Details
- Commit
- N/A
- Whitepaper
- Whitepaper→
- Requirements
- Requirements→
- Technical Requirements
- Technical Requirements→
Assets in Scope
DejitaruOdin.sol
IUniswapV2Factory.sol
IUniswapV2Router02.sol
Appendix 3. Additional Valuables
Verification of System Invariants
During the audit, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Due to the complex and dynamic interactions within the protocol, unexpected edge cases might arise. Therefore, it was important to use fuzz-testing to ensure that several system invariants hold true in all situations.
Fuzz-testing allows the input of many random data points into the system, helping to identify issues that regular testing might miss. A specific Echidna fuzzing suite was prepared for this task, and throughout the assessment, 7 invariants were tested over 100,000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.
Invariant | Test Result | Run Count |
---|---|---|
testUpdateSwapTokensAtAmountFuzz : This test uses fuzzing on the newAmount parameter to ensure that updateSwapTokensAtAmount enforces its constraints. If newAmount is less than 0.001% or greater than 0.5% of total supply, the call must revert. Otherwise, the swapTokensAtAmount should be successfully updated to newAmount. | Passed | 100k+ |
testFuzz_updateMaxTxnAmount : This test fuzzes newNum to verify that updateMaxTxnAmount enforces its minimum limit of 0.1% of total supply. If newNum is below the minimum, the function should revert. Otherwise, it updates maxTransactionAmount correctly. | Passed | 100k+ |
testFuzz_updateMaxWalletAmount : This test fuzzes newNum to ensure updateMaxWalletAmount enforces its minimum limit of 0.5% of total supply. If newNum is below that limit, the call reverts; otherwise, maxWallet updates correctly. | Passed | 100k+ |
testFuzz_excludeFromMaxTransaction : This test verifies that calling excludeFromMaxTransaction sets the internal state correctly for any given address and boolean. No revert is expected; it simply updates the internal mapping. | Passed | 100k+ |
testFuzz_excludeFromFees : This test checks that excludeFromFees updates the fee exclusion mapping as intended. For any given address and boolean value, the contract should reflect that address’s fee exclusion status correctly. | Passed | 100k+ |
testFuzz_updateDevWallet : This test ensures the owner can update the devWallet address. It checks that after calling updateDevWallet with a new address, the devWallet field matches that new address. | Passed | 100k+ |
testFuzz_Transfer : This test fuzzes transferAmount to verify multiple conditions of the _transfer logic indirectly via the public transfer function. If trading is not active and the transfer is nonzero, the call should revert. If trading is not active and the transfer is zero, it should succeed (no tokens move). After enabling trading, if a transfer would exceed the recipient’s maxWallet limit, it should revert. If the recipient’s balance stays within maxWallet and the sender has enough tokens, the transfer should succeed and update balances correctly. | Passed | 100k+ |
Invariant
testUpdateSwapTokensAtAmountFuzz
: This test uses fuzzing on the newAmount parameter to ensure that updateSwapTokensAtAmount enforces its constraints. If newAmount is less than 0.001% or greater than 0.5% of total supply, the call must revert. Otherwise, the swapTokensAtAmount should be successfully updated to newAmount.Test Result
- Passed
Run Count
- 100k+
Invariant
testFuzz_updateMaxTxnAmount
: This test fuzzes newNum to verify that updateMaxTxnAmount enforces its minimum limit of 0.1% of total supply. If newNum is below the minimum, the function should revert. Otherwise, it updates maxTransactionAmount correctly.Test Result
- Passed
Run Count
- 100k+
Invariant
testFuzz_updateMaxWalletAmount
: This test fuzzes newNum to ensure updateMaxWalletAmount enforces its minimum limit of 0.5% of total supply. If newNum is below that limit, the call reverts; otherwise, maxWallet updates correctly.Test Result
- Passed
Run Count
- 100k+
Invariant
testFuzz_excludeFromMaxTransaction
: This test verifies that calling excludeFromMaxTransaction sets the internal state correctly for any given address and boolean. No revert is expected; it simply updates the internal mapping.Test Result
- Passed
Run Count
- 100k+
Invariant
testFuzz_excludeFromFees
: This test checks that excludeFromFees updates the fee exclusion mapping as intended. For any given address and boolean value, the contract should reflect that address’s fee exclusion status correctly.Test Result
- Passed
Run Count
- 100k+
Invariant
testFuzz_updateDevWallet
: This test ensures the owner can update the devWallet address. It checks that after calling updateDevWallet with a new address, the devWallet field matches that new address.Test Result
- Passed
Run Count
- 100k+
Invariant
testFuzz_Transfer
: This test fuzzes transferAmount to verify multiple conditions of the _transfer logic indirectly via the public transfer function. If trading is not active and the transfer is nonzero, the call should revert. If trading is not active and the transfer is zero, it should succeed (no tokens move). After enabling trading, if a transfer would exceed the recipient’s maxWallet limit, it should revert. If the recipient’s balance stays within maxWallet and the sender has enough tokens, the transfer should succeed and update balances correctly.Test Result
- Passed
Run Count
- 100k+
Additional Recommendations
The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.
To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:
Detecting changes to ownership or critical permissions.
Monitoring large or unexpected transactions and minting events.
Pausing operations when irregularities are identified.
These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.