#36158 [SC-Low] `Market.collateral_value_to_sell` will always revert if collateral_configuration

Submitted on Oct 22nd 2024 at 08:33:46 UTC by @jasonxiale for IOP | Swaylend

  • Report ID: #36158

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/Swaylend/swaylend-monorepo/blob/9132747331188b86dd8cbf9a1ca37b811d08dddb/contracts/market/src/main.sw

  • Impacts:

    • Contract fails to deliver promised returns, but doesn't lose value

Description

Brief/Intro

In Market.collateral_value_to_sell, while the function tries to calculate the scale in main.sw#L894-L900, `collateral_configuration.decimals - storage.market_configuration.base_token_decimals` is used, the issue is both `collateral_configuration.decimals` and `storage..market_configuration.base_token_decimals`'s type is u32, so if `collateral_configuration.decimals < storage..market_configuration.base_token_decimals`, the calculation will revert.

Vulnerability Details

```Rust 878 #[storage(read)] 879 fn collateral_value_to_sell(asset_id: AssetId, collateral_amount: u64) -> u64 { // decimals: base_token_decimals 880 let collateral_configuration = storage.collateral_configurations.get(asset_id).read(); 881 let market_configuration = storage.market_configuration.read(); 882 ... 894 let scale = u256::from(10_u64).pow( 895 collateral_configuration 896 .decimals - storage <<<--- here might be reverted 897 .market_configuration 898 .read() 899 .base_token_decimals, 900 ); ... 906 } ```

Impact Details

`Market.collateral_value_to_sell` will always revert if collateral_configuration.decimals < storage..market_configuration.base_token_decimals

References

Add any relevant links to documentation or code

Proof of Concept

Proof of Concept

Please put the following code in `swaylend-monorepo/contracts/market/src/main.sw` file, and run ```bash forc test -l ... Compiled contract "market" with 49 warnings. Finished debug [unoptimized + fuel] target(s) [168.928 KB] in 48.32s Running 2 tests, filtered 0 tests test test_no_revert_overflow ... ok (200.787µs, 491 gas) Decoded log value: 10, log rb: 1970142151624111756 test test_revert_overflow ... ok (111.65µs, 61 gas)

test result: OK. 2 passed; 0 failed; finished in 312.437µs ```

as the output shows, test case `test_revert_overflow` will revert because `collateral_token_decimals` is smaller than `base_token_decimals`

```Rust #[test] fn test_no_revert_overflow() { let base_token_decimals: u32 = 9; let collateral_token_decimals: u32 = 10; let scale = u256::from(10_u64).pow(collateral_token_decimals - base_token_decimals); log(scale); }

#[test(should_revert)] fn test_revert_overflow() { let base_token_decimals: u32 = 9; let collateral_token_decimals: u32 = 6; let scale = u256::from(10_u64).pow(collateral_token_decimals - base_token_decimals); log(scale); } ```