Skip to content

Commit f21c490

Browse files
authored
Merge pull request #206 from ritik4ever/fix/gas-optimization-storage
fix(gas): replace Map blobs with per-key persistent storage in escrow and rewards (#161)
2 parents db332ed + 7aab10b commit f21c490

3 files changed

Lines changed: 360 additions & 70 deletions

File tree

contracts/teachlink/src/escrow.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::insurance::InsuranceManager;
99
use crate::storage::{ESCROWS, ESCROW_COUNT};
1010
use crate::types::{DisputeOutcome, Escrow, EscrowApprovalKey, EscrowSigner, EscrowStatus};
1111
use crate::validation::EscrowValidator;
12-
use soroban_sdk::{symbol_short, vec, Address, Bytes, Env, IntoVal, Map, Vec};
12+
use soroban_sdk::{symbol_short, vec, Address, Bytes, Env, IntoVal, Vec};
1313

1414
pub struct EscrowManager;
1515

@@ -98,9 +98,9 @@ impl EscrowManager {
9898
dispute_reason: None,
9999
};
100100

101-
let mut escrows = Self::load_escrows(env);
102-
escrows.set(escrow_count, escrow.clone());
103-
env.storage().instance().set(&ESCROWS, &escrows);
101+
env.storage()
102+
.persistent()
103+
.set(&(ESCROWS, escrow_count), &escrow);
104104

105105
EscrowAnalyticsManager::update_creation(env, amount);
106106

@@ -449,7 +449,7 @@ impl EscrowManager {
449449
/// // get_escrow(...);
450450
/// ```
451451
pub fn get_escrow(env: &Env, escrow_id: u64) -> Option<Escrow> {
452-
Self::load_escrows(env).get(escrow_id)
452+
env.storage().persistent().get(&(ESCROWS, escrow_id))
453453
}
454454

455455
/// Standard API for get_escrow_count
@@ -520,22 +520,17 @@ impl EscrowManager {
520520
*arbitrator == env.current_contract_address()
521521
}
522522

523-
fn load_escrows(env: &Env) -> Map<u64, Escrow> {
524-
env.storage()
525-
.instance()
526-
.get(&ESCROWS)
527-
.unwrap_or_else(|| Map::new(env))
528-
}
529-
530523
fn load_escrow(env: &Env, escrow_id: u64) -> Result<Escrow, EscrowError> {
531-
let escrows = Self::load_escrows(env);
532-
escrows.get(escrow_id).ok_or(EscrowError::EscrowNotFound)
524+
env.storage()
525+
.persistent()
526+
.get(&(ESCROWS, escrow_id))
527+
.ok_or(EscrowError::EscrowNotFound)
533528
}
534529

535530
fn save_escrow(env: &Env, escrow_id: u64, escrow: Escrow) {
536-
let mut escrows = Self::load_escrows(env);
537-
escrows.set(escrow_id, escrow);
538-
env.storage().instance().set(&ESCROWS, &escrows);
531+
env.storage()
532+
.persistent()
533+
.set(&(ESCROWS, escrow_id), &escrow);
539534
}
540535

541536
fn transfer_from_contract(env: &Env, token: &Address, to: &Address, amount: i128) {

contracts/teachlink/src/rewards.rs

Lines changed: 27 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::storage::{
66
use crate::types::{RewardRate, UserReward};
77
use crate::validation::RewardsValidator;
88

9-
use soroban_sdk::{symbol_short, vec, Address, Env, IntoVal, Map, String};
9+
use soroban_sdk::{symbol_short, vec, Address, Env, IntoVal, String};
1010

1111
pub struct Rewards;
1212

@@ -36,12 +36,6 @@ impl Rewards {
3636
env.storage().instance().set(&REWARD_POOL, &0i128);
3737
env.storage().instance().set(&TOTAL_REWARDS_ISSUED, &0i128);
3838

39-
let reward_rates: Map<String, RewardRate> = Map::new(env);
40-
env.storage().instance().set(&REWARD_RATES, &reward_rates);
41-
42-
let user_rewards: Map<Address, UserReward> = Map::new(env);
43-
env.storage().instance().set(&USER_REWARDS, &user_rewards);
44-
4539
Ok(())
4640
}
4741

@@ -124,25 +118,24 @@ impl Rewards {
124118
return Err(RewardsError::InsufficientRewardPoolBalance);
125119
}
126120

127-
let mut user_rewards: Map<Address, UserReward> = env
121+
let mut user_reward: UserReward = env
128122
.storage()
129-
.instance()
130-
.get(&USER_REWARDS)
131-
.unwrap_or_else(|| Map::new(env));
132-
133-
let mut user_reward = user_rewards.get(recipient.clone()).unwrap_or(UserReward {
134-
user: recipient.clone(),
135-
total_earned: 0,
136-
claimed: 0,
137-
pending: 0,
138-
last_claim_timestamp: 0,
139-
});
123+
.persistent()
124+
.get(&(USER_REWARDS, recipient.clone()))
125+
.unwrap_or(UserReward {
126+
user: recipient.clone(),
127+
total_earned: 0,
128+
claimed: 0,
129+
pending: 0,
130+
last_claim_timestamp: 0,
131+
});
140132

141133
user_reward.total_earned += amount;
142134
user_reward.pending += amount;
143135

144-
user_rewards.set(recipient.clone(), user_reward);
145-
env.storage().instance().set(&USER_REWARDS, &user_rewards);
136+
env.storage()
137+
.persistent()
138+
.set(&(USER_REWARDS, recipient.clone()), &user_reward);
146139

147140
let mut total_issued: i128 = env
148141
.storage()
@@ -188,14 +181,10 @@ impl Rewards {
188181
pub fn claim_rewards(env: &Env, user: Address) -> Result<(), RewardsError> {
189182
user.require_auth();
190183

191-
let mut user_rewards: Map<Address, UserReward> = env
184+
let mut user_reward: UserReward = env
192185
.storage()
193-
.instance()
194-
.get(&USER_REWARDS)
195-
.unwrap_or_else(|| Map::new(env));
196-
197-
let mut user_reward = user_rewards
198-
.get(user.clone())
186+
.persistent()
187+
.get(&(USER_REWARDS, user.clone()))
199188
.ok_or(RewardsError::NoRewardsAvailable)?;
200189

201190
if user_reward.pending <= 0 {
@@ -226,8 +215,9 @@ impl Rewards {
226215
user_reward.pending = 0;
227216
user_reward.last_claim_timestamp = env.ledger().timestamp();
228217

229-
user_rewards.set(user.clone(), user_reward);
230-
env.storage().instance().set(&USER_REWARDS, &user_rewards);
218+
env.storage()
219+
.persistent()
220+
.set(&(USER_REWARDS, user.clone()), &user_reward);
231221

232222
let new_pool_balance = pool_balance - amount_to_claim;
233223
env.storage()
@@ -272,23 +262,15 @@ impl Rewards {
272262
return Err(RewardsError::RateCannotBeNegative);
273263
}
274264

275-
let mut reward_rates: Map<String, RewardRate> = env
276-
.storage()
277-
.instance()
278-
.get(&REWARD_RATES)
279-
.unwrap_or_else(|| Map::new(env));
280-
281-
reward_rates.set(
282-
reward_type.clone(),
283-
RewardRate {
265+
env.storage().persistent().set(
266+
&(REWARD_RATES, reward_type.clone()),
267+
&RewardRate {
284268
reward_type,
285269
rate,
286270
enabled,
287271
},
288272
);
289273

290-
env.storage().instance().set(&REWARD_RATES, &reward_rates);
291-
292274
Ok(())
293275
}
294276

@@ -332,12 +314,7 @@ impl Rewards {
332314
/// // get_user_rewards(...);
333315
/// ```
334316
pub fn get_user_rewards(env: &Env, user: Address) -> Option<UserReward> {
335-
let user_rewards: Map<Address, UserReward> = env
336-
.storage()
337-
.instance()
338-
.get(&USER_REWARDS)
339-
.unwrap_or_else(|| Map::new(env));
340-
user_rewards.get(user)
317+
env.storage().persistent().get(&(USER_REWARDS, user))
341318
}
342319

343320
/// Standard API for get_reward_pool_balance
@@ -400,12 +377,9 @@ impl Rewards {
400377
/// // get_reward_rate(...);
401378
/// ```
402379
pub fn get_reward_rate(env: &Env, reward_type: String) -> Option<RewardRate> {
403-
let reward_rates: Map<String, RewardRate> = env
404-
.storage()
405-
.instance()
406-
.get(&REWARD_RATES)
407-
.unwrap_or_else(|| Map::new(env));
408-
reward_rates.get(reward_type)
380+
env.storage()
381+
.persistent()
382+
.get(&(REWARD_RATES, reward_type))
409383
}
410384

411385
/// Standard API for get_rewards_admin

0 commit comments

Comments
 (0)