# TreasureKey Security Assessment (WIP)
# Findings
## Leftover dust tokens are not collectible
https://github.com/treasurekey/treasurekey-contracts/blob/main/contracts/core/PirateBankBSC.sol#L208-L227
```solidity=
function processDividends(address token, uint amount) internal returns (uint dividendPayout) {
dividendPayout = amount.mul(dividendRate).div(1000);
uint wbnbAmount = 0;
uint pirateAmount = 0;
if (token == address(0)) {
wbnbAmount = dividendPayout.div(2);
pirateAmount = _swapFromBNB(tokenRouter[PIRATE], WBNB, dividendPayout.sub(wbnbAmount), PIRATE, address(this));
PANTHER_ROUTER.addLiquidityETH{value: wbnbAmount}(PIRATE, pirateAmount, 0, 0, address(this), block.timestamp);
} else if (token == PIRATE) {
return 0;
} else {
wbnbAmount = _swap(tokenRouter[token], token, dividendPayout, WBNB, address(this));
pirateAmount = _swap(tokenRouter[PIRATE], WBNB, wbnbAmount.div(2), PIRATE, address(this));
PANTHER_ROUTER.addLiquidity(WBNB, PIRATE, wbnbAmount.sub(wbnbAmount.div(2)), pirateAmount, 0, 0, address(this), block.timestamp);
}
uint256 pirateBNBAmount = ERC20(PIRATE_BNB).balanceOf(address(this));
ERC20(PIRATE_BNB).transfer(PIRATE_POOL, pirateBNBAmount);
IStakingRewards(PIRATE_POOL).notifyRewardAmount(pirateBNBAmount);
}
```
### Issue Description
There may be some dust of WBNB and/or PIRATE left on the balance of the contract after `addLiquidityETH`. There is no way to collect the leftover tokens.
### Recommendation
Consider adding a `recoverToken` method that allows the owner to transfer tokens greater than the recorded amount.
```solidity=
function recoverToken(address tokenAddress, uint tokenAmount) external onlyOwner{
if (tokenAddress == address(0)) {
require(address(this).balance.sub(tokenAmount) >= tokenTotal[tokenAddress], "cannot recover token");
msg.sender.transfer(tokenAmount);
} else {
require(ERC20(tokenAddress).balanceOf(address(this)).sub(tokenAmount) >= tokenTotal[tokenAddress], "cannot recover token");
require(ERC20(tokenAddress).transfer(owner(), tokenAmount));
}
}
```
---
## `PirateBankBSC.sol#withdrawAll` should exclude principal for `processDividends`
https://github.com/treasurekey/treasurekey-contracts/blob/main/contracts/core/PirateBankBSC.sol#L161-L173
```solidity=
if (token == address(0)) {
// We naively send all BNB (minus dividends) since the owner of BNB is the owner
uint payout = processDividends(token, totalBalance);
msg.sender.transfer(totalBalance.sub(payout));
} else {
// Transfer remaining funds to Treasure Key dev
require(ERC20(token).transfer(owner(), earnings.sub(toReturn)));
// Uses remaining funds to calculate dividend payouts
uint remaining = totalBalance.sub(earnings.sub(toReturn));
uint payout = processDividends(token, remaining);
// Transfer rest of funds to token owner minus dividends
require(ERC20(token).transfer(tokenOwner[token], remaining.sub(payout)));
}
```
### Issue Description
The current implementation of `PirateBankBSC.sol#withdrawAll` is including the principal in `processDividends`.
As an example, consider the scenario of:
- Principal: **100 PIRATE**
- Earnings: **10 PIRATE**
- Token Return Ratio: **50%**
- Dividend Rate: **5%**
The expected total dividend should be:
$10 \times (1 - 0.5) \times 0.05 = 0.25$
While in the current implementation, it is:
$( 100 - (10 - 10 \times 0.5)) \times 0.05=4.75$
### Recommendation
Change to:
```solidity=
if (token == address(0)) {
// We naively send all BNB (minus dividends) since the owner of BNB is the owner
uint payout = processDividends(token, earnings);
msg.sender.transfer(totalBalance.sub(payout));
} else {
// Uses remaining funds to calculate dividend payouts
uint remaining = earnings.sub(toReturn);
uint payout = processDividends(token, remaining);
// Transfer remaining funds minus dividends to Treasure Key dev
require(ERC20(token).transfer(owner(), remaining.sub(payout)));
// Transfer principal and toReturn to token owner
require(ERC20(token).transfer(tokenOwner[token],totalBalance.sub(earnings).add(toReturn)));
}
```
---
## Unused function
https://github.com/treasurekey/treasurekey-contracts/blob/main/contracts/core/PirateBankBSC.sol#L253-L257
```solidity=
function _approveTokenIfNeeded(address token) private {
if (ERC20(token).allowance(address(this), address(PANTHER_ROUTER)) == 0) {
ERC20(token).approve(address(PANTHER_ROUTER), uint(~0));
}
}
```
### Issue Description
`_approveTokenIfNeeded(address token) private` is unused.
### Recommendation
Consider removing the unused function.