hats-finance / Common--Stableswap-0xd4d9a2772202ce33b24901d3fc94e95a84b37430

Apache License 2.0
0 stars 0 forks source link

reserve system will be incorrect for FOT tokens #12

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

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

Github username: -- Twitter username: -- Submission hash (on-chain): 0x027e349f16e2795e04ec0c2e8091c6414f06fb4ea74c6d9d82771b0f43d703fb Severity: medium

Description:

Description

The protocol utilizes a reserve system, whenever a transfer/swap occurrs the reserve of a token gets increased/decreased, as is the case in fn add_liquidity:

    impl StablePool for StablePoolContract {
        #[ink(message)]
        fn add_liquidity(
            &mut self,
            min_share_amount: u128,
            amounts: Vec<u128>,
            to: AccountId,
        ) -> Result<(u128, u128), StablePoolError> {
            ensure!(
                amounts.len() == self.pool.tokens.len(),
                StablePoolError::IncorrectAmountsCount
            );

            // Make sure rates are up to date before we attempt any calculations
            self.update_rates();
            let rates = self.get_scaled_rates(&self.pool.token_rates)?;

            // calc lp tokens (shares_to_mint, fee)
            let (shares, fee_part) = math::rated_compute_lp_amount_for_deposit(
                &rates,
                &amounts,
                &self.reserves(),
                self.psp22.total_supply(),
                Some(&self.pool.fees),
                self.amp_coef(),
            )?;

            // Check min shares
            ensure!(
                shares >= min_share_amount,
                StablePoolError::InsufficientLiquidityMinted
            );

            // transfer amounts
            for (id, &token) in self.pool.tokens.iter().enumerate() {
                self.token_by_address(token).transfer_from(
                    self.env().caller(),
                    self.env().account_id(),
->                    amounts[id],
                    vec![],
                )?;
            }

            // mint shares
            let events = self.psp22.mint(to, shares)?;
            self.emit_events(events);

            // mint protocol fee
            if let Some(fee_to) = self.fee_receiver() {
                let protocol_fee = self.pool.fees.protocol_trade_fee(fee_part)?;
                if protocol_fee > 0 {
                    let events = self.psp22.mint(fee_to, protocol_fee)?;
                    self.emit_events(events);
                }
            }

            // update reserves
->            for (i, &amount) in amounts.iter().enumerate() {
                self.increase_reserve(i, amount)?;
            }

As seen in this codeblock, theamount array get transferred to the desginated account_id, shortly after the amount is added to the respective reserve

The problem however is that whenever dealing with fee on transfer tokens the amount that will be received by the account_id will be less than the amount stored inside the reserves. This means that the accounting of these reverses will be incorrect

Recommendation

Make sure to handle FOT tokens, a possible mitigation is to implement a balance check

whoismxuse commented 3 months ago

invalid, FOT will not be used by the protocol