Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

fix(DOS): cross pool dos vector removed by refunding eth only if weth… #122

Merged
merged 3 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions src/DFMM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,13 @@ contract DFMM is IDFMM {
// Internals

/**
* @dev Transfers `amounts` of `tokens` from the sender to the contract. Note
* that if any ETH is present in the contract, it will be wrapped to WETH and
* used if sufficient. Any excess of ETH will be sent back to the sender.
* @notice Transfers `amounts` of `tokens` from the sender to the contract.
* @dev Note that for pools with `WETH` as a token, the contract will accept
* full payments in native ether. If the contract receives more ether than
* the amount of `WETH` needed, the contract will refund the remaining ether.
* If the contract receives less ether than the amount of `WETH` needed, the
* contract will refund the native ether and request the full amount of `WETH`
* needed instead.
* @param tokens An array of token addresses to transfer.
* @param amounts An array of amounts to transfer expressed in WAD.
*/
Expand All @@ -303,23 +307,30 @@ contract DFMM is IDFMM {
downscaleUp(amount, computeScalingFactor(token));
uint256 preBalance = ERC20(token).balanceOf(address(this));

if (token == weth && address(this).balance >= amount) {
// note: `msg.value` can be used safely in a loop because `weth` is a unique token,
// therefore we only enter this branch once.
if (token == weth && msg.value >= amount) {
WETH(payable(weth)).deposit{ value: amount }();
} else {
SafeTransferLib.safeTransferFrom(
ERC20(token), msg.sender, address(this), downscaledAmount
);
}

// If not enough native ether was sent as payment
// or too much ether was sent,
// refund all the remaining ether back to the sender.
if (token == weth && msg.value != 0) {
SafeTransferLib.safeTransferETH(
msg.sender, address(this).balance
);
}

uint256 postBalance = ERC20(token).balanceOf(address(this));
if (postBalance < preBalance + downscaledAmount) {
revert InvalidTransfer();
}
}

if (address(this).balance > 0) {
SafeTransferLib.safeTransferETH(msg.sender, address(this).balance);
}
}

/**
Expand Down
3 changes: 3 additions & 0 deletions test/DFMM/unit/Init.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ contract DFMMInit is DFMMSetUp, Script {
bytes defaultData =
abi.encode(valid, initialInvariant, defaultReserves, initialLiquidity);

/// @notice for handling ether refunds
receive() external payable { }

function test_DFMM_init_StoresStrategyInitialReservesAndLiquidity()
public
{
Expand Down
Loading