Skip to content

Loops

Soroban Loops
#![no_std]
 
extern crate alloc;
 
use soroban_sdk::{contract, contractimpl, Env, Vec, log};
 
#[contract]
pub struct LoopExample;
 
#[contractimpl]
impl LoopExample {
    /// This function takes a vector of i32 values, iterates through each element, and returns the sum.
    /// It checks for overflow to ensure safe operations and minimizes loop iterations to avoid excessive gas consumption.
    pub fn sum_elements(env: Env, values: Vec<i32>) -> i32 {
        let mut sum: i32 = 0; // i32 is used, be mindful of its limits: -2,147,483,648 to 2,147,483,647
        let length: u32 = values.len();
 
        // Iterate over the vector and sum its elements
        for i in 0..length {
            // Fetch the value at index `i`
            let value: i32 = values.get(i).unwrap_or(0);
 
            // Check for overflow
            match sum.checked_add(value) {
                Some(new_sum) => sum = new_sum,
                None => {
                    log!(&env, "Overflow detected, returning current sum: {}", sum);
                    break;
                }
            }
        }
 
        log!(&env, "Final sum: {}", sum);
        sum
    }
 
    /// A demonstration of how you can loop through a Vec<u32> and do some operation.
    /// It also shows how to use the loop and break patterns with consideration for gas fees.
    pub fn count_even_numbers(env: Env, values: Vec<u32>) -> u32 {
        let mut count: u32 = 0;
        let length: u32 = values.len();
 
        for i in 0..length {
            let value: u32 = values.get(i).unwrap_or(0);
 
            if value % 2 == 0 {
                count += 1;
 
                // Break if count reaches a high number to avoid excessive gas fees
                if count > 1000 {
                    log!(&env, "Count exceeds 1000, stopping early to save gas.");
                    break;
                }
            }
        }
 
        log!(&env, "Total even numbers: {}", count);
        count
    }
 
    /// Allocates a temporary vector holding values (1..=count), then computes and returns their product.
    /// If any overflow occurs, the function logs the current product and stops.
    pub fn multiply(_env: Env, count: u32) -> u128 {
        let mut v1 = alloc::vec![]; // Use alloc crate to create a temporary vector
        (1..=count).for_each(|i| v1.push(i));
 
        let mut product: u128 = 1; // Use u128 to handle larger multiplication results
        for i in v1 {
            // Check for overflow
            match product.checked_mul(i as u128) {
                Some(new_product) => product = new_product,
                None => {
                    // Overflow detected, return current product
                    log!(&_env, "Overflow detected, returning current product: {}", product);
                    break;
                }
            }
        }
 
        log!(&_env, "Final product: {}", product);
        product
    }
}

Run in Playground

Loading playground...