# Final Security Audit of `DEXI` token

## Conclusion
This audit was made by [Web3Go](https://web3go.tech)
Auditor: Vladimir Smelov <vsmelov.job@gmail.com>.
Date: 2022-08-09
In the final contract were **NOT FOUND**:
- Backdoors for investor funds withdrawal by anyone.
- Bugs allow stealing money from the contract.
- Any severe security problems.
- Any serious problems with gas consumption.
The client was acknowledged about all notes below.
## Scope
#### Pre-audit
- DEXI.sol (md5 hash - `4669ec9cc43e556f5901a998a60825a3`)
#### Final audit
- DEXI.sol
https://gist.github.com/vsmelov/7d66ce139b6996c82dae8eb80efeaf09
## Methodology
1. Blind audit. Understand the structure of the code without reading any docs.
2. Ask questions to developers.
3. Draw the scheme of cross-contracts interactions.
4. Write user stories and usage cases.
5. Run static analyzers.
6. Find problems with:
- backdoors;
- bugs;
- math;
- potential leaking of funds;
- potential locking of the contract;
- validate arguments and events;
- others.
## Result
### Critical
There are no critical in the final version of the DEXI token.
___
### Major
#### MAJOR-1. DEXI does not allow zero-amount transfers.
At
- contracts/DEXI.sol:721
```solidity=721
function _transfer(
address from,
address to,
uint256 amount
) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
```
there is an incompatibility with
https://eips.ethereum.org/EIPS/eip-20
amount=0 is the correct value, and some DeFi projects may not work with DEXI.
It's **explicitly** stated in EIP-20, whose author is **Vitalik Buterin**, that erc-20 tokens **MUST** support `amount=0` transfers. For example, if some developer of some marketplace will rely on eip-20 Standart and will think that `IERC20(dexi).transfer(amount * fee)` will always work, even in case if `fee=0`, it will break integration with your token in case if `fee=0`.
Let's check any popular erc-20 token, e.g., usdt https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7#code
they all support amount=0 transfers.
This is not a SECURITY ISSUE because no one may steal money. But it's a major defi-ecosystem-integration issue.
##### **Recommendation.**
Accept `amount=0`.
##### **Status.**
ACKNOWLEDGED
Since it's the client's strong opinion not to allow zero transfers, they can leave it as it is. **This is not a security issue.**
Be aware, then use the DEXI token with other DeFi applications.
##### **Client's commentary.**
> We decided to move forward with certain functionality.
___
### Warning
There are no warnings in the final version of the DEXI token.
___
### Comment.
#### COMMENT-1. Variables should be constants
At
- contracts/DEXI.sol:405-406
```solidity=405
uint256 private _tTotal = 50000000 * 10**uint256(_decimals);
address public _burnpoolWalletAddress = address(0x000000000000000000000000000000000000dEaD);
```
The variables are never changed.
##### Recommendation.
Consider the usage of constants to save gas.
##### Status.
FIXED - Variables were declared as constants.
___
#### COMMENT-2. Use scientific notation for clarity
At
- contracts/DEXI.sol:405
```solidity=405
uint256 private _tTotal = 50000000 * 10**uint256(_decimals);
```
"50000000" has too many zeros.
##### Recommendation.
Replace it with "50 * 1e6" for better readability.
##### Status.
FIXED - Scientific notations were used.
___
#### COMMENT-3. No need to initialize "previous" values
At
- contracts/DEXI.sol:410,413,416
```solidity=409
uint256 public _taxFee = 3;
uint256 private _previousTaxFee = _taxFee;
uint256 public _burnFee = 3;
uint256 private _previousBurnFee = _burnFee;
uint256 public _liquidityFee = 3;
uint256 private _previousLiquidityFee = _liquidityFee;
```
There is no reason to initialize previous values.
##### Recommendation.
Consider removing the initialization to save gas at deployment time.
##### Status.
FIXED - These variables were removed.
___
#### COMMENT-4. Unclear reason to use _maxTxAmount
At
- contracts/DEXI.sol:418
- contracts/DEXI.sol:724
```solidity=724
if(from != owner() && to != owner())
require(amount <= _maxTxAmount, "Transfer amount exceeds the maxTxAmount.");
```
It's unclear what the motivation is to limit the max transfer amount—just wasting gas.
It does not change anything because someone may do a significant transfer in a row of smaller transfers.
But it may induce a problem if some huge holder wants to withdraw his big share, e.g., from the DEX pool.
##### Recommendation.
Remove `_maxTxAmount` restriction.
##### Status.
ACKNOWLEDGED
##### Client's commentary.
> We would like to keep it to restrict manipulations in a single transaction.
___
#### COMMENT-5. Use the same style of variable and getter function.
- contracts/DEXI.sol:429
In the final version, it looks like this:
```solidity=437
mapping (address => mapping (address => uint256)) private _allowances;
mapping (uint16 => uint256) public _yearMintedAmount;
mapping (uint16 => uint256) public _yearCanMintAmount;
mapping (address => bool) public _isBlacklisted;
mapping (address => bool) private _isExcludedFromFee;
```
Some variables are public (but prefixed with an underscore), and others are private.
##### Recommendation.
Use the same style. E.g., name public variables with no underscore prefix and private variables with underscore prefix, or make all variables public to use the default getter.
##### Status.
ACKNOWLEDGED - The style remained the same.
---
#### COMMENT-6. Index important event parameters
- contracts/DEXI.sol:450-454
In the final contract, it looks like
```solidity=446
event IsBlackListed(address indexed user, bool indexed flag);
event ExcludeFromFee(address account, bool isExcludedFromFee);
event SetEnabledFlag(bool _enableFlag, TAX_TYPE _flagType);
event TaxesSet(uint8 _buyTax, uint8 _sellTax, uint8 _transferTax, uint8 _burnFee);
event AddNewSwapPair(address pair);
```
##### Recommendation.
Index important event parameters
##### Status.
ACKNOWLEDGED - Some important event parameters are still not indexed.
___
#### COMMENT-7. The event is never used
- contracts/DEXI.sol:451
- contracts/DEXI.sol:453
- contracts/DEXI.sol:454
```solidity=451
event IncludeInReward(address account, bool isExclude);
event ExcludeFromFee(address account, bool isExcludedFromFee);
event IncludeInFee(address account, bool isExcludedFromFee);
event TokenTranfer(address from, address to, uint256 amount, bool takeFee);
```
##### Recommendation.
Consider removing unused events.
##### Status.
FIXED - Unused events were removed.
___
#### COMMENT-8. Use "external pure" declarations
- contracts/DEXI.sol:486
- contracts/DEXI.sol:490
- contracts/DEXI.sol:494
```solidity=486
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
```
##### Recommendation.
Use `external pure` declaration for pure functions.
##### Status.
FIXED - `external pure` declaration was used.
___
#### COMMENT-9. Local variable shadows external declaration
There is an Ownable.owner() function, but it's being shadown by the "owner" argument:
- contracts/DEXI.sol:512
- contracts/DEXI.sol:706
##### Recommendation.
Rename to _owner
##### Status.
ACKNOWLEDGED
___
#### COMMENT-10. No need to use `_msgSender()`
- contracts/DEXI.sol:523
- contracts/DEXI.sol:528
...
In fact "Context" base class is needed in case you change the context of the transaction execution inside the contract (e.g., in meta transactions as described in https://eips.ethereum.org/EIPS/eip-2771)
You never change the code execution context, so you don't need to use `_msgSender`. It's just wasting gas.
##### Recommendation.
Use msg.sender instead.
##### Status.
FIXED - "Context" library usage was removed.
___
#### COMMENT-11. The owner may set `_maxTxAmount` too low
At
- contracts/DEXI.sol:892
```solidity=892
function _setMaxTxAmount(uint256 maxTxAmount) external onlyOwner() {
require(maxTxAmount > 0, "maxTxAmount should be greater than zero");
_maxTxAmount = maxTxAmount;
emit SetMaxTxAmount(maxTxAmount);
}
```
The owner can make the token impossible to use just by setting `_maxTxAmount` to some minimal value (e.g. =1).
##### Recommendation.
Remove.
The owner must be multisig!
##### Status.
ACKNOWLEDGED