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

Obedient Umber Osprey - Wrong implement of sell_fee_criticalMultiplier #249

Open
sherlock-admin4 opened this issue Dec 31, 2024 · 0 comments

Comments

@sherlock-admin4
Copy link

Obedient Umber Osprey

Medium

Wrong implement of sell_fee_criticalMultiplier

Summary

wrong calculation of getSellFeeScaling.

Root Cause

https://github.com/sherlock-audit/2024-12-numa-audit/blob/main/Numa/contracts/NumaProtocol/VaultManager.sol#L57

uint public sell_fee_criticalMultiplier = 10000; // base 1000

function getSellFeeScaling() public view returns (uint, uint, uint) {
uint blockTime = block.timestamp;
uint lastSellFee = sell_fee_withPID;
// if PID/debase has already been updated in that block, no need to compute, we can use what's stored
if (blockTime != lastBlockTime_sell_fee) {
// synth scaling
uint currentLiquidCF = getGlobalLiquidCF();
if (currentLiquidCF < cf_liquid_severe) {
// we need to debase
// debase linearly
uint ndebase = ((blockTime - lastBlockTime_sell_fee) *
sell_fee_debaseValue) / (sell_fee_deltaDebase);

            if (ndebase <= 0) {
                // not enough time has passed to get some debase, so we reset our time reference
                blockTime = lastBlockTime_sell_fee;
            } else {
                if (lastSellFee > ndebase) {
                    lastSellFee = lastSellFee - ndebase;
                    // clip to minimum
                    if (lastSellFee < sell_fee_minimum)
                        lastSellFee = sell_fee_minimum;
                } else lastSellFee = sell_fee_minimum;
            }
        } else {
            if (sell_fee_withPID < sell_fee) {
                // we have debased so we need to rebase
                uint nrebase = ((blockTime - lastBlockTime_sell_fee) *
                    sell_fee_rebaseValue) / (sell_fee_deltaRebase);
                if (nrebase <= 0) {
                    // not enough time has passed to get some rebase, so we reset our time reference
                    blockTime = lastBlockTime_sell_fee;
                } else {
                    lastSellFee = lastSellFee + nrebase;
                    if (lastSellFee > sell_fee) lastSellFee = sell_fee;
                }
            }
        }
    }

    // Sell fee increase also considers synthetics critical scaling.
    // So, if synthetics are debased 4% in critical, then the sell fee should be 9% (5% + 4%)
    // Whichever sell fee is greater should be used at any given time
    // we use criticalScaleForNumaPriceAndSellFee because we want to use this scale in our sell_fee only when cf_critical is reached
    (, , uint criticalScaleForNumaPriceAndSellFee, ) = getSynthScaling();

    uint sell_fee_increaseCriticalCF = ((BASE_1000 -
        criticalScaleForNumaPriceAndSellFee) * 1 ether) / BASE_1000;
    // add a multiplier on top
    sell_fee_increaseCriticalCF =

@>> (sell_fee_increaseCriticalCF * sell_fee_criticalMultiplier) /
1000;

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

No response

Impact

wrong calculation of getSellFeeScaling.

PoC

No response

Mitigation

uint public sell_fee_criticalMultiplier = 1000; // base 1000
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