hats-finance / illuminex-0x0bb4aa1f58719707405c231fcdf0b405714799cf

0 stars 1 forks source link

Denial of Service (DoS) Vulnerability in withdraw Function #26

Open hats-bug-reporter[bot] opened 3 months ago

hats-bug-reporter[bot] commented 3 months ago

Github username: @Jelev123 Twitter username: zhulien_zhelev Submission hash (on-chain): 0xef393fd0481e21a92c3a98c3928871a8a55c624473c321dcb2c8bf0bd05871c7 Severity: medium

Description: Description\ The withdraw function in the contract calculates amountAfterFee, which represents the amount left after deducting network fees and protocol fees from the original amount. The function then compares this amountAfterFee with a user-provided minReceiveAmount to ensure the final amount received is at least the minimum specified by the user. However, this creates a potential vulnerability where an attacker can repeatedly set a minReceiveAmount greater than the amountAfterFee, causing the transaction to revert. This can be exploited to create a Denial of Service (DoS) attack.

Attack Scenario\

  1. Proof of Concept (PoC) File https://github.com/hats-finance/illuminex-0x0bb4aa1f58719707405c231fcdf0b405714799cf/blob/db34511e17fdf281aacef4267c300431d3ac12d7/packages/contracts/contracts/illuminex/xengine/chains/btc/wallet/VaultBitcoinWallet.sol#L385

Recommendation

function withdraw(bytes memory to, uint64 amount, uint64 minReceiveAmount, bytes32 idSeed) public {
    uint64 amountAfterNetworkFee = amount - (BYTES_PER_OUTGOING_TRANSFER * satoshiPerByte);
    require(amountAfterNetworkFee >= minWithdrawalLimit, "AFL");

    uint64 protocolFees = amountAfterNetworkFee * withdrawalFee / 1000;
    if (isExcludedFromFees[msg.sender]) {
        protocolFees = 0;
    }

    uint64 amountAfterFee = amountAfterNetworkFee - protocolFees;

    // Additional check to prevent DoS attack
    require(minReceiveAmount <= amountAfterNetworkFee, "MRA_TOO_HIGH");

    require(amountAfterFee >= minReceiveAmount, "FTH");

    btcToken.burn(msg.sender, amount);
    if (protocolFees > 0) {
        btcToken.mint(owner(), protocolFees);
    }

    bytes32 _transferId = keccak256(abi.encodePacked(idSeed, to, amount));
    queue.push(
        OutgoingQueue.OutgoingTransfer(
            BitcoinUtils.resolveLockingScript(to, _isTestnet(), workingScriptSet),
            amountAfterFee,
            _transferId
        )
    );
}
party-for-illuminati commented 3 months ago

Spam

Jelev123 commented 3 months ago

@party-for-illuminati it maybe is invalid but it doesn`t spam!