---
# System prepended metadata

title: TreasureKey Security Assessment (WIP)

---

# 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.

