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
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
:As seen in this codeblock, the
amount
array get transferred to the desginatedaccount_id
, shortly after theamount
is added to the respective reserveThe problem however is that whenever dealing with fee on transfer tokens the
amount
that will be received by theaccount_id
will be less than theamount
stored inside the reserves. This means that the accounting of these reverses will be incorrectRecommendation
Make sure to handle FOT tokens, a possible mitigation is to implement a balance check