diff --git a/eth2/state_processing/src/per_block_processing/errors.rs b/eth2/state_processing/src/per_block_processing/errors.rs index 3d308153e..1c5514516 100644 --- a/eth2/state_processing/src/per_block_processing/errors.rs +++ b/eth2/state_processing/src/per_block_processing/errors.rs @@ -398,7 +398,12 @@ pub enum TransferInvalid { /// min_deposit_amount` /// /// (resulting_amount, min_deposit_amount) - InvalidResultingFromBalance(u64, u64), + SenderDust(u64, u64), + /// This transfer would result in the `transfer.to` account to have `0 < balance < + /// min_deposit_amount` + /// + /// (resulting_amount, min_deposit_amount) + RecipientDust(u64, u64), /// The state slot does not match `transfer.slot`. /// /// (state_slot, transfer_slot) diff --git a/eth2/state_processing/src/per_block_processing/verify_transfer.rs b/eth2/state_processing/src/per_block_processing/verify_transfer.rs index 3c11290e0..15c142d90 100644 --- a/eth2/state_processing/src/per_block_processing/verify_transfer.rs +++ b/eth2/state_processing/src/per_block_processing/verify_transfer.rs @@ -44,12 +44,16 @@ fn verify_transfer_parametric( spec: &ChainSpec, time_independent_only: bool, ) -> Result<(), Error> { - // Load the sender balance from state. let sender_balance = *state .balances .get(transfer.sender as usize) .ok_or_else(|| Error::Invalid(Invalid::FromValidatorUnknown(transfer.sender)))?; + let recipient_balance = *state + .balances + .get(transfer.recipient as usize) + .ok_or_else(|| Error::Invalid(Invalid::FromValidatorUnknown(transfer.recipient)))?; + // Safely determine `amount + fee`. let total_amount = transfer .amount @@ -62,16 +66,19 @@ fn verify_transfer_parametric( Invalid::FromBalanceInsufficient(transfer.amount, sender_balance) ); - // Verify balances are not "dust" (i.e., greater than zero but less than the minimum deposit + // Verify sender balance will not be "dust" (i.e., greater than zero but less than the minimum deposit // amount). verify!( time_independent_only || (sender_balance == total_amount) || (sender_balance >= (total_amount + spec.min_deposit_amount)), - Invalid::InvalidResultingFromBalance( - sender_balance - total_amount, - spec.min_deposit_amount - ) + Invalid::SenderDust(sender_balance - total_amount, spec.min_deposit_amount) + ); + + // Verify the recipient balance will not be dust. + verify!( + time_independent_only || ((recipient_balance + transfer.amount) >= spec.min_deposit_amount), + Invalid::RecipientDust(sender_balance - total_amount, spec.min_deposit_amount) ); // If loosely enforcing `transfer.slot`, ensure the slot is not in the past. Otherwise, ensure