-
Notifications
You must be signed in to change notification settings - Fork 2
charles__cheerful - Medium6-UserReceivesLessThanMintToLimit #97
Comments
Good, thanks for pointing it out : the source chain's bridge amount needs to be checked for But on destination chain, we already check against |
In 🟢5️⃣ and 🟢6️⃣, we wont check In 🟢7️⃣, you might misunderstanding the bridgeAmount -= fee;
+ require(bridgeAmount >= srcInfos.minBridgeAmount, "WooCrossChainRouterV4: !srcInfos.minBridgeAmount"); In 🟢1️⃣2️⃣, what you said For 🟢1️⃣2️⃣ and 🟢1️⃣4️⃣, |
The protocol team fixed this issue in the following PRs/commits: |
Inteded behaviour -> invalid |
Escalate I don't know why the issue is invalidated, even though the issue has been acknowledged and addressed by the team, as we can see in the comments discussion. Let's address the comment from
This points out that my recommendation to fix the issue is actually incomplete, not invalid though. This is because my recommendation misses a little detail which is, maybe the My point here is that my recommendation was good but incomplete, is this why the finding is invalidated even though it's describing a real problem addressed by the team?
In 🟢7️⃣ I did the same typo too: So the user now would be sending a
But my issue doesn't mean that, the valid execution flow I provide is the one who directly transfers funds with no swap in the destination chain either because
Thus If this last 4th point was the reason to invalidate the finding I think is wrong because the dev team missed or forgot by point 🟢1️⃣2️⃣ that in my issues' PoC inputs we are taking the code path of The judge says: Intended behaviour -> invalid. I don't see any intended behaviour being described by the devs comment, instead the devs did something and changed the code to fix it so it looks it was not intentional and actually an issue. I don't understand why this is invalidated and I would appreciate some clarifications, probably I'm misunderstanding something? are typos or the recommendation thing the reason? |
The escalation could not be created because you are not exceeding the escalation threshold. You can view the required number of additional valid issues/judging contest payouts in your Profile page, |
After additional discussions in discord, I admit that there is something I miss about this one. Therefore, escalating on behalf of @CarlosAlegreUr, after he provides additional comments from discord, I will give my reasons why it should remain invalid and leave the decision to the head of judging. Escalate |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
#97 Final escalation and thanks WangSecurity for your time, effort and kindness. Summing up discord discussion with WangSecurity (lead judge) and Tapir (another contestant). There are 2 main reasons why this issue has been considered invalid:
I totally disagree with the 1st one and I could agree on the second one but it depends on how Sherlok defines small and finite. The exacts reasons why I disagree are written after the summary of the issue written in the next section. First lets summ up the issue (links to the code provided along the explanation): The issue is that in a valid cross-chain swap a user could end up receiving less token amount than the The type of cross-chain swaps would be the following:
In this case it can happen than a user specifies a Now after that, due to using an external swap the Now the cross-chain swap will be carried out sending a Now let me address the 2 reasons why this issue has been considered invalid and why I disagree with 1, potentially both: 1.-The argument of UX is that if the user reads the code and sees that the fee check is never done they can always send more money so after the fee is discounted the desired amount of value arrives to the other chain. Lets say that you want 1000$ at least to be sent, but you know the My critique to this is was the following (copied from discord): But is a user expected to read all the code and workflow of a contract before calling it? Then all bugs are invalid as users can prevent them reading the code. A user is expected to see the interface and docs of the contract, or maybe not even that if using an UI and then fill up the args. In the most informed case on this codebase the interface a user would see is a uint256 refId,
address payable to,
SrcInfos memory srcInfos,
DstInfos calldata dstInfos,
Src1inch calldata src1inch,
Dst1inch calldata dst1inch Then it would see the There are no comments on these args so the user would infer their functionality by their names, here I add in comments a logical conclusion from a users perspective: (only added in the args that apply to this issue) struct SrcInfos {
address fromToken;
address bridgeToken;
uint256 fromAmount;
uint256 minBridgeAmount; // 🟢 Min amount I expect to receive in dstChain (e.g. 4000 USDC)
}
// 🟢 Doesnt involve the minAmount received by 1 inch swap
// as that is: srcInfos.minBridgeAmount
struct Src1inch {
address swapRouter;
bytes data;
}
struct DstInfos {
uint16 chainId;
address toToken;
address bridgeToken;
uint256 minToAmount; // 🟢 Min amount I want to receive of the `to` token
// Notice as a user I know toToken == brigeToken
// in this crossSwap call so I set it to the same amount
// as the minBridgeAmount (e.g. 4000 USDC)
uint256 airdropNativeAmount;
uint256 dstGasForCall;
}
// 🟢 Same doesnt involve the minBridgeAmount
struct Dst1inch {
address swapRouter;
bytes data;
} You can see that a user would expect that the The interface of the contract is misleading and has no warnings that Also, regarding to On top of all these like the team said: To conclude first point user shouldn't need to worry about the nitty-gritty details of the implementation, just read the interface and docs and expect things to work. And all the interfaces and docs present in the code so far tells the user that the 2.-My agreement with the argument of small and finite loss depends on how sherlok defines a small finite loss. This could be considered small in terms of percentage as the loss will be as big as the protocols' fee charged for using external swaps, which is a small % (lets say 1% or even 0.05%). Now despite of that a 1% loss on let's imagine a bridged amount of 1 million dollars would be 10K of loss which is quite an amount of money to lose (or 5K in the 0.05% case). So idk how Sherlok defines finite small loss, in absolute terms or proportional terms. If it is in proportional terms then okay its a "small" loss, you lost 10K while managing 1 million due to code issues. But if it is absolute terms I do not think 10K or 5K is a small loss. As it is a percentage of the bridged amount, it can be considered proportionally low. But in absolute terms the amount lost can be seen as big, like the 10K loss explained. Also if we add the time factor, over time, all people using this option of bridging can accumulate loses due to the protocol and that number can get big. Anyway to sum up, depending on the nuance of how you define small and finite loss I would agree or disagree with the argument. These are all the arguments and counterarguments given on discord for this issue. |
I see the points from the watson and I think this issue can valid as broken core functionality. On the other hand, I believe the loss doesn't exceed small and finite amounts, therefore, should remain low. I'm unsure what is the main argument for judging such issues, therefore, escalated myself and leaving the decision to the head of judging. |
@CarlosAlegreUr @WangSecurity pardon if I'm misunderstanding, but doesn't the comment
invalidate this? |
The problem is that in edge cases, when we get into The problem here is that fromToken != bridgeToken and == toToken. Therefore, we first swap the token here. Or a couple of lines below in a regular swap. Thus, the only loss here is that fee, therefore, I think it doesn't exceed the rule of smal and finite amounts and there is no guarantee that this amount will indeed be lower after deducting the fees. |
First, Thanks for your time and patience and letting me explain myself. @Czar102 , I didn't read Issue #85 before, but now that @WangSecurity pointed it out in this reply, I've read it and it is what I've been trying to explain all this time. #85 has been rewarded, I think my issue should be considered a duplicate of it. I admit that #85 explains better than me the issue, hope that is not enough reason to not to consider mine a duplicate. We both address the consequences of (copied from issue #85) The thing is that because I was thinking on a clear case where the very same But the core issue I was explaining is the same, the lack of checks for Even though my writing was not the most clear one, hope this explanation helps to understand why I think my issue is a duplicate of #85. |
I agree, this seems to indeed be a duplicate of #85. @WangSecurity do you agree with duplication? |
Yes, I agree, sorry to both of you for wasting your time, haven't noticed it indeed should be a duplicate. |
Don't worry you have been very hard-working answering lots of questions during the judging, you did your job well and it is obvious you tried your best! Good job @WangSecurity :D |
thank you very much 👉 👈 |
Result: I agree with #97 (comment) ;) |
Escalations have been resolved successfully! Escalation status:
|
The Lead Senior Watson signed off on the fix. |
charles__cheerful
medium
Medium6-UserReceivesLessThanMintToLimit
by CarlosAlegreUr
Summary
In 2 cross-chain swap scenarios users using the protocol in an expected and valid way can receive less tokens than the desired marked minimum limit thus unwillingly lose funds. Even if the users lose funds, I rate this a Medium and not a High because the protocol has some capability (though not capable in all-scenarios) of fighting back this problem in case third-party services decide to increase their fees.
Vulnerability Detail
When executing a cross-swap through the
crossSwap()
function at theWooCrossChainRouterV4
with sgETH asbridgeToken
and the native coin like ETH as thetoToken
(in the code this translates totoToken == ETH_PLACEHOLDER_ADDR
) the user can receive less than the specifiedminToAmount
. It can also happen with anyfromToken
and abridgeToken == toToken
butbridgeToken != sgETH
.Impact
Users using the protocol in an expected and valid way will receive less tokens on cross-chain swaps than the desired marked minimum limit thus unwillingly lose funds.
Code Snippet
User calls
crossSwap()
at theWooCrossChainRouterV4
contract:All the checks on the source chain will pass and the stargate protocol will initiate the cross-chain bridging of the bridge asset.
To see this is true follow the (🟢1️⃣) numbers that explain the execution in the crossSwap() function below:
See detailed execution flow explanation 👁️
See all code analyzed on the WooCrossChainRouterV4.sol.
Tool used
Manual Review
Recommendation
At
crossSwap()
before sending the bridged token to the user. If thebridgedToken
can be easily compared with thetoToken
as with the sgETH example exposed, then compareminToAmount >= bridgedAmount
If not calculate the conversion of
bridgeToken
andtoToken
to the same accounting unit (USD for example) and compare them.Dont allow cases were fees add up and
minToAmount < bridgedAmount
to keep executing as once cross-chain swap is sent users have no capacity to cancel it.Duplicate of #85
The text was updated successfully, but these errors were encountered: