externalSwap function doesnt check if enough eth is sent by the user. Malicious user can withdraw eth stuck in the contract.
Summary
In externalSwap function, the contract doesn't check if the user has sent eth equal to or greater than fromTokenAmount. This results in extra eth sent by user to be stuck in the contract, and an opportunity for a malicious user to be able to withdraw it.
Vulnerability Detail
Looking at the implementation of the externalSwap function, we can see no checks performed anywhere to see if the msg.value >= fromTokenAmount.
Also, when the swapTarget contract is called, the eth sent to it, is fromTokenAmount instead of msg.value.
If the contract has zero eth as balance, then this vulnerability is not an issue. But if it has some eth, it can be withdrawn by anyone.
Lets look at following scenario:
User 1 calls externalSwap function with 2 eth as msg.value, but he wants to swap only for 1 eth, which means fromTokenAmount = 1 eth.
User 1 was able to swap successfully, and DODORouteProxy contract has a balance of 1 eth now.
Next User 2, seeing that the contract has a balance of 1 eth, calls the externalSwap function with 0 eth as msg.value and fromTokenAmount as 1 eth.
Since the contract has a balance of 1 eth, the function call wont revert and User 2 is able to drain the eth.
Impact
Users who accidentally sent more eth can loose their extra eth.
Any eth present in the protocol can be easily drained by an attacker as the POC shows.
Code Snippet
The following POC was written to prove the scenario mentioned above:
ElKu
high
externalSwap
function doesnt check if enough eth is sent by the user. Malicious user can withdraw eth stuck in the contract.Summary
In externalSwap function, the contract doesn't check if the user has sent
eth
equal to or greater thanfromTokenAmount
. This results in extra eth sent by user to be stuck in the contract, and an opportunity for a malicious user to be able to withdraw it.Vulnerability Detail
Looking at the implementation of the externalSwap function, we can see no checks performed anywhere to see if the
msg.value >= fromTokenAmount
.Also, when the
swapTarget
contract is called, the eth sent to it, isfromTokenAmount
instead ofmsg.value
.If the contract has zero eth as balance, then this vulnerability is not an issue. But if it has some eth, it can be withdrawn by anyone.
Lets look at following scenario:
User 1
callsexternalSwap
function with 2 eth asmsg.value
, but he wants to swap only for 1 eth, which meansfromTokenAmount
= 1 eth.User 1
was able to swap successfully, andDODORouteProxy
contract has a balance of 1 eth now.User 2
, seeing that the contract has a balance of 1 eth, calls theexternalSwap
function with 0 eth asmsg.value
andfromTokenAmount
as 1 eth.User 2
is able to drain the eth.Impact
Code Snippet
The following POC was written to prove the scenario mentioned above:
Tool used
VSCode, Hardhat
Recommendation
Add require statements in the
externalSwap
function:Duplicate of #24