###### tags: `Final Report` TGT Finance Audit === > Copyright © 2022 by Verilog Solutions. All rights reserved. > February 24, 2022 > by **Verilog Solutions** <!-- <span style="position:fixed; top:200px; right:400px; opacity:0.5; font-size: 20px; z-index:99;">watermark</span> --> ![TGT Cover](https://hackmd.io/_uploads/HJshUhdQ9.png) This report presents Verilog's smart contract auditing engagement with TGT Protocol. TGT Protocol is one of the first lending protocols and margin trading platforms on the Emerald Paratime of Oasis Network. --- ## Table of Content [TOC] --- ## Project Summary TGT Finance is a lending protocol built on Oasis Network. TGT Finance utilized a pooled collateral/deposit model to increase capital efficiency. TGT Finance also provides native leverage trading products, which offer a streamlined user experience to traders. --- ## Service Scope Our audit is conducted on the [**main** branch](https://github.com/tgt-finance/tgt-contracts), with commit hash [1c66a650cd01d24bf2c27c2e49e85b1419b004d2](https://github.com/tgt-finance/tgt-contracts/commit/1c66a650cd01d24bf2c27c2e49e85b1419b004d2). Our engagement with TGT Protocol includes the following two services: - Pre-Audit Consulting Service - Audit Service 1. **Pre-Audit Consulting Service** As a part of the pre-audit service, the Verilog team worked closely with the TGT development team to discuss potential vulnerability and smart contract development best practices in a timely fashion. Verilog team is very appreciative of establishing an efficient and effective communication channel with the TGT team, as new findings were often exchanged promptly and fixes were deployed quickly, during the preliminary report stage. 3. **Audit Service** The Verilog team conducted a thorough study of the TGT code, with the TGT architecture graph and UML graph presented below in the TGT Architecture section. The list of findings, along with the severity and solution, is available under section [**Findings & Improvement Suggestions**](#Findings-amp-Improvement-Suggestions). --- ## Architecture ![TGT-Architecture](https://hackmd.io/_uploads/SJ3EPUPx9.png) Listed below are the major smart contracts in the TGT Finance Protocol. * **`TokenRewardPool.sol`**: for actions (supply reward, stake, withdraw, claim reward) * **`utils(folder)`** utility contracts and library contract * **`protocol/interfaces(folder)`**: protocol interfaces * **`protocol/libary(folder)`**: libraries for the procotols * **`protocol/strategies/uniswap(folder)`**: * `StrategySaveBaseTokenOnly.sol` * `StrategyWithdrawTrading.sol` * **`protocol/worker(folder)`**: * `WorkerConfig.sol` * `UniswapWorker.sol` * **`BankController.sol`**: controller contract and help functions * **`ChainLinkPriceOracle.sol`**: upgradable contracts for chainlink oracle * **`ConfigurableInterestVaultConfig.sol`**: interest vault config contract * **`Exponential.sol`**: math library * **`FToken.sol`**: FToken contract main user interaction logic * **`FTokenHelper.sol`**: helper contract * **`InterestRateModel.sol`**: interest rate model contract * **`IPriceOracle.sol`**: price oracle interface * **`TokenVault.sol`**: vault contract * **`Vault.sol`**: margin trading related vault contract * **`WNativeRelayer.sol`**: relayer contract to improve security --- ## Privileged Roles 1. `FToken.sol` * `controller`: * `_reduceReserves()` * `_addReservesFresh()` * `component`: it can be `controller`, this contract itself or eligible `FToken.sol` contracts. * `transferToUser()` * `transferIn()` * `addTotalCash()` * `subTotalCash()` * `vault`: permited vaults * `repayInternalForLeverage()` * `addReservesForLeverage()` 2. `TokenRewardPool.sol` * `owner` * `createPool()` * `setPoolRewardsBlockCount()` * `setPoolRewardsDistributor()` 3. `BandPriceOracle.sol` * `owner` * `setTokenName()` * `setBaseToken()` 4. `ChainLinkPriceOracle.sol` * `owner` * `setBaseToken()` * `setBufferDay()` * `setPriceFeed()` 5. `BankController.sol` * `multisig` * `proposeNewAdmin()` * `reduceReserves()` * `batchReduceReserves()` * `batchReduceAllReserves(address[], address payable)` * `batchReduceAllReserves(address payable)` * `admin`: * `setTransferEthGasCost()` * `setOracle()` * `supportMarket()` * `supportVault()` * `_setCollateralAbility()` * `setCloseFactor()` * `setMarketIsValid()` * `setPauser()` * `pauser`: * `setPaused()` * `setUnpaused()` 6. `WorkerConfig.sol` * `owner`: * `setOracle()` * `setConfigs()` 7. `WNativeReplayer.sol` * `owner`: * `setCallerOk()`: set and remove whitelisted caller * `whitelistedCallers()`: * `withdraw()` 8. `UniswapWorker.sol` * `owner`: * `setParams()`: set two kinds strategists. * `setStrategyOk()`: set or remove strategists. 9. `InterestRateModel.sol` * `owner` * `setSlope1AndSlope2()` 10. `TokenVault.sol` * `owner`: * grant or revoke permissions * `worker`: * `withdraw()` --- ## Findings & Improvement Suggestions #### <html></html> <style> .info { background-color:mediumseagreen; font-size: 12px; color: white; border-radius:4px; padding: 1px 4px; font-weight: 500; display: inline-block; margin: 2px; letter-spacing: 0.3px} </style><style> .minor { background-color: #698999; font-size: 12px; color: white; border-radius:4px; padding: 1px 4px; font-weight: 500; display: inline-block; margin: 2px; letter-spacing: 0.3px} </style><style> .medium { background-color: #FFCA0F; color: #121212; font-size: 12px; border-radius:4px; padding: 1px 4px; font-weight: 500; display: inline-block; margin: 2px; letter-spacing: 0.3px} </style><style> .major{ background-color: #FF6B4A; color: white; font-size: 12px; border-radius:4px; padding: 1px 4px; font-weight: 500; display: inline-block; margin: 2px; letter-spacing: 0.3px} </style><style> .critical{ background-color: #FF0000; color: white; font-size: 12px; border-radius:4px; padding: 1px 4px; font-weight: 500; display: inline-block; margin: 2px; letter-spacing: 0.3px} </style> <span class='info'>Informational</span><span class='minor'>Minor</span><span class='medium'>Medium</span><span class='major'>Major</span><span class='critical'>Critical</span> | | Total | Acknowledged | Resolved | | ------------- | ----- | ------------ | -------- | | Critical | 0 | 0 | 0 | | Major | 3 | 3 | 3 | | Medium | 3 | 3 | 3 | | Minor | 11 | 11 | 11 | | Informational | 16 | 16 | 16 | ### Major 1. Reentrancy attack risk at `FToken.deposit()` (`FToken.deposit()`: L296). <span class='major'>Major</span> **Description**: Possible reentrancy attack might happen at `FToken.deposit()`. It associates with sending native token back to `account` which might have reentrancy attack inside its fallback functions. **Recommendation**: Add `nonReenntrant` modifier for `FToken.deposit()` and remove the `nonReentrant` for `mint()`. **Result**: Fixed in commit [135479ea1fd773e1446b07451dfa399e03071be2](https://github.com/tgt-finance/tgt-contracts/commit/135479ea1fd773e1446b07451dfa399e03071be2). 3. Change the constructor to a initialize function if it's an updagrable contract (`WNativeRelayer.sol`, `TokenVault.sol`).<span class='major'>Major</span> **Description**: Avoid using constructor or assign variables values inside constructor when writing an upgradable contract. **Recommendation**: The value will not be written to proxy contract's storage if assigning variables values inside constructor. **Result**: Fixed in commit [6fe1904d5dca8e5b0cadf2d5c0db22d5162c31d7](https://github.com/tgt-finance/tgt-contracts/commit/6fe1904d5dca8e5b0cadf2d5c0db22d5162c31d7). 1. Logical conflict. pending owner cannot claim ownership (`TokenVault.sol`). <span class='major'>Major</span> **Description**: pending owner cannot claim pending ownership since `transferOwnership` function can only be called by `owner`. **Recommendation**: Rewrite the function `claimOwnership`. **Result**: Fixed in commit [fa6df5b1f130a5182b25eb9cbacc0f5a55232dd7](https://github.com/tgt-finance/tgt-contracts/commit/fa6df5b1f130a5182b25eb9cbacc0f5a55232dd7). ### Medium 1. Returns unexpected value when `utilization` is bigger or equal to `MAX_USAGE_RATE` at `InterestRateModel._getPureAPR()` based on comment (`InterestRateModel.sol`: L75).<span class='medium'>Medium</span> **Description**: The return value should be `BASIC_INTEREST + interestSlope1 + interestSlope2` when `utilization` is bigger or equal to `MAX_USAGE_RATE`. **Recommendation**: ```Solidity= else { // Not possible, but just in case - 130% APY return BASIC_INTEREST + interestSlope1 + interestSlope2; } ``` **Result**: Fixed in commit [ab2fb8ed5fe8529892ae72f318cc71c807e3f244](https://github.com/tgt-finance/tgt-contracts/commit/ab2fb8ed5fe8529892ae72f318cc71c807e3f244). 1. `OwnableUpgradeSafe` and`ReentrancyGuardUpgradeSafe` are not initialized (`TokenVault.sol`: L147, L169). <span class='medium'>Medium</span> **Description**:`OwnableUpgradeSafe` in `Whitelist` and `ReentrancyGuardUpgradeSafe` in `TokenVault` contract are not initialized. **Recommendation**: Initialize `OwnableUpgradeSafe` `ReentrancyGuardUpgradeSafe` inside the initialize function. **Result**: Fixed in commit [fa6df5b1f130a5182b25eb9cbacc0f5a55232dd7](https://github.com/tgt-finance/tgt-contracts/commit/fa6df5b1f130a5182b25eb9cbacc0f5a55232dd7). 1. Reentrancy attack risk at `Vault.work()` and `Vault.kill()` (`Vault.work()`: L197, `Vault.kill()`: L309). <span class='medium'>Medium</span> **Description**: Users interact with vault to perform margin trading through functions `Vault.work()` and `Vault.kill()`. There are many calls to external contracts and complicated variable calculations inside these two functions. `nonReentrant` modifier is recommended to avoid possible reentrancy attack. **Recommendation**: Add `nonReentrant` modifier to `Vault.work()` and `Vault.kill()`. **Result**: Fixed in commit [fb4b983c5bc78b9dd5055274213205a74eabf0c0](https://github.com/tgt-finance/tgt-contracts/commit/fb4b983c5bc78b9dd5055274213205a74eabf0c0). ### Minor 1. Unused `OwnableUpgradeSafe` and library `SafeMath` in (`StrategySaveBaseTokenOnly.sol`, `StrategyWithdrawTrading.sol`, `WorkerConfig.sol`) <span class='minor'>Minor</span> **Description**: There is no function that requires the `owner` role so `OwnableUpgradeSafe` is unnecessary. Library `SafeMath` is currently unused. **Recommendation**: Remove unused inheritance and libraries. **Result**: Fixed in commit [43dfbb927e4f99c58fa5e5e745adc4d716407e26](https://github.com/tgt-finance/tgt-contracts/commit/43dfbb927e4f99c58fa5e5e745adc4d716407e26). 3. Unsued modifier. (`UniswapWorker.sol`: L87, `Vault.sol`: L103) <span class='minor'>Minor</span> **Description**: modifier `onlyEOA` in `UniswapWorker.sol` and `inExec` in `Vault.sol` are unused. **Recommendation**: Remove the unused modifiers. **Result**: Fixed in commit [a39151f24de112244b0051de0aaacd71fb4fb091](https://github.com/tgt-finance/tgt-contracts/commit/a39151f24de112244b0051de0aaacd71fb4fb091). 1. Variable declarations shadow existing declarations (`BandPriceOracle.sol`:L34, L44 `FToken.sol`:L394, L403) <span class='minor'>Minor</span> **Description**: - Variable declearation `uint256 totalCash` in `calcExchangeRate()` (L394) and in `exchangeRateAfter()` shadows exisiting declearation. - The return value `price` of `BandPriceOracle.getPrice()`and the variable `price` defined in `BandPriceOracle.get()` shadow the existing valuable `price`. **Recommendation**: Rename those variables. **Result**: Fixed in commit [a39151f24de112244b0051de0aaacd71fb4fb091](https://github.com/tgt-finance/tgt-contracts/commit/a39151f24de112244b0051de0aaacd71fb4fb091). 1. The variable `address worker` in `event Work()` not indexed (`Vault.sol`: L30). <span class='minor'>Minor</span> **Description**: The variable `address worker` in `event Work()` not indexed. **Recommendation**: Add `indexed` modifier to the variable `address` **Result**: Fixed in commit [1c66a650cd01d24bf2c27c2e49e85b1419b004d2](https://github.com/tgt-finance/tgt-contracts/commit/1c66a650cd01d24bf2c27c2e49e85b1419b004d2). 3. Unused function parameter `address _underlying` in `transferToUserInternal()` (`FToken.()`L157). <span class='minor'>Minor</span> **Description**: Unused function parameter `address _underlying`. **Recommendation**: Remove or Comment out the variable name. Otherwise, put it in a placeholder expression `_underlying;` **Result**:Fixed in commit [3a0b6664ef947ddaeb2f4d6474c18068c1cbdce3](https://github.com/tgt-finance/tgt-contracts/commit/3a0b6664ef947ddaeb2f4d6474c18068c1cbdce3). 1. Scope and modifier for `FToken.transferIn()` function(`FToken.transferIn()`: L172, `FToken.approve()`: L255). <span class='minor'>minor</span> **Description**: `FToken.transferIn()` is currently only used as `external` functions here. To enhance security, we have two alternative modification suggestions for this function. **Recommendation**: * Add a `nonReentrant` modifier to this function and make it an `external` function. * Make this function an `internal` or `private` function **Result**: Fixed in commit [9fba8673ceb0c8c68300846fb2d819aa451750ee](https://github.com/tgt-finance/tgt-contracts/commit/9fba8673ceb0c8c68300846fb2d819aa451750ee). 1. Function calls might fail if farm contract address is zero address (`FToken.transferTokens()`: L249, `FToken.deposit()`: L301, `FToken.withdrawInternal()`: L507, `FToken.seizeInternal()`: L886). <span class='minor'>Minor</span> **Description**: There are calls to farm contract, which is set in the contract `ConfigurableInterestVaultConfig`. Calls might fail if farm contract is not set or set to zero address for current FToken contract. **Recommendation**: Do Address zero check first on farm address then do interactions with it. ```Solidity= (address farm, uint256 poolId) = config.getFarmConfig(address(this)); if(farm != address(0)) { // do calls to farm contract } ``` **Result**: Fixed in commit [70d0c87fff53646e50d4a34e283b84486a6298fc](https://github.com/tgt-finance/tgt-contracts/commit/70d0c87fff53646e50d4a34e283b84486a6298fc). 3. `event PauserSet()` lacks corrsponding `newPauser` and `oldPauser` (`BankController`: L37). <span class='minor'>Minor</span> **Description**: The `PauserSet()` decleration does not include corrsponding data fields (`newPauser` and `oldPauser`). **Recommendation**: Add `newPauser` and `oldPauser` into `PauserSet()` decleration. **Result**: Fixed in commit [f6193adc03ee7c4ff52ef1127de8c2b0c320b7b3](https://github.com/tgt-finance/tgt-contracts/commit/f6193adc03ee7c4ff52ef1127de8c2b0c320b7b3). 3. Redundant type casting from `address` to `IFToken` (`BankController`: L274). <span class='minor'>Minor</span> **Description**: ```solidity= function checkAccountsIn(address account, IFToken fToken) external view returns (bool) { return markets[IFToken(address(fToken)).underlying()].accountsIn[account]; } ``` **Recommendation**: Replace with the following code. ```solidity= function checkAccountsIn(address account, IFToken fToken) external view returns (bool) { return markets[fToken.underlying()].accountsIn[account]; } ``` **Result**: Fixed in commit [14d4cc7c64cd1e2bfc1caa3ba1d9f8782ec2eb7f](https://github.com/tgt-finance/tgt-contracts/commit/14d4cc7c64cd1e2bfc1caa3ba1d9f8782ec2eb7f). 1. Sanitize Input <span class='minor'>Minor</span> **Description**: We suggest adding input sanitization checks when assigning function input parameters to variables. **Recommendation**: Add input sanitization checks when assigning function input parameters to variables. For example: * Zero address check for `minter` and `account` in `BankController.mintCheck()` and `BankController.borrowCheck()` * Input number range check for `_minDebtSize` in `ConfigurableInterestVaultConfig.setMinDebtSize()` **Result**: Fixed in commit [c7ce45de5d308596719a376e97878a0b7ea9cf83](https://github.com/tgt-finance/tgt-contracts/commit/c7ce45de5d308596719a376e97878a0b7ea9cf83). 1. Check if pool already exists when creating new pool (`TokenRewardPool.createPool()`: L86) <span class='minor'>Minor</span> **Description**: Check if pool already exists when creating new pool. **Recommendation**: Add a mapping to track all added pool. Check if pool existed in `TokenRewardPool.createPool()` first. ```solidity= // add a mapping to track added pool mapping(address => mapping(address => bool)) isPoolCreated; function createPool( IERC20Upgradeable _stakingToken, IERC20Upgradeable _rewardsToken, address _rewardsDistributor ) public onlyOwner { // check pool require(!isPoolCreated[_stakingToken][_rewardsToken], "TRP: POOL EXISTED!"); // ... isPoolCreated[_stakingToken][_rewardsToken] = true; ``` **Result**: Fixed in commit [85cfad57f495e8a138ab7f92995be6e14b7a16b5](https://github.com/tgt-finance/tgt-contracts/commit/85cfad57f495e8a138ab7f92995be6e14b7a16b5). ### Informational 1. General practice suggestions. <span class='info'>Informational</span> **Description**: The are many functions associated with transferring users' funds following a series of other operations (i.e. `FToken.repay()`). We recommend transferring in funds first then do these operations. **Recommendation**: Transfer in funds first then do the rest of operations. **Result**: Fixed in commit [a39151f24de112244b0051de0aaacd71fb4fb091](https://github.com/tgt-finance/tgt-contracts/commit/a39151f24de112244b0051de0aaacd71fb4fb091). File deleted. 1. The `IDebtToken` interface is defined but never used (`IDebtToken`). <span class='info'>Informational</span> **Description**: The `IDebtToken` interface is defined but not implemented by any contracts. **Recommendation**: Remove the interface. **Result**: Fixed in commit [ed1298dff74e9636948932aa2a58b843470d92f2](https://github.com/tgt-finance/tgt-contracts/commit/ed1298dff74e9636948932aa2a58b843470d92f2). File deleted. 7. `BankController.sol` Should implement `IBankController` interface (`BankController`: L16). <span class='info'>Informational</span> **Description**: Not implementing the interface may cause the run time error if function is defined in `BankController.sol` without a declaration in `IBankController`. **Recommendation**: Add `IBankController` in the list of implementation. **Result**: Fixed in commit [69d3c5a6635fdf2c3f364684e0a2cba6f456b8d4](https://github.com/tgt-finance/tgt-contracts/commit/69d3c5a6635fdf2c3f364684e0a2cba6f456b8d4) 1. `InterestRateModel` should implement the `IInterestRateModel` interface (`InterestRateModel.sol`: L7). <span class='info'>Informational</span> **Description**: Not implementing the interface may cause the run time error if function is defined in `InterestRateModel` without a declaration in `IInterestRateModel`. **Recommendation**: Add `IInterestRateModel` in the list of implementation. **Result**: Fixed in commit [df588cccd2fe8b8a41dd5cc27d1780a8ac5f5001](https://github.com/tgt-finance/tgt-contracts/commit/df588cccd2fe8b8a41dd5cc27d1780a8ac5f5001). 1. Redundant interface `IInterestRateModel.sol` and `InterestModel.sol`. **Description**: Two interfaces are about interest rate model. **Recommendation**: Keep `IInterestRateModel.sol`. **Result**: Fixed in commit [43261b8c350657091507bd837d578f6e95c0aa50](https://github.com/tgt-finance/tgt-contracts/commit/43261b8c350657091507bd837d578f6e95c0aa50). 3. `FToken.sol` contract should implement the IERC20 standards (`FToken.transfer()`: L205, `FToken.approve()`: L255). <span class='info'>Informational</span> **Description**: The `FToken` does not implement the standard IERC20 interface. `FToken.transfer()` does not have bool return and `FToken.approve()` does not emit `Approval` event. Thus it does not follows standards **Recommendation**: Modifies the functions to follow the standard IERC20 interface and also modifiers the `IFToken.sol` as well. **Result**: Fixed in commit [8c1ed9f9061216e334c88d02ca6025e379fef636](https://github.com/tgt-finance/tgt-contracts/commit/8c1ed9f9061216e334c88d02ca6025e379fef636). 1. Comments `// 2. Convert farming tokens to base tokens.` is wrong (`StrategySaveBaseTokenOnly`: L43). <span class='info'>Informational</span> **Description**: The comment should be `convert base tokens to farm tokens`. **Recommendation**: Change comment to `Convert base tokens to farm tokens`. **Result**: Fixed in commit [ab2fb8ed5fe8529892ae72f318cc71c807e3f244](https://github.com/tgt-finance/tgt-contracts/commit/ab2fb8ed5fe8529892ae72f318cc71c807e3f244). 1. Add token balance differences check (`StrategySaveBaseTokenOnly.executeWithData()`: L24, `StrategyWithdrawTrading.executeWithData()`: L23). <span class='info'>Informational</span> **Description**: function `executeWithData` convert all base token to farm token. A balance difference check for farm token could be added to make sure farm token balance increases after swap. **Recommendation**: function `StrategySaveBaseTokenOnly.executeWithData()` convert all base tokens to farm tokens. `StrategyWithdrawTrading.executeWithData()` convert partial farm tokens / base tokens. Record the tokens balance before and after swap and require that balance difference is greater or equal to `amountOutMin`. **Result**: Fixed in commit [a39151f24de112244b0051de0aaacd71fb4fb091](https://github.com/tgt-finance/tgt-contracts/commit/a39151f24de112244b0051de0aaacd71fb4fb091). Required after balance bigger than before balance. 1. Remove `payable` keyword in function `executeWithData` (`StrategySaveBaseTokenOnly.executeWithData()`: L30, `IStrategy.executeWithData()`: L5). <span class='info'>Informational</span> **Description**: All `IStrategy` contracts we currently have only deal with ERC20 tokens. No need for `payable` keyword. **Recommendation**: Remove `payable`. **Result**: Fixed in commit [a39151f24de112244b0051de0aaacd71fb4fb091](https://github.com/tgt-finance/tgt-contracts/commit/a39151f24de112244b0051de0aaacd71fb4fb091). 1. Use existing `onlyAdmin()` modifier instead of `require(msg.sender==admin)` (`BankController.sol`: L151, L172). <span class='info'>Informational</span> **Description**: The `_setMarketBorrowSupplyCaps()` and `setTokenConfig()` implment existing authentication login defined in `onlyAdmin()`. **Recommendation**: Replace `require(msg.sender==admin)` with `onlyAdmin()` modifier. **Result**: Fixed in commit [a39151f24de112244b0051de0aaacd71fb4fb091](https://github.com/tgt-finance/tgt-contracts/commit/a39151f24de112244b0051de0aaacd71fb4fb091). 1. Suggest only receive from `wnative` (`WNativeRelayer.receive()`: L37). <span class='info'>Informational</span> **Description**: Add a require to `receive()` to require the `msg.sender` is `wnative`. So only `wnative` can send native tokens to this contract. **Recommendation**: ```Solidity= receive() external payable { require(msg.sender == wnative, "WNativeRelayer::onlyWnative"); } ``` **Result**: Fixed in commit [8c9ac7d8d7101da3059df5c1e3c41182af94d710](https://github.com/tgt-finance/tgt-contracts/commit/8c9ac7d8d7101da3059df5c1e3c41182af94d710). 1. `OPTICAL_USAGE_RATE`, `MAX_USAGE_RATE` and `BASIC_INTEREST` can be constant variables (`InterestRateModel.sol`). <span class='info'>Informational</span> **Description**: `OPTICAL_USAGE_RATE`, `MAX_USAGE_RATE` and `BASIC_INTEREST` can be constant variables. **Recommendation**: Set `OPTICAL_USAGE_RATE`, `MAX_USAGE_RATE` and `BASIC_INTEREST` to constant variables. **Result**: Fixed in commit [ca81ff479fd0ea435151f4115790eeda0c58b13b](https://github.com/tgt-finance/tgt-contracts/commit/ca81ff479fd0ea435151f4115790eeda0c58b13b). 1. Wrong error message in `withdraw()` (`TokenVault`: L212). <span class='info'>Informational</span> **Description**: The error message of ` require(_receiver != address(0), "Illegal amount" );` unmatch. **Recommendation**: Replace it with `"Receiver address is zero"`. **Result**: Fixed in commit [c2e7ca29f122e24624e0aea8725aedd6e3833d80](https://github.com/tgt-finance/tgt-contracts/commit/c2e7ca29f122e24624e0aea8725aedd6e3833d80). 1. Redundant check (`TokenVault.withdraw()`: L213)<span class='info'>Informational</span> **Description**: The check for SToken balance is redundant. `safeTransfer` will revert on insufficient balance. **Recommendation**: Remove the redundant the require. **Result**: Fixed in commit [c4a6b8d55aa0b70ae3e69611e2fe0c67a2393e8b](https://github.com/tgt-finance/tgt-contracts/commit/c4a6b8d55aa0b70ae3e69611e2fe0c67a2393e8b). 1. Use openzeppelin `Address` library for `onlyEOA` modifier (`Vault.sol`: L85). <span class='info'>Informational</span> **Description**: Currently, it only checks if an account is EOA by comparing `msg.sender` and `tx.origin`. There are many ways to bypass this check (i.e. using `delegatecall`). **Recommendation**: Use openzeppelin `Address` library for `onlyEOA` modifier to check if an account is EOA. **Result**: Fixed in commit [e8e8afe2f11b73b2ee4c5b765ee833a7a9672af4](https://github.com/tgt-finance/tgt-contracts/commit/e8e8afe2f11b73b2ee4c5b765ee833a7a9672af4). 1. Interface `IVault.sol` is empty. <span class='info'>Informational</span> **Description**: `IVault` interface can be removed from `Vault` inheritance since `IVault` is empty. **Recommendation**: Remove `IVault.sol`. **Result**: Fixed in commit [14d0251eebb299edea73eeea4eb0473e2234b278](https://github.com/tgt-finance/tgt-contracts/commit/14d0251eebb299edea73eeea4eb0473e2234b278). --- ## Disclaimer Verilog receives compensation from one or more clients for performing the smart contract and auditing analysis contained in these reports. The report created is solely for Clients and published with their consent. As such, the scope of our audit is limited to a review of code, and only the code we note as being within the scope of our audit detailed in this report. It is important to note that the Solidity code itself presents unique and unquantifiable risks since the Solidity language itself remains under current development and is subject to unknown risks and flaws. Our sole goal is to help reduce the attack vectors and the high level of variance associated with utilizing new and consistently changing technologies. Thus, Verilog in no way claims any guarantee of security or functionality of the technology we agree to analyze. In addition, Verilog reports do not provide any indication of the technologies proprietors, business, business model, or legal compliance. As such, reports do not provide investment advice and should not be used to make decisions about investment or involvement with any particular project. Verilog has the right to distribute the Report through other means, including via Verilog publications and other distributions. Verilog makes the reports available to parties other than the Clients (i.e., “third parties”) – on its website in hopes that it can help the blockchain ecosystem develop technical best practices in this rapidly evolving area of innovation.