Skip to content

Commit 73b93cd

Browse files
committed
test(contract): move the prepay validation tests to unit tests
`prepay_attestation_storage`'s exact-multiple and zero-grants cases are pure input validation: they need a contract and a deposit context, nothing about participants or protocol state, so they belong in `src` rather than the in-process harness.
1 parent 9e63d0c commit 73b93cd

2 files changed

Lines changed: 60 additions & 55 deletions

File tree

crates/contract/src/lib.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4894,6 +4894,66 @@ mod tests {
48944894
)
48954895
}
48964896

4897+
/// The deposit must be exactly `fee × grants`, which is what makes a remainder — and so a
4898+
/// refund path — impossible.
4899+
#[rstest]
4900+
#[case::one_yocto_short(-1)]
4901+
#[case::one_yocto_over(1)]
4902+
fn prepay_attestation_storage__should_reject_a_deposit_that_is_not_an_exact_multiple(
4903+
#[case] offset: i128,
4904+
) {
4905+
// Given
4906+
let (_, mut contract, _) = basic_setup(Curve::Edwards25519, &mut OsRng);
4907+
let node: AccountId = "newcomer.near".parse().unwrap();
4908+
let fee = u128::from(contract.config().attestation_storage_fee_millinear);
4909+
let exact = NearToken::from_millinear(fee * 2).as_yoctonear();
4910+
let attached = NearToken::from_yoctonear((exact as i128 + offset) as u128);
4911+
testing_env!(
4912+
VMContextBuilder::new()
4913+
.predecessor_account_id("operator.near".parse().unwrap())
4914+
.attached_deposit(attached)
4915+
.build()
4916+
);
4917+
4918+
// When
4919+
let result = contract.prepay_attestation_storage(node.clone(), 2);
4920+
4921+
// Then
4922+
assert_matches!(
4923+
&result,
4924+
Err(Error::InvalidParameters(InvalidParameters::UnexpectedDeposit {
4925+
attached: a,
4926+
required
4927+
})) if *a == attached.as_yoctonear() && *required == exact
4928+
);
4929+
assert_eq!(contract.available_attestation_grants(node), 0);
4930+
}
4931+
4932+
#[test]
4933+
fn prepay_attestation_storage__should_reject_zero_grants() {
4934+
// Given
4935+
let (_, mut contract, _) = basic_setup(Curve::Edwards25519, &mut OsRng);
4936+
let node: AccountId = "newcomer.near".parse().unwrap();
4937+
testing_env!(
4938+
VMContextBuilder::new()
4939+
.predecessor_account_id("operator.near".parse().unwrap())
4940+
.attached_deposit(NearToken::from_yoctonear(0))
4941+
.build()
4942+
);
4943+
4944+
// When
4945+
let result = contract.prepay_attestation_storage(node.clone(), 0);
4946+
4947+
// Then
4948+
assert_matches!(
4949+
&result,
4950+
Err(Error::InvalidParameters(
4951+
InvalidParameters::MalformedPayload { .. }
4952+
))
4953+
);
4954+
assert_eq!(contract.available_attestation_grants(node), 0);
4955+
}
4956+
48974957
/// Without this the async path would store for free while the synchronous one charged.
48984958
#[test]
48994959
fn resolve_verification__should_consume_one_grant_when_the_entry_is_new() {

crates/contract/tests/inprocess/attestation_submission.rs

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -942,61 +942,6 @@ fn vote_code_hash_works_in_contract_protocol_states(#[case] state: ContractProto
942942
assert_allowed_docker_image_hashes!(&setup, 100, &[(code_hash, None)]);
943943
}
944944

945-
/// The deposit must be exactly `fee × grants`. Anything else is rejected, which is what
946-
/// makes a remainder — and therefore a refund path — impossible.
947-
#[rstest]
948-
#[case::one_yocto_short(-1)]
949-
#[case::one_yocto_over(1)]
950-
fn prepay_attestation_storage__should_reject_a_deposit_that_is_not_an_exact_multiple(
951-
#[case] offset: i128,
952-
) {
953-
// Given
954-
let mut setup = TestSetupBuilder::new().build();
955-
let node: AccountId = "newcomer.near".parse().unwrap();
956-
let fee = u128::from(setup.contract.config().attestation_storage_fee_millinear);
957-
let exact = NearToken::from_millinear(fee * 2).as_yoctonear();
958-
let attached = NearToken::from_yoctonear((exact as i128 + offset) as u128);
959-
testing_env!(common::participant_context_with_deposit(
960-
&"operator.near".parse().unwrap(),
961-
attached
962-
));
963-
964-
// When
965-
let result = setup.contract.prepay_attestation_storage(node.clone(), 2);
966-
967-
// Then
968-
assert_matches!(
969-
&result,
970-
Err(Error::InvalidParameters(InvalidParameters::UnexpectedDeposit { attached: a, required }))
971-
if *a == attached.as_yoctonear() && *required == exact
972-
);
973-
assert_eq!(setup.contract.available_attestation_grants(node), 0);
974-
}
975-
976-
/// Buying zero grants is rejected rather than silently accepting the deposit.
977-
#[test]
978-
fn prepay_attestation_storage__should_reject_zero_grants() {
979-
// Given
980-
let mut setup = TestSetupBuilder::new().build();
981-
let node: AccountId = "newcomer.near".parse().unwrap();
982-
testing_env!(common::participant_context_with_deposit(
983-
&"operator.near".parse().unwrap(),
984-
NearToken::from_yoctonear(0)
985-
));
986-
987-
// When
988-
let result = setup.contract.prepay_attestation_storage(node.clone(), 0);
989-
990-
// Then
991-
assert_matches!(
992-
&result,
993-
Err(Error::InvalidParameters(
994-
InvalidParameters::MalformedPayload { .. }
995-
))
996-
);
997-
assert_eq!(setup.contract.available_attestation_grants(node), 0);
998-
}
999-
1000945
/// The operator pays and the node submits — two different accounts. This is the whole point
1001946
/// of prepaying: the node's function-call key cannot attach a deposit, so somebody else must.
1002947
#[test]

0 commit comments

Comments
 (0)