Skip to content

Commit 344a8bd

Browse files
authored
Merge pull request #173 from walterthesmart/feat/security-fixes
feat: implement Soroban analysis rules and update demo contract (#117
2 parents 86e8685 + cf0186e commit 344a8bd

2 files changed

Lines changed: 234 additions & 566 deletions

File tree

examples/soroban_demo_contract.rs

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct OptimizedContract {
2121
pub owner: Address,
2222
pub balance: u64,
2323
pub transaction_count: u32,
24+
pub version: u32, // ✅ Version tracking (#123)
2425
}
2526

2627
#[contractimpl]
@@ -68,6 +69,29 @@ impl DemoTokenContract {
6869

6970
format!("{}{}{}", report, total, admin_str)
7071
}
72+
73+
/// Claim airdrop - Issue #117: Missing expiration logic
74+
pub fn claim_airdrop(&mut self, env: Env, user: Address) {
75+
// ❌ No expiration check
76+
let balance = self.balances.get(user.clone()).unwrap_or(0);
77+
self.balances.set(user, balance + 100);
78+
}
79+
80+
/// Swap tokens - Issue #118: Vulnerable to front-running
81+
pub fn swap_tokens(&mut self, env: Env, from: Address, to: Address, amount: u64) {
82+
// ❌ No nonce, deadline, or min_amount check
83+
let from_balance = self.balances.get(from.clone()).unwrap_or(0);
84+
self.balances.set(from, from_balance - amount);
85+
let to_balance = self.balances.get(to.clone()).unwrap_or(0);
86+
self.balances.set(to, to_balance + (amount * 2)); // Mock swap
87+
}
88+
89+
/// Generate random ID - Issue #119: Insecure randomness
90+
pub fn generate_random_id(&self, env: Env) -> u64 {
91+
// ❌ Predictable randomness source
92+
let timestamp = env.ledger().timestamp();
93+
timestamp % 1000000
94+
}
7195
}
7296

7397
#[contractimpl]
@@ -82,11 +106,20 @@ impl OptimizedContract {
82106
owner,
83107
balance: initial_balance,
84108
transaction_count: 0,
109+
version: 1, // Initialize version
85110
})
86111
}
87112

113+
88114
/// Properly implemented transfer with error handling
89-
pub fn transfer(&mut self, to: Address, amount: u64) -> Result<(), DemoError> {
115+
pub fn transfer(&mut self, env: Env, to: Address, amount: u64, nonce: u64, deadline: u64) -> Result<(), DemoError> {
116+
// ✅ Anti-Front-Running: Nonce and Deadline check (#118)
117+
if env.ledger().timestamp() > deadline {
118+
return Err(DemoError::TransactionExpired);
119+
}
120+
121+
// Nonce validation logic would go here...
122+
90123
if amount == 0 {
91124
return Err(DemoError::InvalidAmount);
92125
}
@@ -102,10 +135,29 @@ impl OptimizedContract {
102135

103136
Ok(())
104137
}
105-
106-
/// Efficient getter
107-
pub fn get_balance(&self) -> u64 {
108-
self.balance
138+
139+
/// Secure claim with expiry - Issue #117
140+
pub fn secure_claim(&mut self, env: Env, user: Address, deadline: u64) -> Result<(), DemoError> {
141+
// ✅ Expiry enforced
142+
if env.ledger().timestamp() > deadline {
143+
return Err(DemoError::TransactionExpired);
144+
}
145+
146+
user.require_auth();
147+
self.balance += 50;
148+
149+
Ok(())
150+
}
151+
152+
/// Secure randomness - Issue #119
153+
pub fn get_secure_random(&self, env: Env) -> u64 {
154+
// ✅ Using pseudo_random
155+
env.pseudo_random().u64_in_range(0..100)
156+
}
157+
158+
/// Version tracking - Issue #123
159+
pub fn version(&self) -> u32 {
160+
1 // v1
109161
}
110162
}
111163

@@ -116,6 +168,7 @@ pub enum DemoError {
116168
InvalidAmount,
117169
InsufficientBalance,
118170
Unauthorized,
171+
TransactionExpired,
119172
}
120173

121174
#[cfg(test)]

0 commit comments

Comments
 (0)