From 602b220aa599c074bce015f756ab63800c3c5d94 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sat, 27 Apr 2024 00:38:08 +0530 Subject: [PATCH 01/12] chore: add more tests --- primitives/orderbook/src/types.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index e36e3a11f..10e104b59 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -1031,7 +1031,7 @@ pub struct ApprovedSnapshot { mod tests { use crate::ingress::{EgressMessages, IngressMessages}; use crate::traits::VerifyExtensionSignature; - use crate::types::UserActions; + use crate::types::{Order, OrderDetails, OrderPayload, UserActions}; use polkadex_primitives::{AccountId, AssetId}; use rust_decimal::Decimal; use sp_runtime::MultiSignature; @@ -1068,4 +1068,19 @@ mod tests { let result = sig.verify_extension_signature(&payload, &account); assert_eq!(result, true); } + + #[test] + pub fn verify_order_signed_by_extension() { + let order_payload_str = "{\"client_order_id\":\"0x7765626170702d000079a87e313975c2490257e1ea808147fd0d7a096930b4c3\",\"user\":\"5Cct7e6gLzXHN35Zc9QYqA1DXPeJFhqt3RiZGzCMzo16JwjC\",\"main_account\":\"5FYr5g1maSsAAw6w98xdAytZ6MEQ8sNPgp3PNLgy9o79kMug\",\"pair\":\"PDEX-3496813586714279103986568049643838918\",\"side\":\"Ask\",\"order_type\":\"LIMIT\",\"quote_order_quantity\":\"0\",\"qty\":\"1\",\"price\":\"1\",\"timestamp\":1714158182636}"; + let signature_payload_str = "{\"Sr25519\":\"32ce7e9d9ca9eb84447a079e5309e313a3a6767211c5b5957d6512825f0d2f00dcccc1ca57cc514e9a82d605431e989b03bbceca29a421e515023f138ea6ff84\"}"; + let payload = serde_json::from_str::(order_payload_str).unwrap(); + let signature = serde_json::from_str::(signature_payload_str).unwrap(); + // Convert to Order type for primitives + let order_details = OrderDetails { payload: payload.clone(), signature: signature.clone() }; + let order: Order = Order::try_from(order_details).unwrap(); + let json_str = serde_json::to_string(&OrderPayload::from(order.clone())).unwrap(); + assert_eq!(json_str, order_payload_str); + let result = signature.verify_extension_signature(&json_str, &payload.main_account); + assert_eq!(order.verify_signature(), true); + } } From 99cf4cc20d97da761fa6f38400edfe86669260f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sat, 27 Apr 2024 01:19:11 +0530 Subject: [PATCH 02/12] chore: add more tests --- primitives/orderbook/src/types.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index 10e104b59..59398b566 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -1078,9 +1078,6 @@ mod tests { // Convert to Order type for primitives let order_details = OrderDetails { payload: payload.clone(), signature: signature.clone() }; let order: Order = Order::try_from(order_details).unwrap(); - let json_str = serde_json::to_string(&OrderPayload::from(order.clone())).unwrap(); - assert_eq!(json_str, order_payload_str); - let result = signature.verify_extension_signature(&json_str, &payload.main_account); assert_eq!(order.verify_signature(), true); } } From 3794939b8b873f24940390710ee3cf8a42faba7d Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sat, 27 Apr 2024 20:19:32 +0530 Subject: [PATCH 03/12] chore: add more tests --- primitives/orderbook/src/types.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index 59398b566..c22f17ac4 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -1031,7 +1031,10 @@ pub struct ApprovedSnapshot { mod tests { use crate::ingress::{EgressMessages, IngressMessages}; use crate::traits::VerifyExtensionSignature; - use crate::types::{Order, OrderDetails, OrderPayload, UserActions}; + use crate::types::{ + Order, OrderDetails, OrderPayload, UserActions, WithdrawPayloadCallByUser, + WithdrawalDetails, + }; use polkadex_primitives::{AccountId, AssetId}; use rust_decimal::Decimal; use sp_runtime::MultiSignature; @@ -1080,4 +1083,23 @@ mod tests { let order: Order = Order::try_from(order_details).unwrap(); assert_eq!(order.verify_signature(), true); } + + #[test] + pub fn verify_withdrawal_signed_by_extension() { + let withdraw_payload_str = + "{\"asset_id\":{\"asset\":\"PDEX\"},\"amount\":\"1.11111111\",\"timestamp\":1714229288928}"; + let signature_payload_str = + "{\"Sr25519\":\"785ae7c0ece6fb07429689f0b7d30f11e8f612507fbbc4edb3cbc668f7b4d3060a460b32ae2d4fed52b97faf21d9de768881d25711c9141fde40af4d58e57886\"}"; + let payload = + serde_json::from_str::(withdraw_payload_str).unwrap(); + let signature = serde_json::from_str::(signature_payload_str).unwrap(); + const MAIN_ACCOUNT: &str = "5FYr5g1maSsAAw6w98xdAytZ6MEQ8sNPgp3PNLgy9o79kMug"; + let details = WithdrawalDetails { + payload: payload.clone(), + main: AccountId::from_str(MAIN_ACCOUNT).unwrap(), + proxy: AccountId::from_str(MAIN_ACCOUNT).unwrap(), + signature: signature.clone(), + }; + assert_eq!(details.verify_signature(), true); + } } From 238e02b9bcd77b70ccf0cfd56b61e79be97d8cc2 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sat, 27 Apr 2024 20:44:41 +0530 Subject: [PATCH 04/12] feat: add verify for withdraw request --- primitives/orderbook/src/types.rs | 52 +++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index c22f17ac4..bb771aa9f 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -295,11 +295,32 @@ impl WithdrawalRequest { impl WithdrawalRequest { /// Verifies request payload. pub fn verify(&self) -> bool { - let signer = match Decode::decode(&mut &self.proxy.encode()[..]) { - Ok(signer) => signer, - Err(_) => return false, - }; - self.signature.verify(self.payload.encode().as_ref(), &signer) + // check signature with proxy account + let signer = Decode::decode(&mut &self.proxy.encode()[..]); + let mut result = false; + if let Ok(signer) = signer { + result = self.signature.verify(self.payload.encode().as_ref(), &signer); + } + if result { + return true; + } + log::error!(target:"orderbook","Withdrawal request signature check failed"); + + // check signature with main account + let signer = Decode::decode(&mut &self.main.encode()[..]); + match signer { + Ok(main) => { + let payload_str = serde_json::to_string(&self.payload); + if let Ok(payload_str) = payload_str { + return self.signature.verify_extension_signature(&payload_str, &main); + } + false + }, + Err(err) => { + log::error!(target:"orderbook","Withdrawal request signature check failed {:}", err); + return false; + }, + } } /// Instantiates `AccountAsset` DTO based on owning data. @@ -1033,7 +1054,7 @@ mod tests { use crate::traits::VerifyExtensionSignature; use crate::types::{ Order, OrderDetails, OrderPayload, UserActions, WithdrawPayloadCallByUser, - WithdrawalDetails, + WithdrawalDetails, WithdrawalRequest, }; use polkadex_primitives::{AccountId, AssetId}; use rust_decimal::Decimal; @@ -1102,4 +1123,23 @@ mod tests { }; assert_eq!(details.verify_signature(), true); } + + #[test] + pub fn verify_withdrawal_request_signed_by_extension() { + let withdraw_payload_str = + "{\"asset_id\":{\"asset\":\"PDEX\"},\"amount\":\"1.11111111\",\"timestamp\":1714229288928}"; + let signature_payload_str = + "{\"Sr25519\":\"785ae7c0ece6fb07429689f0b7d30f11e8f612507fbbc4edb3cbc668f7b4d3060a460b32ae2d4fed52b97faf21d9de768881d25711c9141fde40af4d58e57886\"}"; + let payload = + serde_json::from_str::(withdraw_payload_str).unwrap(); + let signature = serde_json::from_str::(signature_payload_str).unwrap(); + const MAIN_ACCOUNT: &str = "5FYr5g1maSsAAw6w98xdAytZ6MEQ8sNPgp3PNLgy9o79kMug"; + let request = WithdrawalRequest { + payload: payload.clone(), + main: AccountId::from_str(MAIN_ACCOUNT).unwrap(), + proxy: AccountId::from_str(MAIN_ACCOUNT).unwrap(), + signature: signature.clone(), + }; + assert_eq!(request.verify(), true); + } } From b0e7bab0f38108348995b4d6c96e13cc6003ed0d Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sat, 27 Apr 2024 20:50:49 +0530 Subject: [PATCH 05/12] chore: remove withdraw details struct --- primitives/orderbook/src/types.rs | 54 +------------------------------ 1 file changed, 1 insertion(+), 53 deletions(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index bb771aa9f..8d1fbd827 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -1003,39 +1003,6 @@ impl TryFrom for Order { } } -/// Defines withdraw details DTO. -#[derive(Clone, Debug, Encode, Decode, Eq, PartialEq, Serialize, Deserialize)] -pub struct WithdrawalDetails { - /// Withdraw payload. - pub payload: WithdrawPayloadCallByUser, - /// Main account identifier. - pub main: AccountId, - /// Proxy account identifier. - pub proxy: AccountId, - /// Signature. - pub signature: Signature, -} - -impl WithdrawalDetails { - /// Verifies the signature. - pub fn verify_signature(&self) -> bool { - let result = self.signature.verify(self.payload.encode().as_ref(), &self.proxy); - if result { - return true; - } - log::error!(target:"orderbook","Withdrawal signature check failed"); - let payload_str = serde_json::to_string(&self.payload); - if let Ok(payload_str) = payload_str { - let result = self.signature.verify_extension_signature(&payload_str, &self.main); - if result { - return true; - } - } - log::error!(target:"orderbook","Withdrawal extension signature check failed"); - false - } -} - /// Overarching type used by validators when submitting /// their signature for a summary to aggregator #[derive(serde::Serialize, serde::Deserialize, Debug, Clone)] @@ -1054,7 +1021,7 @@ mod tests { use crate::traits::VerifyExtensionSignature; use crate::types::{ Order, OrderDetails, OrderPayload, UserActions, WithdrawPayloadCallByUser, - WithdrawalDetails, WithdrawalRequest, + WithdrawalRequest, }; use polkadex_primitives::{AccountId, AssetId}; use rust_decimal::Decimal; @@ -1105,25 +1072,6 @@ mod tests { assert_eq!(order.verify_signature(), true); } - #[test] - pub fn verify_withdrawal_signed_by_extension() { - let withdraw_payload_str = - "{\"asset_id\":{\"asset\":\"PDEX\"},\"amount\":\"1.11111111\",\"timestamp\":1714229288928}"; - let signature_payload_str = - "{\"Sr25519\":\"785ae7c0ece6fb07429689f0b7d30f11e8f612507fbbc4edb3cbc668f7b4d3060a460b32ae2d4fed52b97faf21d9de768881d25711c9141fde40af4d58e57886\"}"; - let payload = - serde_json::from_str::(withdraw_payload_str).unwrap(); - let signature = serde_json::from_str::(signature_payload_str).unwrap(); - const MAIN_ACCOUNT: &str = "5FYr5g1maSsAAw6w98xdAytZ6MEQ8sNPgp3PNLgy9o79kMug"; - let details = WithdrawalDetails { - payload: payload.clone(), - main: AccountId::from_str(MAIN_ACCOUNT).unwrap(), - proxy: AccountId::from_str(MAIN_ACCOUNT).unwrap(), - signature: signature.clone(), - }; - assert_eq!(details.verify_signature(), true); - } - #[test] pub fn verify_withdrawal_request_signed_by_extension() { let withdraw_payload_str = From 4f8064c78f10571de3090b2ef7839ef8ce9175e9 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sat, 27 Apr 2024 21:08:12 +0530 Subject: [PATCH 06/12] feat: register funding account on new user deposit --- pallets/ocex/src/lib.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pallets/ocex/src/lib.rs b/pallets/ocex/src/lib.rs index 069bfce18..370c85430 100644 --- a/pallets/ocex/src/lib.rs +++ b/pallets/ocex/src/lib.rs @@ -1706,12 +1706,16 @@ pub mod pallet { ) -> DispatchResult { ensure!(Self::orderbook_operational_state(), Error::::ExchangeNotOperational); ensure!(>::get().contains(&asset), Error::::TokenNotAllowlisted); - // Check if account is registered - ensure!(>::contains_key(&user), Error::::AccountNotRegistered); ensure!(amount.saturated_into::() <= DEPOSIT_MAX, Error::::AmountOverflow); let converted_amount = Decimal::from(amount.saturated_into::()) .checked_div(Decimal::from(UNIT_BALANCE)) .ok_or(Error::::FailedToConvertDecimaltoBalance)?; + + // if a new user is depositing, then register the user with main account as proxy + if !>::contains_key(&user){ + Self::register_user(user.clone(), user.clone())?; + } + Self::transfer_asset(&user, &Self::get_pallet_account(), amount, asset)?; // Get Storage Map Value if let Some(expected_total_amount) = From 6dac54374d566be29113e5db3d788c9c579495ac Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:28:03 +0530 Subject: [PATCH 07/12] chore: clippy --- primitives/orderbook/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index 8d1fbd827..d53c05121 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -318,7 +318,7 @@ impl WithdrawalRequest { }, Err(err) => { log::error!(target:"orderbook","Withdrawal request signature check failed {:}", err); - return false; + false; }, } } From 1d02fa24a414a6aaa85a37a87b91d56c0052ec96 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Sun, 28 Apr 2024 20:28:16 +0530 Subject: [PATCH 08/12] chore: build --- primitives/orderbook/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/orderbook/src/types.rs b/primitives/orderbook/src/types.rs index d53c05121..5be6d8557 100644 --- a/primitives/orderbook/src/types.rs +++ b/primitives/orderbook/src/types.rs @@ -318,7 +318,7 @@ impl WithdrawalRequest { }, Err(err) => { log::error!(target:"orderbook","Withdrawal request signature check failed {:}", err); - false; + false }, } } From 0f85977e02952603636f9dac2e37c93ecc0f45e0 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Mon, 29 Apr 2024 12:48:55 +0530 Subject: [PATCH 09/12] chore: fmt --- pallets/ocex/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pallets/ocex/src/lib.rs b/pallets/ocex/src/lib.rs index 370c85430..2fddfc541 100644 --- a/pallets/ocex/src/lib.rs +++ b/pallets/ocex/src/lib.rs @@ -1712,7 +1712,7 @@ pub mod pallet { .ok_or(Error::::FailedToConvertDecimaltoBalance)?; // if a new user is depositing, then register the user with main account as proxy - if !>::contains_key(&user){ + if !>::contains_key(&user) { Self::register_user(user.clone(), user.clone())?; } From d88e09adf4d4f852195cbee5c286f698f53433c9 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Mon, 29 Apr 2024 15:00:57 +0530 Subject: [PATCH 10/12] fix: tests --- pallets/ocex/src/tests.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/pallets/ocex/src/tests.rs b/pallets/ocex/src/tests.rs index c7bf3e04d..dd89e2d47 100644 --- a/pallets/ocex/src/tests.rs +++ b/pallets/ocex/src/tests.rs @@ -1509,15 +1509,13 @@ fn test_deposit_account_not_registered() { let account_id = create_account_id(); new_test_ext().execute_with(|| { assert_ok!(OCEX::set_exchange_state(RuntimeOrigin::root(), true)); - allowlist_token(AssetId::Asset(10)); - assert_noop!( - OCEX::deposit( - RuntimeOrigin::signed(account_id.clone().into()), - AssetId::Asset(10), - 100_u128.into() - ), - Error::::AccountNotRegistered - ); + mint_into_account(account_id.clone()); + assert_ok!(OCEX::allowlist_token(RuntimeOrigin::root(), AssetId::Polkadex)); + assert_ok!(OCEX::deposit( + RuntimeOrigin::signed(account_id.clone().into()), + AssetId::Polkadex, + 100_u128.into() + )); }); } From a0c5c2f9cac2d253e93b056f7e018ad35f9358b5 Mon Sep 17 00:00:00 2001 From: Gautham Date: Mon, 29 Apr 2024 13:21:09 +0300 Subject: [PATCH 11/12] update deposit test --- pallets/ocex/src/tests.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pallets/ocex/src/tests.rs b/pallets/ocex/src/tests.rs index c7bf3e04d..e75da2f15 100644 --- a/pallets/ocex/src/tests.rs +++ b/pallets/ocex/src/tests.rs @@ -1509,15 +1509,14 @@ fn test_deposit_account_not_registered() { let account_id = create_account_id(); new_test_ext().execute_with(|| { assert_ok!(OCEX::set_exchange_state(RuntimeOrigin::root(), true)); - allowlist_token(AssetId::Asset(10)); - assert_noop!( + mint_into_account(account_id.clone()); + allowlist_token(AssetId::Polkadex); + assert_ok!( OCEX::deposit( RuntimeOrigin::signed(account_id.clone().into()), - AssetId::Asset(10), + AssetId::Polkadex, 100_u128.into() - ), - Error::::AccountNotRegistered - ); + )); }); } From 846fdf8034b6eaba1a4a4eeae2a4ff55f96d1d55 Mon Sep 17 00:00:00 2001 From: Emmanuel Thomas <50878033+nuel77@users.noreply.github.com> Date: Mon, 29 Apr 2024 16:44:52 +0530 Subject: [PATCH 12/12] fix: fmt --- pallets/ocex/src/tests.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/pallets/ocex/src/tests.rs b/pallets/ocex/src/tests.rs index e75da2f15..1ccaf0e7b 100644 --- a/pallets/ocex/src/tests.rs +++ b/pallets/ocex/src/tests.rs @@ -1511,12 +1511,11 @@ fn test_deposit_account_not_registered() { assert_ok!(OCEX::set_exchange_state(RuntimeOrigin::root(), true)); mint_into_account(account_id.clone()); allowlist_token(AssetId::Polkadex); - assert_ok!( - OCEX::deposit( - RuntimeOrigin::signed(account_id.clone().into()), - AssetId::Polkadex, - 100_u128.into() - )); + assert_ok!(OCEX::deposit( + RuntimeOrigin::signed(account_id.clone().into()), + AssetId::Polkadex, + 100_u128.into() + )); }); }