Skip to content

Commit f6d73d1

Browse files
committed
test(dpp): add tests for credit transfer and topup validation error paths
1 parent 3397bd7 commit f6d73d1

1 file changed

Lines changed: 165 additions & 0 deletions

File tree

  • packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0

packages/rs-dpp/src/state_transition/state_transitions/identity/identity_credit_transfer_transition/v0/v0_methods.rs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,168 @@ impl IdentityCreditTransferTransitionMethodsV0 for IdentityCreditTransferTransit
110110
Ok(transition)
111111
}
112112
}
113+
114+
#[cfg(all(test, feature = "state-transition-signing"))]
115+
mod tests {
116+
use crate::address_funds::AddressWitness;
117+
use crate::consensus::basic::BasicError;
118+
use crate::consensus::ConsensusError;
119+
use crate::identity::accessors::{IdentityGettersV0, IdentitySettersV0};
120+
use crate::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0;
121+
use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
122+
use crate::identity::signer::Signer;
123+
use crate::identity::{Identity, IdentityPublicKey, KeyType, Purpose, SecurityLevel};
124+
use crate::state_transition::identity_credit_transfer_transition::methods::IdentityCreditTransferTransitionMethodsV0;
125+
use crate::state_transition::identity_credit_transfer_transition::v0::IdentityCreditTransferTransitionV0;
126+
use crate::ProtocolError;
127+
use platform_value::BinaryData;
128+
use platform_value::Identifier;
129+
use platform_version::version::LATEST_PLATFORM_VERSION;
130+
131+
#[derive(Debug)]
132+
struct TestIdentitySigner {
133+
allowed_key_id: u32,
134+
}
135+
136+
impl Signer<IdentityPublicKey> for TestIdentitySigner {
137+
fn sign(
138+
&self,
139+
_key: &IdentityPublicKey,
140+
_data: &[u8],
141+
) -> Result<BinaryData, ProtocolError> {
142+
Ok(vec![0; 65].into())
143+
}
144+
145+
fn sign_create_witness(
146+
&self,
147+
_key: &IdentityPublicKey,
148+
_data: &[u8],
149+
) -> Result<AddressWitness, ProtocolError> {
150+
Err(ProtocolError::NotSupported(
151+
"sign_create_witness is not used in these tests".to_string(),
152+
))
153+
}
154+
155+
fn can_sign_with(&self, key: &IdentityPublicKey) -> bool {
156+
key.id() == self.allowed_key_id
157+
}
158+
}
159+
160+
fn transfer_key(key_id: u32) -> IdentityPublicKey {
161+
IdentityPublicKeyV0 {
162+
id: key_id,
163+
purpose: Purpose::TRANSFER,
164+
security_level: SecurityLevel::CRITICAL,
165+
contract_bounds: None,
166+
key_type: KeyType::ECDSA_SECP256K1,
167+
read_only: false,
168+
data: vec![2; 33].into(),
169+
disabled_at: None,
170+
}
171+
.into()
172+
}
173+
174+
fn identity_with_transfer_key(identity_id: Identifier, key_id: u32) -> Identity {
175+
let mut identity =
176+
Identity::default_versioned(LATEST_PLATFORM_VERSION).expect("expected identity");
177+
identity.set_id(identity_id);
178+
identity.add_public_key(transfer_key(key_id));
179+
identity
180+
}
181+
182+
#[test]
183+
fn should_return_identity_credit_transfer_to_self_error_when_recipient_is_sender() {
184+
let identity_id = Identifier::random();
185+
let identity = identity_with_transfer_key(identity_id, 1);
186+
let min_transfer_amount = LATEST_PLATFORM_VERSION
187+
.fee_version
188+
.state_transition_min_fees
189+
.credit_transfer;
190+
191+
let result = IdentityCreditTransferTransitionV0::try_from_identity(
192+
&identity,
193+
identity_id,
194+
min_transfer_amount,
195+
0,
196+
TestIdentitySigner { allowed_key_id: 1 },
197+
None,
198+
1,
199+
LATEST_PLATFORM_VERSION,
200+
None,
201+
);
202+
203+
match result {
204+
Err(ProtocolError::ConsensusError(consensus_error)) => {
205+
assert!(matches!(
206+
consensus_error.as_ref(),
207+
ConsensusError::BasicError(BasicError::IdentityCreditTransferToSelfError(_))
208+
));
209+
}
210+
other => panic!("expected to-self consensus error, got {other:?}"),
211+
}
212+
}
213+
214+
#[test]
215+
fn should_return_invalid_identity_credit_transfer_amount_error_when_below_minimum() {
216+
let identity_id = Identifier::random();
217+
let identity = identity_with_transfer_key(identity_id, 1);
218+
let min_transfer_amount = LATEST_PLATFORM_VERSION
219+
.fee_version
220+
.state_transition_min_fees
221+
.credit_transfer;
222+
assert!(
223+
min_transfer_amount > 0,
224+
"minimum transfer amount must be positive"
225+
);
226+
let below_min_amount = min_transfer_amount - 1;
227+
228+
let result = IdentityCreditTransferTransitionV0::try_from_identity(
229+
&identity,
230+
Identifier::random(),
231+
below_min_amount,
232+
0,
233+
TestIdentitySigner { allowed_key_id: 1 },
234+
None,
235+
1,
236+
LATEST_PLATFORM_VERSION,
237+
None,
238+
);
239+
240+
match result {
241+
Err(ProtocolError::ConsensusError(consensus_error)) => {
242+
assert!(matches!(
243+
consensus_error.as_ref(),
244+
ConsensusError::BasicError(
245+
BasicError::InvalidIdentityCreditTransferAmountError(error)
246+
) if error.amount() == below_min_amount
247+
&& error.min_amount() == min_transfer_amount
248+
));
249+
}
250+
other => panic!("expected invalid amount consensus error, got {other:?}"),
251+
}
252+
}
253+
254+
#[test]
255+
fn should_succeed_when_transfer_amount_equals_minimum() {
256+
let identity_id = Identifier::random();
257+
let identity = identity_with_transfer_key(identity_id, 1);
258+
let min_transfer_amount = LATEST_PLATFORM_VERSION
259+
.fee_version
260+
.state_transition_min_fees
261+
.credit_transfer;
262+
263+
let result = IdentityCreditTransferTransitionV0::try_from_identity(
264+
&identity,
265+
Identifier::random(),
266+
min_transfer_amount,
267+
0,
268+
TestIdentitySigner { allowed_key_id: 1 },
269+
None,
270+
1,
271+
LATEST_PLATFORM_VERSION,
272+
None,
273+
);
274+
275+
assert!(result.is_ok(), "expected boundary amount to be valid");
276+
}
277+
}

0 commit comments

Comments
 (0)