Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

MaslarovK - Insufficient Supply Limit Checks in _stablecoinSwap() Function, Leading to Potential DoS in StablecoinHandler.sol #234

Open
sherlock-admin2 opened this issue Nov 13, 2024 · 0 comments

Comments

@sherlock-admin2
Copy link
Contributor

sherlock-admin2 commented Nov 13, 2024

MaslarovK

Medium

Insufficient Supply Limit Checks in _stablecoinSwap() Function, Leading to Potential DoS in StablecoinHandler.sol

Summary

In the StablecoinHandler.sol contract, the stablecoinSwap() function is used to execute swaps between origin and target tokens. The internal _stablecoinSwap() function performs necessary minting and burning operations depending on whether the tokens are stablecoins or ERC20s. However, the current logic only enforces a minimum supply limit for the origin token and a maximum supply limit for the target token, which is insufficient.

This lack of comprehensive supply limit checks can lead to unexpected scenarios where:

  1. The origin token supply may exceed the maximum limit, causing the system to operate beyond protocol constraints.
  2. The target token supply may drop below the minimum limit, leading to underflow conditions or unintended token shortages.

Without enforcing both minimum and maximum limits for each token, the contract is at risk of potential Denial of Service (DoS) attacks, as future swaps may fail if the token supply constraints are violated.

https://github.com/sherlock-audit/2024-11-telcoin/blob/main/telcoin-audit/contracts/stablecoin/StablecoinHandler.sol#L144-L181

Root Cause

The root cause of this vulnerability is the incomplete checks in _stablecoinSwap() and _verifyStablecoinSwap(). The function currently verifies the following:

  • For the origin token, it ensures the supply does not fall below the minimum after burning.
  • For the target token, it checks that the supply does not exceed the maximum after minting.

However, it does not verify:

  • That the origin token remains within its maximum supply limit.
  • That the target token stays above the minimum supply limit.

Relevant Code Sections

In _verifyStablecoinSwap():

if (isXYZ(ss.origin)) {
    // Only checks the minimum limit after burning the specified amount
    if (Stablecoin(ss.origin).totalSupply() - ss.oAmount < getMinLimit(ss.origin))
        revert InvalidMintBurnBoundry(ss.origin, ss.oAmount);
}

In _stablecoinSwap():

if (isXYZ(ss.target)) {
    // Only checks the maximum limit after minting the specified amount
    if (Stablecoin(ss.target).totalSupply() + ss.tAmount > getMaxLimit(ss.target))
        revert InvalidMintBurnBoundry(ss.target, ss.tAmount);
}

The absence of these checks makes the contract vulnerable to operating beyond protocol-imposed limits, creating risks for system integrity.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

  1. Initiate a Swap:

    • A user initiates a swap with stablecoinSwap() for an origin or target token that is close to or exceeding the protocol-defined limits.
  2. Bypass Comprehensive Limit Checks:

    • Since the contract only verifies the minimum limit for the origin and the maximum limit for the target, a swap could inadvertently cause the origin token supply to exceed the maximum or the target token supply to fall below the minimum.
  3. Potential DoS in Future Transactions:

    • After this transaction, any future swaps may fail if token constraints are violated (i.e., the target token falls below the required minimum, or the origin token supply exceeds the protocol-imposed maximum). This can render certain token pairs unusable until manual intervention corrects the limits.

Impact

The incomplete limit checks in _stablecoinSwap() expose the contract to serious vulnerabilities:

  • Denial of Service (DoS): Future swaps involving these tokens could revert if the supply limits are not within protocol constraints, causing significant disruptions in protocol functionality.
  • System Integrity Risk: Operating with token supplies outside the defined limits violates protocol rules, potentially affecting the protocol's stability and reputation.
  • Unintended Token Supply State: Failing to enforce comprehensive limits may allow certain tokens to exist in an oversupplied or undersupplied state, which is contrary to expected behavior in stablecoin systems.

Example Scenario with Real Values

Assume the following setup:

  • Origin Token: 0xTokenA with minSupply = 1000 and maxSupply = 10,000
  • Target Token: 0xTokenB with minSupply = 500 and maxSupply = 5,000
  1. A user initiates a stablecoinSwap() where:

    • ss.origin = 0xTokenA
    • ss.target = 0xTokenB
    • ss.oAmount = 2,000 (amount to burn from 0xTokenA)
    • ss.tAmount = 1,500 (amount to mint to 0xTokenB)
  2. If TokenA’s total supply is near 10,000 (its maximum), burning 2,000 might keep it within the allowable minimum but would not check if it exceeds the maximum after the burn.

  3. Similarly, if TokenB’s total supply is near 500 (its minimum), minting 1,500 might ensure it’s below the maximum but would not check if it falls below the minimum after the mint.

  4. This operation could leave TokenA in an oversupplied state or TokenB in an undersupplied state, blocking future swaps or causing unpredictable behavior for these tokens.

PoC

No response

Mitigation

To mitigate this vulnerability, implement comprehensive supply limit checks in both _verifyStablecoinSwap() and _stablecoinSwap(). Each token's supply should be verified against both minimum and maximum limits during the swap operation.

Suggested Code Fix

In _verifyStablecoinSwap(), add checks for both the minimum and maximum supply limits for the origin and target tokens:

function _verifyStablecoinSwap(
    address wallet,
    StablecoinSwap memory ss
) internal view nonZero(ss) {
    if (wallet == address(0)) revert ZeroValueInput("WALLET");

    if (isXYZ(ss.origin)) {
        // Ensure total supply is within min and max limits for origin
        uint256 newSupplyOrigin = Stablecoin(ss.origin).totalSupply() - ss.oAmount;
        if (newSupplyOrigin < getMinLimit(ss.origin) || newSupplyOrigin > getMaxLimit(ss.origin)) {
            revert InvalidMintBurnBoundry(ss.origin, ss.oAmount);
        }
    } else if (ss.liquiditySafe == address(0)) {
        revert ZeroValueInput("LIQUIDITY SAFE");
    }

    if (isXYZ(ss.target)) {
        // Ensure total supply is within min and max limits for target
        uint256 newSupplyTarget = Stablecoin(ss.target).totalSupply() + ss.tAmount;
        if (newSupplyTarget < getMinLimit(ss.target) || newSupplyTarget > getMaxLimit(ss.target)) {
            revert InvalidMintBurnBoundry(ss.target, ss.tAmount);
        }
    } else if (ss.liquiditySafe == address(0)) {
        revert ZeroValueInput("LIQUIDITY SAFE");
    }
}

Summary

By enforcing both minimum and maximum limits for each token in the stablecoinSwap() flow, the protocol can avoid operating outside of intended constraints. This will reduce the risk of DoS attacks or inadvertent protocol violations, preserving system integrity and ensuring that token swaps remain reliable and consistent with expected behavior.

@sherlock-admin3 sherlock-admin3 changed the title Faithful Pecan Nightingale - Insufficient Supply Limit Checks in _stablecoinSwap() Function, Leading to Potential DoS in StablecoinHandler.sol MaslarovK - Insufficient Supply Limit Checks in _stablecoinSwap() Function, Leading to Potential DoS in StablecoinHandler.sol Nov 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant