# Attackathon \_ Fuel Network 33170 - \[Smart Contract - Medium] UFP Exp In Sway-lib Logic Vulnerability

Submitted on Sat Jul 13 2024 10:02:26 GMT-0400 (Atlantic Standard Time) by @Minato7namikazi for [Attackathon | Fuel Network](https://immunefi.com/bounty/fuel-network-attackathon/)

Report ID: #33170

Report type: Smart Contract

Report severity: Medium

Target: <https://github.com/FuelLabs/sway-libs/tree/0f47d33d6e5da25f782fc117d4be15b7b12d291b>

Impacts:

* Permanent freezing of funds

## Description

## Brief/Intro

During my audit of the UFP (unsigned fixed-point number) implementations in the sway-libs , this logic vulnerability were identified. This could lead to incorrect calculations in any smart contracts or scripts relying on this function and cause massive losses.

## Vulnerability Details

```
impl Exponent for UFP128 {
    fn exp(exponent: Self) -> Self {
        let one = UFP128::from((1, 0));
        let p2 = one / UFP128::from((2, 0));
        let p3 = one / UFP128::from((6, 0));
        let p4 = one / UFP128::from((24, 0));
        let p5 = one / UFP128::from((120, 0));
        let p6 = one / UFP128::from((720, 0));
        let p7 = one / UFP128::from((5040, 0));

        // common technique to counter losing sugnifucant numbers in usual approximation
        let _res_minus_1 = exponent + exponent * exponent * (p2 + exponent * (p3 + exponent * (p4 + exponent * (p5 + exponent * (p6 + exponent * p7)))));
        let res = one;
        res
    }
}
```

### The function calculates `_res_minus_1` correctly .. but then it ignores this calculation and simply returns `one`. This means the exponential function will always return 1, regardless of the input.

### The impact is Loss of funds because of

* Incorrect Financial Calculations : using the vulnerable exponential function for compound interest, option pricing, or yield calculations. With this bug, all such calculations would return 1, regardless of the input.
* Some token distribution models or staking rewards systems use exponential decay or growth. This bug would make such systems non-functional, potentially: Distributing incorrect amounts of tokens

### Recommendation

we should use the calculated result like

```rust

impl Exponent for UFP128 {
    fn exp(exponent: Self) -> Self {
        let one = UFP128::from((1, 0));
        let p2 = one / UFP128::from((2, 0));
        let p3 = one / UFP128::from((6, 0));
        let p4 = one / UFP128::from((24, 0));
        let p5 = one / UFP128::from((120, 0));
        let p6 = one / UFP128::from((720, 0));
        let p7 = one / UFP128::from((5040, 0));

        // Common technique to counter losing significant numbers in usual approximation
        let res_minus_1 = exponent + exponent * exponent * (p2 + 
                         exponent * (p3 + exponent * (p4 + 
                         exponent * (p5 + exponent * (p6 + 
                         exponent * p7)))));

        one + res_minus_1
    }
}

```

* Now it's calculates the exponential function using a Taylor series approximation and should return the correct result. the function now adds 1 to the calculated `res_minus_1` to get the final result, as the original calculation was for (e^x - 1).

## Proof of concept

## Add this PoC test in the end of the ufp128.sw

```

#[test]
fn PoC_exp() {


    let one = UFP128::from_uint(1);
    let res = UFP128::exp(one);
    assert(res == UFP128::from((1, 0)));


    let two = UFP128::from_uint(2);
    let res = UFP128::exp(two);
    assert(res == UFP128::from((1, 0)));


    let three = UFP128::from_uint(3);
    let res = UFP128::exp(three);
    assert(res == UFP128::from((1, 0)));


    let four = UFP128::from_uint(4);
    let res = UFP128::exp(four);
    assert(res == UFP128::from((1, 0)));


    let five = UFP128::from_uint(5);
    let res = UFP128::exp(five);
    assert(res == UFP128::from((1, 0)));


    let six = UFP128::from_uint(6);
    let res = UFP128::exp(six);
    assert(res == UFP128::from((1, 0)));


    let seven = UFP128::from_uint(7);
    let res = UFP128::exp(seven);
    assert(res == UFP128::from((1, 0)));


    let eight = UFP128::from_uint(8);
    let res = UFP128::exp(eight);
    assert(res == UFP128::from((1, 0)));


    let nine = UFP128::from_uint(9);
    let res = UFP128::exp(nine);
    assert(res == UFP128::from((1, 0)));


}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://reports.immunefi.com/fuel-network-or-attackathon/attackathon-_-fuel-network-33170-smart-contract-medium-ufp-exp-in-sway-lib-logic-vulnerability.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
