One Shot: Reloaded

First Flight #47
Beginner FriendlyNFT
100 EXP
Submission Details
Impact: low
Likelihood: high

[L-04] Gas Optimization in Skill Calculation

Author Revealed upon completion

Root + Impact

Description

The skill_of function performs redundant calculations that could be optimized for gas efficiency. The current implementation uses multiple intermediate variables and conditional checks that could be streamlined.

This inefficiency increases gas costs for every battle outcome calculation, affecting all users who participate in battles.

// In one_shot.move
@> public(friend) fun skill_of(token_id: address): u64 acquires RapperStats {
@> let stats_res = borrow_global<RapperStats>(@battle_addr);
@> let s = table::borrow(&stats_res.stats, token_id);
@> let after1 = if (s.weak_knees) { 65 - 5 } else { 65 };
@> let after2 = if (s.heavy_arms) { after1 - 5 } else { after1 };
@> let after3 = if (s.spaghetti_sweater) { after2 - 5 } else { after2 };
@> let final_skill = if (s.calm_and_ready) { after3 + 10 } else { after3 };
@> final_skill
@> }

Risk

Likelihood:

  • Every battle uses this function

  • Redundant calculations occur on every call

  • Gas costs accumulate over time

Impact:

  • Increased gas costs for all battle participants

  • Unnecessary computational overhead

  • Suboptimal user experience due to higher fees

Proof of Concept

This PoC demonstrates the gas inefficiency:

// Demonstrate gas inefficiency
let token_id = /* valid token */;
let start_gas = gas_used();
// Current inefficient calculation
let skill = one_shot::skill_of(token_id);
// Uses 4 intermediate variables and 4 conditional checks
let end_gas = gas_used();
let gas_inefficiency = end_gas - start_gas;
// Result: 4 conditional branches + 4 intermediate variables
// vs optimized version with single calculation

Recommended Mitigation

The mitigation provides an optimized calculation:

public(friend) fun skill_of(token_id: address): u64 acquires RapperStats {
let stats_res = borrow_global<RapperStats>(@battle_addr);
let s = table::borrow(&stats_res.stats, token_id);
- let after1 = if (s.weak_knees) { 65 - 5 } else { 65 };
- let after2 = if (s.heavy_arms) { after1 - 5 } else { after1 };
- let after3 = if (s.spaghetti_sweater) { after2 - 5 } else { after2 };
- let final_skill = if (s.calm_and_ready) { after3 + 10 } else { after3 };
- final_skill
+ let base_skill = 65;
+ base_skill = base_skill - (if (s.weak_knees) 5 else 0);
+ base_skill = base_skill - (if (s.heavy_arms) 5 else 0);
+ base_skill = base_skill - (if (s.spaghetti_sweater) 5 else 0);
+ base_skill = base_skill + (if (s.calm_and_ready) 10 else 0);
+ base_skill
}

This optimization reduces gas costs by eliminating redundant intermediate variables and streamlining the calculation logic.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.