Fix possible subtract with overflow if mining pool is not setup (#4836)
automerge
This commit is contained in:
		@@ -374,18 +374,10 @@ impl<'a> StorageAccount<'a> {
 | 
				
			|||||||
                    StorageError::InvalidOwner as u32,
 | 
					                    StorageError::InvalidOwner as u32,
 | 
				
			||||||
                ))?
 | 
					                ))?
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            redeem(*pending_lamports, rewards_pool, owner)?;
 | 
				
			||||||
            let pending = *pending_lamports;
 | 
					 | 
				
			||||||
            if rewards_pool.account.lamports < pending {
 | 
					 | 
				
			||||||
                println!("reward pool has {}", rewards_pool.account.lamports);
 | 
					 | 
				
			||||||
                Err(InstructionError::CustomError(
 | 
					 | 
				
			||||||
                    StorageError::RewardPoolDepleted as u32,
 | 
					 | 
				
			||||||
                ))?
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            rewards_pool.account.lamports -= pending;
 | 
					 | 
				
			||||||
            owner.account.lamports += pending;
 | 
					 | 
				
			||||||
            //clear pending_lamports
 | 
					            //clear pending_lamports
 | 
				
			||||||
            *pending_lamports = 0;
 | 
					            *pending_lamports = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.account.set_state(storage_contract)
 | 
					            self.account.set_state(storage_contract)
 | 
				
			||||||
        } else if let StorageContract::ReplicatorStorage {
 | 
					        } else if let StorageContract::ReplicatorStorage {
 | 
				
			||||||
            owner: account_owner,
 | 
					            owner: account_owner,
 | 
				
			||||||
@@ -409,11 +401,10 @@ impl<'a> StorageAccount<'a> {
 | 
				
			|||||||
                })
 | 
					                })
 | 
				
			||||||
                .collect::<Vec<_>>();
 | 
					                .collect::<Vec<_>>();
 | 
				
			||||||
            reward_validations.clear();
 | 
					            reward_validations.clear();
 | 
				
			||||||
            let total_proofs = checked_proofs.len() as u64;
 | 
					 | 
				
			||||||
            let num_validations = count_valid_proofs(&checked_proofs);
 | 
					            let num_validations = count_valid_proofs(&checked_proofs);
 | 
				
			||||||
            let reward = num_validations * REPLICATOR_REWARD * (num_validations / total_proofs);
 | 
					            let reward = num_validations * REPLICATOR_REWARD;
 | 
				
			||||||
            rewards_pool.account.lamports -= reward;
 | 
					            redeem(reward, rewards_pool, owner)?;
 | 
				
			||||||
            owner.account.lamports += reward;
 | 
					
 | 
				
			||||||
            self.account.set_state(storage_contract)
 | 
					            self.account.set_state(storage_contract)
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Err(InstructionError::InvalidArgument)?
 | 
					            Err(InstructionError::InvalidArgument)?
 | 
				
			||||||
@@ -421,6 +412,21 @@ impl<'a> StorageAccount<'a> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn redeem(
 | 
				
			||||||
 | 
					    rewards: u64,
 | 
				
			||||||
 | 
					    rewards_pool: &mut KeyedAccount,
 | 
				
			||||||
 | 
					    owner: &mut StorageAccount,
 | 
				
			||||||
 | 
					) -> Result<(), InstructionError> {
 | 
				
			||||||
 | 
					    if rewards_pool.account.lamports < rewards {
 | 
				
			||||||
 | 
					        Err(InstructionError::CustomError(
 | 
				
			||||||
 | 
					            StorageError::RewardPoolDepleted as u32,
 | 
				
			||||||
 | 
					        ))?
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    rewards_pool.account.lamports -= rewards;
 | 
				
			||||||
 | 
					    owner.account.lamports += rewards;
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn create_rewards_pool() -> Account {
 | 
					pub fn create_rewards_pool() -> Account {
 | 
				
			||||||
    Account::new_data(std::u64::MAX, &StorageContract::RewardsPool, &crate::id()).unwrap()
 | 
					    Account::new_data(std::u64::MAX, &StorageContract::RewardsPool, &crate::id()).unwrap()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -470,7 +476,7 @@ fn count_valid_proofs(proofs: &[ProofStatus]) -> u64 {
 | 
				
			|||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
    use super::*;
 | 
					    use super::*;
 | 
				
			||||||
    use crate::id;
 | 
					    use crate::{id, rewards_pools};
 | 
				
			||||||
    use std::collections::BTreeMap;
 | 
					    use std::collections::BTreeMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
@@ -570,4 +576,35 @@ mod tests {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        .unwrap();
 | 
					        .unwrap();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_redeem() {
 | 
				
			||||||
 | 
					        let reward = 100;
 | 
				
			||||||
 | 
					        let mut owner_account = Account {
 | 
				
			||||||
 | 
					            lamports: 1,
 | 
				
			||||||
 | 
					            ..Account::default()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        let mut rewards_pool = create_rewards_pool();
 | 
				
			||||||
 | 
					        let pool_id = rewards_pools::id();
 | 
				
			||||||
 | 
					        let mut keyed_pool_account = KeyedAccount::new(&pool_id, false, &mut rewards_pool);
 | 
				
			||||||
 | 
					        let mut owner = StorageAccount {
 | 
				
			||||||
 | 
					            id: Pubkey::default(),
 | 
				
			||||||
 | 
					            account: &mut owner_account,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // check that redeeming from depleted pools fails
 | 
				
			||||||
 | 
					        keyed_pool_account.account.lamports = 0;
 | 
				
			||||||
 | 
					        assert_eq!(
 | 
				
			||||||
 | 
					            redeem(reward, &mut keyed_pool_account, &mut owner),
 | 
				
			||||||
 | 
					            Err(InstructionError::CustomError(
 | 
				
			||||||
 | 
					                StorageError::RewardPoolDepleted as u32,
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        assert_eq!(owner.account.lamports, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        keyed_pool_account.account.lamports = 200;
 | 
				
			||||||
 | 
					        assert_eq!(redeem(reward, &mut keyed_pool_account, &mut owner), Ok(()));
 | 
				
			||||||
 | 
					        // check that the owner's balance increases
 | 
				
			||||||
 | 
					        assert_eq!(owner.account.lamports, 101);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user