Omniscia Kinza Finance Audit
ProtectedNativeTokenGateway Manual Review Findings
ProtectedNativeTokenGateway Manual Review Findings
PNT-01M: Inexistent Renewal of Approvals
| Type | Severity | Location |
|---|---|---|
| Standard Conformity | ![]() | ProtectedNativeTokenGateway.sol:L53-L54 |
Description:
In contrast to the ProtectedERC20Gateway::depositProtectedToken function, the ProtectedNativeTokenGateway::depositProtectedBNB function will not automatically renew its WBNB and pWBNB approvals.
Example:
48function depositProtectedBNB(49 address onBehalfOf,50 uint16 referralCode51) external payable {52 WBNB.deposit{value: msg.value}();53 pWBNB.depositFor(address(this), msg.value);54 POOL.deposit(address(pWBNB), msg.value, onBehalfOf, referralCode);55}Recommendation:
We advise the ProtectedNativeTokenGateway::depositProtectedBNB function to align with the ProtectedERC20Gateway::depositProtectedToken function, refreshing its approvals whenever necessary.
Alleviation:
The Kinza Finance team has stated that the allowance being set in the contract's ProtectedNativeTokenGateway::constructor is sufficient for the lifetime of the contract and as such they do not wish to introduce an approval refresh mechanism.
As such, we consider this exhibit nullified as the Kinza Finance team has assessed the current behaviour is sufficient.
PNT-02M: Potential Withdrawal Denial-of-Service
| Type | Severity | Location |
|---|---|---|
| Language Specific | ![]() | ProtectedNativeTokenGateway.sol:L104 |
Description:
The ProtectedNativeTokenGateway::withdrawBNBWithPermit function will attempt to consume a permit before executing the ERC20::transferFrom operation. Given that permits can be submitted and consumed by anyone, it is possible for a user to detect a substantial ProtectedNativeTokenGateway::withdrawBNBWithPermit operation and sabotage it by consuming the permit first.
Impact:
While the Denial-of-Service attack is trivial to perform, its impact is minimal as it would only be important in case a substantial withdrawal is detected and wished to be arbitraged.
Example:
87function withdrawBNBWithPermit(88 uint256 amount,89 address to,90 uint256 deadline,91 uint8 permitV,92 bytes32 permitR,93 bytes32 permitS94) external {95 IAToken apWBNB = IAToken(POOL.getReserveData(address(pWBNB)).aTokenAddress);96 uint256 userBalance = apWBNB.balanceOf(msg.sender);97 uint256 amountToWithdraw = amount;98
99 // if amount is equal to type(uint256).max, the user wants to redeem everything100 if (amount == type(uint256).max) {101 amountToWithdraw = userBalance;102 }103 // permit `amount` rather than `amountToWithdraw` to make it easier for front-ends and integrators104 apWBNB.permit(msg.sender, address(this), amount, deadline, permitV, permitR, permitS);105 apWBNB.transferFrom(msg.sender, address(this), amountToWithdraw);106 POOL.withdraw(address(pWBNB), amountToWithdraw, address(this));107 // withdraw the pToken to wToken first108 pWBNB.withdrawTo(address(this), amountToWithdraw);109 // withdraw the wToken to native token110 WBNB.withdraw(amountToWithdraw);111 _safeTransferBNB(to, amountToWithdraw);112}Recommendation:
We advise the code to opportunistically perform the IAToken::permit operation, continuing with the ERC20::transferFrom operation regardless of whether the permit succeeds as it may have been consumed by another party.
Alleviation:
The Kinza Finance team has stated that while they acknowledge this exhibit they consider that it bears no financial impact and as such will acknowledge it.
PNT-03M: Potentially Inaccurate Maximum Withdrawal Mechanism
| Type | Severity | Location |
|---|---|---|
| Mathematical Operations | ![]() | ProtectedNativeTokenGateway.sol:L63, L72, L75, L77, L79, L81, L83, L88, L101, L105, L106, L108, L110, L111 |
Description:
The ProtectedNativeTokenGateway::withdrawProtectedBNB and ProtectedNativeTokenGateway::withdrawBNBWithPermit functions will assume that an amount of type(uint256).max refers to a withdrawal of the user's available balance, however, the measurement utilized as the amount withdrawn is the user's IAToken::balanceOf whereas the pool implementation will utilize the user's IAToken::scaledBalanceOf multiplied with the next liquidity index.
Impact:
While a loss arising from these mathematical inaccuracies would be inconsequential, it may lead to unfulfillable transfers in case this inaccuracy leads to an amountToWithdraw less than the expected one.
Example:
62function withdrawProtectedBNB(63 uint256 amount,64 address to65) external {66 IAToken apWBNB = IAToken(POOL.getReserveData(address(pWBNB)).aTokenAddress);67 uint256 userBalance = apWBNB.balanceOf(msg.sender);68 uint256 amountToWithdraw = amount;69
70 // if amount is equal to uint(-1), the user wants to redeem everything71 if (amount == type(uint256).max) {72 amountToWithdraw = userBalance;73 }74 // transfer aPToken from msg.sender to this contract75 apWBNB.transferFrom(msg.sender, address(this), amountToWithdraw);76 // withdraw aPToken to pToken77 POOL.withdraw(address(apWBNB), amountToWithdraw, address(this));78 // withdraw the pToken to wToken first79 pWBNB.withdrawTo(address(this), amountToWithdraw);80 // withdraw the wToken to native token81 WBNB.withdraw(amountToWithdraw);82 // transfer BNB back to the caller 83 _safeTransferBNB(to, amountToWithdraw);84}Recommendation:
We advise the code to perform the following steps:
- Fetch the minimum between the
userBalanceand theamountfrom the user - Pass in the
amountargument as is to theIPool::withdrawcall - Store the result of the
IPool::withdrawcall and use it in theERC20Wrapper::withdrawTocall as an argument
The above steps will guarantee that all amounts are safe to use and that they respect any mathematical truncation that may occur in between calculations.
Alleviation:
The special-purpose maximum value handling logic has been removed from the ProtectedNativeTokenGateway::withdrawProtectedBNB and ProtectedNativeTokenGateway::withdrawBNBWithPermit functions, instead utilizing the provided amount directly and storing the IPool::withdraw result to be utilized in the ERC20Wrapper::withdrawTo function call.
As such, we consider this exhibit alleviated as the original described vulnerability is no longer possible.


