Closed sherlock-admin4 closed 5 months ago
1 comment(s) were left on this issue during the judging contest.
takarez commented:
seem invalid to me
This scenario: if feeAmount is greater than amountOut, calling _distributeOnTwTap will revert and block reward distribution.
seems like will never be given because feeShares
should be always equal or bigger than the actual amount withdrawn as if you check the withdraw function on the Yieldbox, it rounds down:
} else {
// amount may be lower than the value of share due to rounding, that's ok
amount = share._toAmount(totalSupply[assetId], totalAmount, false);
}
Let me know if I am incorrect whoever sumitted, thanks.
request poc
PoC requested from @ctf-sec
Requests remaining: 1
This scenario:
if feeAmount is greater than amountOut, calling _distributeOnTwTap will revert and block reward distribution.
seems like will never be given becausefeeShares
should be always equal or bigger than the actual amount withdrawn as if you check the withdraw function on the Yieldbox, it rounds down:} else { // amount may be lower than the value of share due to rounding, that's ok amount = share._toAmount(totalSupply[assetId], totalAmount, false); }
Let me know if I am incorrect whoever sumitted, thanks.
Yeah I agree, but I think the
uint256 feeAmount = yieldBox.toAmount(_assetId, feeShares, false);
still not match the withdraw amount, which results in a port of reward not distributed.
I think the worth case is that the feeShares equals to most of the total shares in the yield box:
function testShares() public {
uint256 share = 10 ether;
uint256 total = 10 ether;
uint256 amonut = 10 ether;
amonut++;
total+= 1e8;
uint256 toAmount = share * amonut / total;
console.log("toAmount: %d", toAmount);
uint256 share2 = 10 ether;
uint256 total2 = 0 ether;
uint256 amonut2 = 0 ether;
amonut2++;
total2+= 1e8;
uint256 toAmount2 = share2 * amonut2 / total2;
console.log("toAmount2: %d", toAmount2);
console.log((toAmount - toAmount2) / 1 ether);
}
In this case ,the majority of the reward is not distributed.
Anyway the root cause is not handling the return value of yieldBox.withdraw, which worth fixing.
totalAmount++;
totalShares_ += 1e8;
I believe this is a duplicate of my issue #43 Have detailed an example where it can revert.
The reasoning is basically that both withdraw
and toAmount
should round down in most cases, but if withdraw
rounds down and the division in toAmount
has no remainder, toAmount returns a bigger value and the function reverts.
This situation is possible since toAmount is called after the withdraw, and thus is used on different values.
Maybe we can avoid coding the PoC for the same thing twice, and use @ctf-sec 's Poc for this
Yes, it seems a duplicate of #43
The protocol team fixed this issue in PR/commit https://github.com/Tapioca-DAO/Tapioca-bar/pull/353.
ctf_sec
medium
Share computing for reward distribution is incorrect
Summary
Share computing for reward distribution is incorrect
Vulnerability Detail
Line of code
This code in
Penrose.sol
is used to distribute the reward totwTAP.sol
user that lock their TAP tokenbut the problem is that we are calling
and ignored the return parameter:
Line of code
the returned
amountOut
should be what used for reward distributionbut the code compute the
feeAmount
again using stale sharesif
feeAmount
is greater thanamountOut
, calling_distributeOnTwTa
p will revert and block reward distribution.Line of code
Impact
.
Code Snippet
https://github.com/sherlock-audit/2024-02-tapioca/blob/dc2464f420927409a67763de6ec60fe5c028ab0e/Tapioca-bar/contracts/Penrose.sol#L565
https://github.com/Tapioca-DAO/tap-yieldbox/blob/8de8ad15fe80c4e00843475d7d20fae4d0397003/contracts/interfaces/IYieldBox.sol#L56
https://github.com/sherlock-audit/2024-02-tapioca/blob/dc2464f420927409a67763de6ec60fe5c028ab0e/Tapioca-bar/contracts/Penrose.sol#L580
Tool used
Manual Review
Recommendation
Duplicate of #43