xanoutas/solidity-security-findings huggingface dataset:
Use of `u64` for `price_per_day` and `price_per_month` limits handling tokens with 18 decimals  
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/main/contracts/codedestate/src/msg.rs#L168
https://github.com/code-423n4/2024-10-coded-estate/blob/main/contracts/codedestate/src/msg.rs#L111


# Vulnerability details

## Impact  
The use of `u64` for `price_per_day` and `price_per_month` prevents setting rental prices higher than approximately 18 tokens when using tokens with 18 decimals, potentially restricting landlords from setting appropriate rental prices in tokens with 18 decimals.  
## Proof-of-Concept  
The `SetListForShortTermRental` and `SetListForLongTermRental` enums in the contract use `u64` for `price_per_day` and `price_per_month` respectively, while the corresponding functions, `setlistforshorttermrental` and `setlistforlongtermrental`, also define these prices as `u64`.  

```rust
File: contracts/codedestate/src/msg.rs
pub enum ExecuteMsg<T, E> {
    SetListForShortTermRental {
        token_id: String,
        denom: String,
        price_per_day: u64, // <-- here
        auto_approve: bool,
        available_period: Vec<String>,
        minimum_stay: u64,
        cancellation: Vec<CancellationItem>,
    },
    SetListForLongTermRental {
        token_id: String,
        denom: String,
        price_per_month: u64, // <-- here
        auto_approve: bool,
        available_period: Vec<String>,
        minimum_stay: u64,
        cancellation: Vec<CancellationItem>,
    },
}

File: contracts/codedestate/src/execute.rs
pub fn setlistforshorttermrental(
    &self,
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    token_id: String,
    denom: String,
    price_per_day: u64, // <--
    auto_approve: bool,
    available_period: Vec<String>,
    minimum_stay:u64,
    cancellation:Vec<CancellationItem>,
) -> Result<Response<C>, ContractError> {... snipped ...}

pub fn setlistforlongtermrental(
    &self,
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    token_id: String,
    denom: String,
    price_per_month: u64, // <--
    auto_approve: bool,
    available_period: Vec<String>,
    minimum_stay: u64,
    cancellation: Vec<CancellationItem>,
) -> Result<Response<C>, ContractError> {... snipped ...}
```

This poses a problem when dealing with tokens with 18 decimals, as the maximum value `u64` can store is approximately `1.8446744e+19`. In contrast, `u128`, which is used elsewhere in the contract for handling token amounts (e.g., `info.funds[0].amount`), can accommodate much larger values, fully supporting tokens with 18 decimals.  

This mismatch can create issues when landlords attempt to specify rental prices. For example, when a token is worth `$1` (with 18 decimals), the maximum price that can be set per day or month is capped at approximately 18 tokens ~ `$18`, potentially preventing landlords from setting appropriate rental prices for their properties.    

Additionally, since Nibiru chain, the deployment chain for Coded Estate, supports custom denominated tokens, landlords may select tok
Incorrect use of `u64` for arg `amount` in `withdrawtolandlord` can cause withdrawal failure
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/main/contracts/codedestate/src/execute.rs#L1786-L1796
https://github.com/code-423n4/2024-10-coded-estate/blob/main/contracts/codedestate/src/msg.rs#L156-L162


# Vulnerability details

## Impact  
The use of `u64` for token amount in the `withdrawtolandlord` function can lead to failed withdrawals when handling tokens with 18 decimals, limiting the landlord’s ability to withdraw their entitled funds if the amount exceeds the maximum value of `u64`.  

## Proof-of-Concept  
In the `withdrawtolandlord` function, the token amount is defined as a `u64` value. However, this can cause issues when handling tokens with 18 decimals, as the `u64` data type can only store values up to approximately `1.8446744e+19` ~ `18` token of token with 18 decimals. This limit is significantly lower than what is supported by `u128`, which is used in other parts of the contract to handle token amount, such as `info.funds[0].amount` is a `U128` type.  

```rust
File: contracts/codedestate/src/execute.rs
pub fn withdrawtolandlord(
    &self,
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    token_id: String,
    tenant: String,
    renting_period: Vec<String>,
    amount:u64,
    address:String
) -> Result<Response<C>, ContractError> { ... snipped ...}

File: contracts/codedestate/src/msg.rs
pub enum ExecuteMsg<T, E> {
    ...snipped...
    ...
    WithdrawToLandlord {
        token_id: String,
        tenant: String,
        renting_period: Vec<String>,
        amount: u64,
        address: String,
    },
    ...snipped...
    ...
```

This discrepancy between the data types can create an issue. If the token amount owed to the landlord exceeds the maximum value supported by `u64`, the landlord will not be able to withdraw their entitled funds through the `withdrawtolandlord` function.  

This is problematic as the Nibiru chain, the chain on which Coded Estate is deployed, supports custom denominated tokens, and users can specify tokens with 18 decimals as their payment currency. For example, if a large payment is made in such a token, the landlord would be unable to withdraw the full amount due to the limitations of the `u64` type.  

See: https://github.com/NibiruChain/nibiru/blob/main/x/tokenfactory/keeper/msg_server.go#L18-L41

### Example Scenario:
1. A user pays deposit using a token with 18 decimals.  
2. The total deposit amount exceeds the maximum value of `u64` (~18 tokens for 18-decimal tokens).  
3. When the landlord tries to withdraw their funds via the `withdrawtolandlord` function, the function fails because the `u64` type cannot accommodate the large token amount.  
4. As a result, the landlord is unable to withdraw their funds, leading to loss of access to legitimate payments.  

## Recommended Mitigations  
- Change type of `amount` to `u128` for consistency with other parts in the system.  


## Assessed type

Context
incorrect refund amount is sent  to the tenant if long term reservation is cancelled after approval 
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1647-L1683
https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1727-L1731


# Vulnerability details

## Impact
`token.longterm_rental.cancellation.percentage` is not deducted from the `token.longterm_rental.deposit_amount` and refunded back to the user as expected after a `cancelreservationafterapprovalforlongterm()` call to cancel a reservation that has been approved. 

## Proof Of Concept 
https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1647-L1683
```rust 
    pub fn cancelreservationafterapprovalforlongterm(
        &self,
        deps: DepsMut,
        info: MessageInfo,
        token_id: String,
        renting_period: Vec<String>
    ) -> Result<Response<C>, ContractError> {
        let mut token = self.tokens.load(deps.storage, &token_id)?;

        let mut position: i32 = -1;
        // let mut amount = Uint128::from(0u64);
        // let tenant_address = info.sender.to_string();
        for (i, item) in token.rentals.iter().enumerate() {
            if item.address == Some(info.sender.clone()) && item.renting_period[0].to_string() == renting_period[0]
            && item.renting_period[1].to_string() == renting_period[1]
             {
                if item.approved_date.is_none() {
                    return Err(ContractError::NotApproved {});
                } else {
                    position = i as i32;
                    // amount = item.deposit_amount;
                }
            }
        }

        if position != -1 {
            // token.rentals.remove(position as usize);
            token.rentals[position as usize].cancelled = true;
            self.tokens.save(deps.storage, &token_id, &token)?;
            Ok(Response::new()
            .add_attribute("action", "cancelreservationafterapprovalforlongterm")
            .add_attribute("sender", info.sender)
            .add_attribute("token_id", token_id))
        } else {
            return Err(ContractError::NotReserved {});
        }
    }
```
in the `cancelreservationafterapprovalforlongterm()` we can see how no money is refunded to the tenant after cancellation is made after approval. The function does not calculate the refundable amount incase of a cancellation by tenant after approval like it is done in `cancelreservationafterapprovalforshortterm()`. See [here](https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1083-L1112). 

A landlord can set that cancellations after approval will happen with a 90% refund via `setlistforlongtermrental()`, where the         `token.longterm_rental.cancellation.percentage` will be set to 90. But this will never be enforced in the `canc
`depositforlongtermrental()` does not validate the `sent_amount`
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1544-L1590


# Vulnerability details

## Impact
`depositforlongtermrental()` does not validate the `sent_amount`. It doesn't 
- check if amount sent in is enough to pay for rent for the rental's minimum_stay.  
- deduct the protocol fee percentage from the amount sent in. The protocol earns no fees from a `setreservationforlongterm()` + `depositforlongtermrental()` action. 

## Proof Of Concept 
https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1544-L1590
```rust
    pub fn depositforlongtermrental(
        &self,
        deps: DepsMut,
        info: MessageInfo,
        token_id: String,
        renting_period: Vec<String>,
    ) -> Result<Response<C>, ContractError> {
        let mut token = self.tokens.load(deps.storage, &token_id)?;

        let mut position: i32 = -1;
        let sent_amount = info.funds[0].amount;
        if info.funds[0].denom != token.longterm_rental.denom {
            return Err(ContractError::InvalidDeposit {});
        }

        if sent_amount > Uint128::new(0)
        {
            for (i, item) in token.rentals.iter().enumerate() {
                if item.address == Some(info.sender.clone()) && item.renting_period[0].to_string() == renting_period[0]
                && item.renting_period[1].to_string() == renting_period[1]
                {
                   position = i as i32;
                }
            }
    
            if position == -1 {
                return Err(ContractError::NotReserved {});
            }
    
            // let fee_percentage = self.get_fee(deps.storage)?;
    
            token.rentals[position as usize].deposit_amount += 
            Uint128::from(sent_amount); 
            //@audit no calculation for if the sent_amount is suffificent enough to cover the rent amount required for the renting period  
            //@audit contract recieves money but doesnt track it? it is commented out? how will the owner withdraw fee amount, why is fee percentage not collected here?
            // self.increase_balance(deps.storage, info.funds[0].denom.clone(), Uint128::new((u128::from(sent_amount) * u128::from(fee_percentage)) / 10000))?;
            self.tokens.save(deps.storage, &token_id, &token)?;
        }
        else {
            return Err(ContractError::InsufficientDeposit {});
        }



        Ok(Response::new()
            .add_attribute("action", "depositforlongtermrental")
            .add_attribute("sender", info.sender)
            .add_attribute("token_id", token_id))
    }
```

`depositforlongtermrental()` is meant to be called after `setreservationforlongterm()` by the tenant to make rent payment for the property to be rented. Each long term rental property's token struct has a `token.longterm_rental.price_per_month` value, this value is set b
Lack of upfront cost for long-term reservations allows fake reservations, blocking real users  
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/main/contracts/codedestate/src/execute.rs#L1341-L1433


# Vulnerability details

## Impact  
This issue allows a malicious actor to reserve long-term rentals without upfront payment, making large time slots unavailable for other potential renters. It creates an unfair scenario where legitimate users are blocked out from booking, as the property becomes unavailable for both short-term and long-term rentals during the reserved period. This could lead to decreased revenue for property owners.  

## Description  
The `setreservationforlongterm` function allows users to reserve long-term rentals without any upfront payment. Once a reservation is made, the reserved period is marked as unavailable, blocking other users from reserving the same property during that period for either long-term or short-term rentals.  

```rust
pub fn setreservationforlongterm(
    &self,
    deps: DepsMut,
    info: MessageInfo,
    token_id: String,
    renting_period: Vec<String>,
    guests:usize,
) -> Result<Response<C>, ContractError> {
    let mut token = self.tokens.load(deps.storage, &token_id)?;
    let new_checkin = renting_period[0].parse::<u64>();
    let new_checkin_timestamp;

    match new_checkin {
        Ok(timestamp) => {
            new_checkin_timestamp = timestamp;
        }
        Err(_e) => {
            return Err(ContractError::NotReserved {});
        }
    }
    let new_checkout = renting_period[1].parse::<u64>();
    let new_checkout_timestamp;

    match new_checkout {
        Ok(timestamp) => {
            new_checkout_timestamp = timestamp;
        }
        Err(_e) => {
            return Err(ContractError::NotReserved {});
        }
    }

    if ((new_checkout_timestamp - new_checkin_timestamp)/ 86400) < token.longterm_rental.minimum_stay {
        return Err(ContractError::LessThanMinimum {});
    }

    let mut placetoreserve: i32 = -1;
    let lenofrentals = token.rentals.len();

    let mut flag = false;
    // @c4-contest: if the renting period overlap with an existing rental, the placetoreserve will be -1
    for (i, tenant) in token.rentals.iter().enumerate() {
        let checkin = tenant.renting_period[0];
        let checkout = tenant.renting_period[1];
        if new_checkout_timestamp < checkin {
            if i == 0 {
                placetoreserve = 0;
                break;
            } else if flag {
                placetoreserve = i as i32;
                break;
            }
        } else if checkout < new_checkin_timestamp {
            flag = true;
            if i == lenofrentals - 1 {
                placetoreserve = lenofrentals as i32;
                break;
            }
        } else {
            flag = false;
        }
    }

    if placetoreserve == -1 {
        if lenofrentals > 0 {
            return Err(ContractError::UnavailablePeriod {});
        } else {
            placetoreserve = 0;
        }
    }

    let tenant = Rental
reservations can be made outside of rental property's available_period
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1353-L1374
https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L795-L817


# Vulnerability details

## Impact
no check for if the `renting_period` is within the rentals available period (`token.shortterm_rental.available_period`). This means that reservations can be made to rent the property on dates outside its available period. 

## Proof Of Concept 
property managers/landlords can list a property via `setlistforshorttermrental()` and `setlistforshorttermrental()`. In both of these functions, the parameter `available_period` is accepted and is set into the rental token's struct in storage as seen below 

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L722-L742
```rust
    pub fn setlistforshorttermrental(
        .....

        available_period: Vec<String>,

        ....
    ) -> Result<Response<C>, ContractError> {
        ......
        token.shortterm_rental.available_period = available_period;
        ....
    }
```

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L1280-L1300
```rust
    pub fn setlistforlongtermrental(
        .....

        available_period: Vec<String>,

        ....
    ) -> Result<Response<C>, ContractError> {
        ......
        token.longterm_rental.available_period = available_period;
        ....
    }
```

In these functions, the rental's available time is specified by the property manager/owner and this is set into storage. 

But users can still make reservations for the property for times outside the rental's available period. This is because `setreservationforshortterm()` and `setreservationforlongterm()` do not check that the `renting_period` specified by a renting user is within the rental property's `available_period`. As seen below in both functions, they only check that the `renting_period` is more than the rental's minimum stay duration, i.e more than 1 day if minimum duration is 1 day. A real world scenario example of this bug is that a user can make still reservations for july 21 - 25 even though the property owner/manager has specified that the rental's available period is only june 21 - 25. 

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L795-L817
```rust
        let new_checkout = renting_period[1].parse::<u64>();
        let new_checkout_timestamp;

        match new_checkout {
            Ok(timestamp) => {
                new_checkout_timestamp = timestamp;
            }
            Err(_e) => {
                return Err(ContractError::NotReserved {});
            }
        }

        if ((new_checkout_time
can impersonate another high value rental because token_uri is arbitrary and supplied by user. 
Audit: 2024-10-coded-estate-findings
Severity: MEDIUM

# Lines of code

https://github.com/code-423n4/2024-10-coded-estate/blob/97efb35fd3734676f33598e6dff70119e41c7032/contracts/codedestate/src/execute.rs#L255


# Vulnerability details

## Impact
because `token_uri` value is not sanitized and is arbitrary/provided by a user, a malicious user can provide a token uri which may have " or , or simply a fake url which points to a different higher value rental property in order to phish unsuspecting users. 

## Proof Of Concept 

```rust
    pub fn mint(
        &self,
        deps: DepsMut,
        info: MessageInfo,
        token_id: String,
        owner: String,
        token_uri: Option<String>,
        extension: T,
    ) -> Result<Response<C>, ContractError> {
        //@audit no money collected to mint a token? do they mint for free? 
        // cw_ownable::assert_owner(deps.storage, &info.sender)?;

        let longterm_rental = LongTermRental {
            islisted: None,
            price_per_month: 0u64,
            available_period:vec![],
            deposit_amount: Uint128::from(0u64),
            withdrawn_amount: Uint128::from(0u64),
            denom:"ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349".to_string(),
            auto_approve:false,
            cancellation:vec![],
            minimum_stay:0u64,
        };

        let shortterm_rental = ShortTermRental {
            islisted: None,
            price_per_day: 0u64,
            available_period: vec![],
            deposit_amount: Uint128::from(0u64),
            withdrawn_amount: Uint128::from(0u64),
            denom: "ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349".to_string(),
            auto_approve: false,
            cancellation:vec![],
            minimum_stay:0u64,
        };

        let sell = Sell {
            islisted:None,
            auto_approve:false,
            price:0u64,
            denom:"ibc/F082B65C88E4B6D5EF1DB243CDA1D331D002759E938A0F5CD3FFDC5D53B3E349".to_string(),            
        };

        // create the token
        let token = TokenInfo {
            owner: info.sender.clone(),
            approvals: vec![],
            rentals:vec![],
            bids:vec![],
            longterm_rental,
            shortterm_rental,
            sell,
            token_uri, 
            extension,
        };

        self.tokens
            .update(deps.storage, &token_id, |old| match old {
                Some(_) => Err(ContractError::Claimed {}),
                None => Ok(token),
            })?;

        self.increment_tokens(deps.storage)?;

        Ok(Response::new()
            .add_attribute("action", "mint")
            .add_attribute("minter", info.sender)
            .add_attribute("owner", owner) //@audit here owner arg is used but in the token object owner is set to info.sender. owner may not be info.sender
            .add_attribute("token_id", token_id))
    }

```
lets say a malicious user wants to make a rental that impersonates another high valu