소스 검색

sdk: add fallible money fee parsing

brid 1 주 전
부모
커밋
72dbe9f135
1개의 변경된 파일58개의 추가작업 그리고 2개의 파일을 삭제
  1. 58 2
      src/sdk/src/tx.rs

+ 58 - 2
src/sdk/src/tx.rs

@@ -23,11 +23,11 @@ use std::{
 
 #[cfg(feature = "async")]
 use darkfi_serial::async_trait;
-use darkfi_serial::{SerialDecodable, SerialEncodable};
+use darkfi_serial::{deserialize, SerialDecodable, SerialEncodable};
 
 use super::{
     crypto::{ContractId, SecretKey},
-    ContractError, GenericResult,
+    ContractError, FeeError, FeeResult, GenericResult,
 };
 use crate::crypto::{DAO_CONTRACT_ID, DEPLOYOOOR_CONTRACT_ID, MONEY_CONTRACT_ID};
 
@@ -89,6 +89,15 @@ impl ContractCall {
         self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x00)
     }
 
+    /// Returns the paid native token fee encoded in a `Money::FeeV1` call.
+    pub fn money_fee_value(&self) -> FeeResult<u64> {
+        if !self.is_money_fee() || self.data.len() < 9 {
+            return Err(FeeError::InvalidFeeCall)
+        }
+
+        deserialize(&self.data[1..9]).map_err(|_| FeeError::InvalidFeeCall)
+    }
+
     /// Returns true if call is a money genesis mint.
     pub fn is_money_genesis_mint(&self) -> bool {
         self.matches_contract_call_type(*MONEY_CONTRACT_ID, 0x01)
@@ -160,6 +169,53 @@ impl ContractCall {
     }
 }
 
+#[cfg(test)]
+mod tests {
+    use darkfi_serial::serialize;
+
+    use super::*;
+    use crate::crypto::DAO_CONTRACT_ID;
+
+    #[test]
+    fn money_fee_value_extracts_paid_fee() {
+        let fee = 42_u64;
+        let mut data = vec![0x00];
+        data.extend(serialize(&fee));
+        data.extend([0xab, 0xcd]);
+
+        let call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
+
+        assert_eq!(call.money_fee_value().unwrap(), fee);
+    }
+
+    #[test]
+    fn money_fee_value_rejects_wrong_contract() {
+        let mut data = vec![0x00];
+        data.extend(serialize(&42_u64));
+
+        let call = ContractCall { contract_id: *DAO_CONTRACT_ID, data };
+
+        assert_eq!(call.money_fee_value(), Err(FeeError::InvalidFeeCall));
+    }
+
+    #[test]
+    fn money_fee_value_rejects_wrong_function() {
+        let mut data = vec![0x01];
+        data.extend(serialize(&42_u64));
+
+        let call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data };
+
+        assert_eq!(call.money_fee_value(), Err(FeeError::InvalidFeeCall));
+    }
+
+    #[test]
+    fn money_fee_value_rejects_short_data() {
+        let call = ContractCall { contract_id: *MONEY_CONTRACT_ID, data: vec![0x00, 0x01] };
+
+        assert_eq!(call.money_fee_value(), Err(FeeError::InvalidFeeCall));
+    }
+}
+
 // Avoid showing the data in the debug output since often the calldata is very long.
 impl Debug for ContractCall {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {