diff --git a/pallets/claims/src/lib.rs b/pallets/claims/src/lib.rs index 99a357a44..f38695d83 100644 --- a/pallets/claims/src/lib.rs +++ b/pallets/claims/src/lib.rs @@ -42,6 +42,7 @@ pub use pallet::*; use pallet_evm::AddressMapping; use parity_scale_codec::{Decode, Encode}; use scale_info::TypeInfo; +use schnorrkel::{signing_context, PublicKey, Signature}; use serde::{self, Deserialize, Serialize}; use sp_core::H160; use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256}; @@ -558,8 +559,16 @@ impl Pallet { extra: &[u8], ) -> Option { let msg = keccak_256(&Self::polkadotjs_signable_message(what, extra)); - let res = AccountId32::new([0; 32]); - Some(MultiAddress::Native(res)) + let pk: PublicKey = match addr.clone() { + MultiAddress::EVM(_) => return None, + MultiAddress::Native(a) => PublicKey::from_bytes(&a.encode()).ok()?, + }; + let signature: Signature = Signature::from_bytes(&s.0.encode()).ok()?; + const SIGNING_CTX: &'static [u8] = b"substrate"; + match pk.verify_simple(SIGNING_CTX, &msg, &signature) { + Ok(_) => Some(addr), + Err(_) => None, + } } fn process_claim( @@ -616,7 +625,7 @@ impl Pallet { Self::eth_recover(ðereum_signature, &data, &statement[..]) .ok_or(Error::::InvalidEthereumSignature)?, MultiAddressSignature::Native(sr25519_signature) => { - ensure!(signer.is_none(), Error::::InvalidNativeAccount); + ensure!(!signer.is_none(), Error::::InvalidNativeAccount); Self::sr25519_recover(signer.unwrap(), &sr25519_signature, &data, &statement[..]) .ok_or(Error::::InvalidNativeSignature)? }, diff --git a/pallets/claims/src/tests.rs b/pallets/claims/src/tests.rs index 7440bda3c..af06ec025 100644 --- a/pallets/claims/src/tests.rs +++ b/pallets/claims/src/tests.rs @@ -734,3 +734,54 @@ fn test_unclaimed_returned_to_destination() { ); }); } + +#[test] +fn test_claim_from_substrate_address_to_evm() { + new_test_ext().execute_with(|| { + let original_total_claims = Total::::get(); + let claim_of_sub_alice = 500; + assert_ok!(ClaimsPallet::claim( + RuntimeOrigin::none(), + Some(get_multi_address_account_id(42)), + Some(sr25519_utils::sub(&alice_sr25519())), + sr25519_utils::sig::( + &alice_sr25519(), + &Some(get_multi_address_account_id(42)).encode(), + &[][..] + ) + )); + assert_eq!(Total::::get(), original_total_claims - claim_of_sub_alice); + + // force set the expiry config + assert_ok!(ClaimsPallet::force_set_expiry_config( + RuntimeOrigin::root(), + 5, + get_multi_address_account_id(100) + )); + + // run to after expiry block + run_to_block(7); + assert_eq!(Total::::get(), 0); + // the dest account should receive the remaining pot balance + assert_eq!( + Balances::free_balance(get_multi_address_account_id(100).to_account_id_32()), + original_total_claims - claim_of_sub_alice + ); + + // all further claims should fail with PotUnderflow error since the funds have been + // emptied + assert_noop!( + ClaimsPallet::claim( + RuntimeOrigin::none(), + Some(get_multi_address_account_id(42)), + None, + sr25519_utils::sig::( + &bob_sr25519(), + &Some(get_multi_address_account_id(42)).encode(), + &[][..] + ) + ), + Error::::PotUnderflow + ); + }); +} diff --git a/pallets/claims/src/utils/ethereum_address.rs b/pallets/claims/src/utils/ethereum_address.rs index 60f814b35..c8e8dfc6c 100644 --- a/pallets/claims/src/utils/ethereum_address.rs +++ b/pallets/claims/src/utils/ethereum_address.rs @@ -1,5 +1,7 @@ use super::*; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; + /// An Ethereum address (i.e. 20 bytes, used to represent an Ethereum account). /// /// This gets serialized to the 0x-prefixed hex representation.