sherlock-audit / 2024-09-orderly-network-solana-contract-judging

0 stars 0 forks source link

Petite Pecan Starfish - users can deposit more than expected in rate limiter #83

Open sherlock-admin3 opened 4 days ago

sherlock-admin3 commented 4 days ago

Petite Pecan Starfish

Medium

users can deposit more than expected in rate limiter

Summary

users can deposit more than expected in rate limiter

Root Cause

admin can set capacity and refill_per_second but if capacity will be updated by admin users can deposit more than expected

PoC

Textual PoC: let's assume capcity is 1000 and refill_per_second is 1 and alice deposits 1000 token in vault at T1 and in this moment tokens is 0 its mean another users cannot deposit becuase there isn't capacity and after 60 seconds users just can deposit 60 token becuase of refill_per_second and if admin increase capacity to 1200 in T1 + 60 users should can deposit 200 + 60 token becuase capcity will be increased by admin but when capcity will be updated by admin also tokens will be updated as well and new value for tokens is new capcity and in result users can deposit 1200 tokens instead of 200 + 60 tokens

pub struct RateLimiter {
    pub capacity: u64,
    pub tokens: u64,//remaining capacity and for every consume this value will be updated
    pub refill_per_second: u64,
    pub last_refill_time: u64,
}

Code Snippet

https://github.com/sherlock-audit/2024-09-orderly-network-solana-contract/blob/main/solana-vault/packages/solana/contracts/programs/solana-vault/src/state/oapp_state/peer.rs#L28

Impact

users can deposit more than expected

Mitigation

 #[account]
 #[derive(InitSpace)]
@@ -25,7 +27,19 @@ impl RateLimiter {

     pub fn set_capacity(&mut self, capacity: u64) -> Result<()> {
         self.capacity = capacity;
-        self.tokens = capacity;
+        if(self.capacity != 0){//its mean admin want to change old values
+            self.refill(0)?;
+            if(capacity > self.capacity){
+            
+                self.tokens = (capacity - self.capacity) + self.tokens
+            }
+  
+        }
+        else{
+            self.tokens = capacity;
+        }
         self.last_refill_time = Clock::get()?.unix_timestamp.try_into().unwrap();
         Ok(())
     }