310 lines
13 KiB
Rust
310 lines
13 KiB
Rust
#![cfg(test)]
|
|
|
|
use mock::*;
|
|
use super::*;
|
|
use hex_literal::hex;
|
|
|
|
use sp_runtime::AccountId32;
|
|
use frame_support::traits::Get;
|
|
use frame_support::assert_ok;
|
|
use libsecp256k1::{Message, SecretKey, PublicKey};
|
|
|
|
use ghost_helpers::merkle_tree::{generate_tree, generate_proof};
|
|
|
|
#[derive(Clone)]
|
|
pub struct NewTestUser {
|
|
pub substrate_account: AccountId32,
|
|
pub evm_secret: SecretKey,
|
|
pub evm_address: EvmAddress,
|
|
pub allowed_shares: u128,
|
|
pub token_id: u128,
|
|
}
|
|
|
|
#[test]
|
|
fn claim_happy_path() {
|
|
new_test_ext().execute_with(|| {
|
|
let network_id = 69u64;
|
|
|
|
let minimum_donation_u128 = <<Test as crate::Config>::MinimumDonation as Get<u128>>::get();
|
|
let minimum_donation: BalanceOf<Test> = minimum_donation_u128.unique_saturated_into();
|
|
|
|
let secret_key_1 = SecretKey::parse(&[1u8; 32]).unwrap();
|
|
let public_key_1 = PublicKey::from_secret_key(&secret_key_1);
|
|
let pubkey_raw_1 = &public_key_1.serialize()[1..65];
|
|
let pubkey_hash_1 = SubstrateKeccakHasher::hash(pubkey_raw_1);
|
|
|
|
let mut evm_addr_bytes_1 = [0u8; 20];
|
|
evm_addr_bytes_1.copy_from_slice(&pubkey_hash_1.as_ref()[12..32]);
|
|
|
|
let user_1 = NewTestUser {
|
|
substrate_account: AccountId32::new([11u8; 32]),
|
|
evm_secret: secret_key_1,
|
|
evm_address: EvmAddress::from(evm_addr_bytes_1),
|
|
allowed_shares: 420u128,
|
|
token_id: 0,
|
|
};
|
|
|
|
let secret_key_2 = SecretKey::parse(&[2u8; 32]).unwrap();
|
|
let public_key_2 = PublicKey::from_secret_key(&secret_key_2);
|
|
let pubkey_raw_2 = &public_key_2.serialize()[1..65];
|
|
let pubkey_hash_2 = SubstrateKeccakHasher::hash(pubkey_raw_2);
|
|
|
|
let mut evm_addr_bytes_2 = [0u8; 20];
|
|
evm_addr_bytes_2.copy_from_slice(&pubkey_hash_2.as_ref()[12..32]);
|
|
|
|
let user_2 = NewTestUser {
|
|
substrate_account: AccountId32::new([22u8; 32]),
|
|
evm_secret: secret_key_2,
|
|
evm_address: EvmAddress::from(evm_addr_bytes_2),
|
|
allowed_shares: 1337u128,
|
|
token_id: 1,
|
|
};
|
|
|
|
let secret_key_3 = SecretKey::parse(&[3u8; 32]).unwrap();
|
|
let public_key_3 = PublicKey::from_secret_key(&secret_key_3);
|
|
let pubkey_raw_3 = &public_key_3.serialize()[1..65];
|
|
let pubkey_hash_3 = SubstrateKeccakHasher::hash(pubkey_raw_3);
|
|
|
|
let mut evm_addr_bytes_3 = [0u8; 20];
|
|
evm_addr_bytes_3.copy_from_slice(&pubkey_hash_3.as_ref()[12..32]);
|
|
|
|
let user_3 = NewTestUser {
|
|
substrate_account: AccountId32::new([69u8; 32]),
|
|
evm_secret: secret_key_3,
|
|
evm_address: EvmAddress::from(evm_addr_bytes_3),
|
|
allowed_shares: 69u128,
|
|
token_id: 2,
|
|
};
|
|
|
|
let users = vec![user_1.clone(), user_2.clone(), user_3.clone()];
|
|
let max_index = 2u8;
|
|
|
|
let raw_values_complex = vec![(0u8, &user_1), (1u8, &user_2), (2u8, &user_3)];
|
|
let merkle_tree = generate_tree::<SubstrateKeccakHasher, u8, _, _, _>(
|
|
max_index,
|
|
raw_values_complex,
|
|
|
|
|item: (u8, &NewTestUser)| -> Result<(usize, Vec<u8>), ()> {
|
|
let (index, u) = item;
|
|
|
|
let tmp_package = ClaimPackage {
|
|
shares: u.allowed_shares,
|
|
merkle_proof: Default::default(),
|
|
token_id: u.token_id,
|
|
index: index as u32
|
|
};
|
|
|
|
Ok((index as usize, tmp_package.get_preimage(&u.evm_address, network_id).to_vec()))
|
|
}
|
|
).unwrap();
|
|
|
|
let merkle_root = *merkle_tree.last().unwrap();
|
|
|
|
let network_state = NetworkShare::new(1_000_000, merkle_root, 2);
|
|
let global_state = ShareState::new(1_000_000);
|
|
NetworkShares::<Test>::insert(&network_id, network_state);
|
|
GlobalShares::<Test>::put(global_state);
|
|
|
|
let mut global_activated = GlobalShares::<Test>::get().claimed_shares;
|
|
let mut network_activated = NetworkShares::<Test>::get(&network_id)
|
|
.claimed_shares();
|
|
|
|
for (slot_index, current_user) in users.iter().enumerate() {
|
|
MemberShares::<Test>::insert(¤t_user.substrate_account, MemberShare {
|
|
locked_balance: minimum_donation,
|
|
initiated_network: None,
|
|
activated_shares: 0,
|
|
});
|
|
|
|
let proof = generate_proof::<SubstrateKeccakHasher, u8>(&merkle_tree, max_index, slot_index as u8);
|
|
|
|
let claim_package = ClaimPackage {
|
|
shares: current_user.allowed_shares,
|
|
merkle_proof: BoundedVec::try_from(proof).unwrap(),
|
|
token_id: current_user.token_id,
|
|
index: slot_index as u32,
|
|
};
|
|
|
|
let preimage = claim_package.get_preimage(¤t_user.evm_address, network_id);
|
|
let preimage_hash = SubstrateKeccakHasher::hash(&preimage);
|
|
|
|
let message_string_bytes = Governance::ethereum_signable_message(
|
|
¤t_user.substrate_account,
|
|
&network_id,
|
|
&preimage_hash
|
|
);
|
|
|
|
let message_hash = SubstrateKeccakHasher::hash(&message_string_bytes);
|
|
let mut message_bytes = [0u8; 32];
|
|
message_bytes.copy_from_slice(message_hash.as_ref());
|
|
|
|
let msg_to_sign = Message::parse(&message_bytes);
|
|
|
|
let (sig, recovery_id) = libsecp256k1::sign(&msg_to_sign, ¤t_user.evm_secret);
|
|
|
|
let mut signature_raw = [0u8; 65];
|
|
signature_raw[0..32].copy_from_slice(&sig.r.b32());
|
|
signature_raw[32..64].copy_from_slice(&sig.s.b32());
|
|
signature_raw[64] = recovery_id.serialize();
|
|
|
|
let evm_signature = EvmSignature::from(signature_raw);
|
|
|
|
assert_ok!(Governance::claim(
|
|
RuntimeOrigin::signed(current_user.substrate_account.clone()),
|
|
network_id,
|
|
claim_package,
|
|
current_user.evm_address.clone(),
|
|
evm_signature
|
|
));
|
|
|
|
let updated_share = MemberShares::<Test>::get(¤t_user.substrate_account);
|
|
assert_eq!(updated_share.activated_shares, current_user.allowed_shares);
|
|
|
|
global_activated += current_user.allowed_shares;
|
|
network_activated += current_user.allowed_shares;
|
|
}
|
|
|
|
assert_eq!(global_activated, GlobalShares::<Test>::get().claimed_shares);
|
|
assert_eq!(
|
|
network_activated,
|
|
NetworkShares::<Test>::get(&network_id).claimed_shares(),
|
|
);
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn verify_proof_from_python_preclaims_for_sepolia() {
|
|
new_test_ext().execute_with(|| {
|
|
// ===========================================================================================================
|
|
// === FINAL MERKLE ROOT FOR [SEPOLIA]: c41c281c8404f5ce0adfca067ef8ed260f28c2cb1d7944c84ce2431936b1919e ===
|
|
// ===========================================================================================================
|
|
// [+] Total padded leaves: 128
|
|
// [+] Merkle tree size: 255
|
|
// [+] Network ID: 11155111
|
|
// [+] Proof size: 7
|
|
// [+] Total shares: 1398900000000000000000
|
|
|
|
let network_id = 11155111u64;
|
|
let merkle_root = EvmHash::from(hex!("c41c281c8404f5ce0adfca067ef8ed260f28c2cb1d7944c84ce2431936b1919e"));
|
|
let proof_size = 7;
|
|
let total_shares = 1398900000000000000000;
|
|
|
|
let network_state = NetworkShare::new(total_shares, merkle_root, proof_size);
|
|
let global_state = ShareState::new(total_shares);
|
|
NetworkShares::<Test>::insert(&network_id, network_state);
|
|
GlobalShares::<Test>::put(global_state);
|
|
|
|
let evm_holder_1 = EvmAddress::from(hex!("D500EFDef75E89Bf6caF5C98F7633575d0049a72"));
|
|
let claim_package_1 = ClaimPackage {
|
|
index: 0,
|
|
token_id: 1,
|
|
shares: 684900000000000000000,
|
|
merkle_proof: BoundedVec::try_from(
|
|
vec![
|
|
EvmHash::from(hex!("86d599b297ed8fb56476884b43502e15e7b207835f9a62bd07b4f3338ac63b44")),
|
|
EvmHash::from(hex!("85ec1f887b1a32e76cd1b70de6a5b1900045efd7dfe3b218d3b6cef672735da6")),
|
|
EvmHash::from(hex!("1e8a291eb2ba08696ca482c7869cab5ad360da4e4df55589adf40b08b020cc5b")),
|
|
EvmHash::from(hex!("a090ff633d4831ca76640ffce9d9399a0f8409bbbc98814d0d885c538c9ebc08")),
|
|
EvmHash::from(hex!("85ad79082ed24d2fc6748f131ed39280d402cb7a0844b42b9d768d4639b516a9")),
|
|
EvmHash::from(hex!("2c55408bc86c5a292611bc01ba46ac6c6b37b8409097b752bad884be24249ec4")),
|
|
EvmHash::from(hex!("9e046ea7683ac6dfa95caf833912d806b41296fcaa86718b4822f42ae68a6ff5"))
|
|
]
|
|
).unwrap(),
|
|
};
|
|
|
|
let preimage_1 = claim_package_1.get_preimage(&evm_holder_1, network_id);
|
|
|
|
assert_ok!(
|
|
Governance::verify_merkle_proof(
|
|
&network_id,
|
|
&preimage_1,
|
|
&claim_package_1,
|
|
)
|
|
);
|
|
|
|
let evm_holder_2 = EvmAddress::from(hex!("Ee71538ae7677829676BD8dD18259Ed93E6B44e9"));
|
|
let claim_package_2 = ClaimPackage {
|
|
index: 2,
|
|
token_id: 3,
|
|
shares: 14900000000000000000,
|
|
merkle_proof: BoundedVec::try_from(
|
|
vec![
|
|
EvmHash::from(hex!("547eb6ce3345e183448c61ee30e4eca0523537114e8d3971894196598651040e")),
|
|
EvmHash::from(hex!("9e9936d6cd248898747a8d29d2ef1b02ca06c40583873fd7c3a7ddd1554f5472")),
|
|
EvmHash::from(hex!("1e8a291eb2ba08696ca482c7869cab5ad360da4e4df55589adf40b08b020cc5b")),
|
|
EvmHash::from(hex!("a090ff633d4831ca76640ffce9d9399a0f8409bbbc98814d0d885c538c9ebc08")),
|
|
EvmHash::from(hex!("85ad79082ed24d2fc6748f131ed39280d402cb7a0844b42b9d768d4639b516a9")),
|
|
EvmHash::from(hex!("2c55408bc86c5a292611bc01ba46ac6c6b37b8409097b752bad884be24249ec4")),
|
|
EvmHash::from(hex!("9e046ea7683ac6dfa95caf833912d806b41296fcaa86718b4822f42ae68a6ff5"))
|
|
]
|
|
).unwrap(),
|
|
};
|
|
|
|
let preimage_2 = claim_package_2.get_preimage(&evm_holder_2, network_id);
|
|
|
|
assert_ok!(
|
|
Governance::verify_merkle_proof(
|
|
&network_id,
|
|
&preimage_2,
|
|
&claim_package_2,
|
|
)
|
|
);
|
|
|
|
let evm_holder_3 = EvmAddress::from(hex!("29c6D9e3c3981e4FcF2AC6B486e4E4210daeA1Ee"));
|
|
let claim_package_3 = ClaimPackage {
|
|
index: 6,
|
|
token_id: 7,
|
|
shares: 10900000000000000000,
|
|
merkle_proof: BoundedVec::try_from(
|
|
vec![
|
|
EvmHash::from(hex!("441f13d353fe0224fe4ab418fe56c66287e0ba1e5e562f56a4b7195ca3d9f741")),
|
|
EvmHash::from(hex!("17f9ae41fbcbbfc35accf1e4e132a905b0a95e68e085757ae8304b6a0554e908")),
|
|
EvmHash::from(hex!("a6f6783441ed0d4c5f1da8d1f026c037e15706c4ecb4c400216d485105ec9596")),
|
|
EvmHash::from(hex!("a090ff633d4831ca76640ffce9d9399a0f8409bbbc98814d0d885c538c9ebc08")),
|
|
EvmHash::from(hex!("85ad79082ed24d2fc6748f131ed39280d402cb7a0844b42b9d768d4639b516a9")),
|
|
EvmHash::from(hex!("2c55408bc86c5a292611bc01ba46ac6c6b37b8409097b752bad884be24249ec4")),
|
|
EvmHash::from(hex!("9e046ea7683ac6dfa95caf833912d806b41296fcaa86718b4822f42ae68a6ff5"))
|
|
]
|
|
).unwrap(),
|
|
};
|
|
|
|
let preimage_3 = claim_package_3.get_preimage(&evm_holder_3, network_id);
|
|
|
|
assert_ok!(
|
|
Governance::verify_merkle_proof(
|
|
&network_id,
|
|
&preimage_3,
|
|
&claim_package_3,
|
|
)
|
|
);
|
|
|
|
let evm_holder_4 = EvmAddress::from(hex!("Fe962E8BB2a6877d14b53E0a07932C040eC885ea"));
|
|
let claim_package_4 = ClaimPackage {
|
|
index: 35,
|
|
token_id: 36,
|
|
shares: 10900000000000000000,
|
|
merkle_proof: BoundedVec::try_from(
|
|
vec![
|
|
EvmHash::from(hex!("5ddb291d62d02afab17cee218f2f367d612736b0f1ae59d2d28aac811e2057f3")),
|
|
EvmHash::from(hex!("d990cb37076db084b1621bc8327e0f740e242da4c463ea3a0457a6483c07fdbf")),
|
|
EvmHash::from(hex!("7bf41c14904c75e189893d05cf99c55516a194882463980cf08468c3bfd7dd8a")),
|
|
EvmHash::from(hex!("1c4c8136fe9e6dc08dc1c69f2da707a271ae510cdb5af6051b5222f2812edee0")),
|
|
EvmHash::from(hex!("3ec8d2443fd6f9decef06bf930e37cd37d78bf1c6004dc84b9ca1199712a82f8")),
|
|
EvmHash::from(hex!("1951c00e48f734ba95daeb3e8f6a2d971cc6fb0afac471ae39a21013f5756794")),
|
|
EvmHash::from(hex!("9e046ea7683ac6dfa95caf833912d806b41296fcaa86718b4822f42ae68a6ff5"))
|
|
]
|
|
).unwrap(),
|
|
};
|
|
|
|
let preimage_4 = claim_package_4.get_preimage(&evm_holder_4, network_id);
|
|
|
|
assert_ok!(
|
|
Governance::verify_merkle_proof(
|
|
&network_id,
|
|
&preimage_4,
|
|
&claim_package_4,
|
|
)
|
|
);
|
|
})
|
|
}
|