Skip to content

Commit 6279a07

Browse files
committed
Check notifications are received correctly
1 parent 59db231 commit 6279a07

File tree

1 file changed

+87
-11
lines changed

1 file changed

+87
-11
lines changed

integration_tests/src/tests/evm_notification_test.rs

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use alloy_core::sol_types::{SolCall, SolValue};
2+
use alloy_core::{primitives::U256 as AlloyU256, sol};
13
use export_macro::vm_test;
24
use fil_actor_miner::{
35
ProveCommitSectors3Params, SectorActivationManifest, PieceActivationManifest,
@@ -6,19 +8,25 @@ use fil_actor_miner::{
68
use fil_actors_runtime::{
79
EAM_ACTOR_ADDR, test_utils::EVM_ACTOR_CODE_ID, test_utils::make_piece_cid,
810
};
9-
use fvm_ipld_encoding::{RawBytes, ipld_block::IpldBlock};
11+
use fvm_ipld_encoding::{RawBytes, ipld_block::IpldBlock, BytesDe};
1012
use fvm_shared::{
1113
address::Address, econ::TokenAmount, sector::{RegisteredSealProof, SectorNumber},
1214
piece::PaddedPieceSize, piece::PieceInfo,
1315
};
1416
use num_traits::Zero;
1517
use vm_api::VM;
18+
use vm_api::util::serialize_ok;
1619

1720
use crate::util::{
1821
create_accounts, create_miner, precommit_sectors_v2,
1922
advance_by_deadline_to_epoch, PrecommitMetadata,
2023
};
2124

25+
// Generate a statically typed interface for the NotificationReceiver contract
26+
sol!("../actors/evm/tests/contracts/NotificationReceiver.sol");
27+
28+
// Use ContractParams from evm_test module to avoid duplicate definition
29+
use super::evm_test::ContractParams;
2230

2331
#[vm_test]
2432
pub fn evm_receives_ddo_notifications_test(v: &dyn VM) {
@@ -58,10 +66,7 @@ pub fn evm_receives_ddo_notifications_test(v: &dyn VM) {
5866
create_result.ret.unwrap().deserialize().expect("Failed to decode create return");
5967
let evm_actor_addr = Address::new_id(create_return.actor_id);
6068
let evm_robust_addr = create_return.robust_address.unwrap();
61-
let evm_eth_addr = create_return.eth_address;
62-
63-
println!("Created EVM contract at ID: {}, Robust: {}, ETH: 0x{}",
64-
evm_actor_addr, evm_robust_addr, hex::encode(&evm_eth_addr));
69+
let _evm_eth_addr = create_return.eth_address;
6570

6671

6772
// Precommit sectors
@@ -139,16 +144,87 @@ pub fn evm_receives_ddo_notifications_test(v: &dyn VM) {
139144
).unwrap();
140145

141146
assert!(prove_result.code.is_success(), "ProveCommit failed: {}", prove_result.message);
142-
143-
println!("Successfully proved sectors with EVM notifications");
144147

145148
// Verify that the EVM contract received the notifications
146-
// In a real test, we would call a getter method on the contract to verify state
147-
// For now, we check that the EVM actor exists and has the expected code
149+
// Check that the EVM actor exists with correct code
148150
let evm_actor = v.actor(&evm_actor_addr).unwrap();
149151
assert_eq!(evm_actor.code, *EVM_ACTOR_CODE_ID, "EVM actor has wrong code ID");
150152

151-
// The contract should have processed the notifications
152-
// In production, we would call contract methods to verify the stored notification data
153+
// 1. Call totalNotifications() to verify it equals 1
154+
{
155+
let call_params = NotificationReceiver::totalNotificationsCall::new(()).abi_encode();
156+
let call_result = v.execute_message(
157+
&worker,
158+
&evm_robust_addr,
159+
&TokenAmount::zero(),
160+
fil_actor_evm::Method::InvokeContract as u64,
161+
Some(serialize_ok(&ContractParams(call_params.to_vec()))),
162+
).unwrap();
163+
164+
assert!(call_result.code.is_success(), "Failed to call totalNotifications: {}", call_result.message);
165+
166+
// Decode the return value
167+
let return_data: BytesDe = call_result.ret.unwrap().deserialize().unwrap();
168+
let total_notifications = AlloyU256::abi_decode(&return_data.0)
169+
.expect("Failed to decode totalNotifications return value");
170+
assert_eq!(total_notifications, AlloyU256::from(1), "Expected 1 notification, got {}", total_notifications);
171+
}
153172

173+
// 2. Call getNotification(0) to verify the notification contents match exactly what was sent
174+
{
175+
let call_params = NotificationReceiver::getNotificationCall::new((AlloyU256::from(0),)).abi_encode();
176+
let call_result = v.execute_message(
177+
&worker,
178+
&evm_robust_addr,
179+
&TokenAmount::zero(),
180+
fil_actor_evm::Method::InvokeContract as u64,
181+
Some(serialize_ok(&ContractParams(call_params.to_vec()))),
182+
).unwrap();
183+
184+
assert!(call_result.code.is_success(), "Failed to call getNotification: {}", call_result.message);
185+
186+
// Decode the return value - it returns a tuple of (uint64, int64, bytes, uint64, bytes)
187+
let return_data: BytesDe = call_result.ret.unwrap().deserialize().unwrap();
188+
189+
// Use the generated abi_decode_returns function
190+
let notification_result = NotificationReceiver::getNotificationCall::abi_decode_returns(&return_data.0)
191+
.expect("Failed to decode getNotification return value");
192+
193+
let received_sector = notification_result.sector;
194+
let minimum_commitment_epoch = notification_result.minimumCommitmentEpoch;
195+
let data_cid_bytes = notification_result.dataCid;
196+
let received_piece_size = notification_result.pieceSize;
197+
let received_payload = notification_result.payload;
198+
199+
// Verify the notification fields match EXACTLY what was sent in the manifest
200+
201+
// Check sector number matches what we set in the manifest
202+
assert_eq!(received_sector, sector_number,
203+
"Sector number mismatch: expected {}, got {}", sector_number, received_sector);
204+
205+
// Check piece size matches what we set in the manifest
206+
assert_eq!(received_piece_size, piece_size0.0,
207+
"Piece size mismatch: expected {}, got {}", piece_size0.0, received_piece_size);
208+
209+
// Check payload matches exactly what we set in the manifest (hex "cafe")
210+
let expected_payload_bytes = hex::decode("cafe").unwrap();
211+
assert_eq!(received_payload.as_ref(), expected_payload_bytes.as_slice(),
212+
"Payload mismatch: expected 0x{}, got 0x{}",
213+
hex::encode(&expected_payload_bytes), hex::encode(&received_payload));
214+
215+
// Check the piece CID data is present
216+
// The contract receives the CID with an extra leading byte from the CBOR encoding,
217+
// so we verify it contains the expected CID data after the first byte
218+
let expected_cid_bytes = piece_cid0.to_bytes();
219+
assert!(!data_cid_bytes.is_empty(), "Data CID should not be empty");
220+
assert!(data_cid_bytes.len() > expected_cid_bytes.len(), "Data CID seems too short");
221+
// Verify the CID data matches (skipping the first byte which is CBOR encoding)
222+
assert_eq!(&data_cid_bytes[1..], expected_cid_bytes,
223+
"Piece CID data mismatch: expected 0x{}, got 0x{}",
224+
hex::encode(&expected_cid_bytes), hex::encode(&data_cid_bytes[1..]));
225+
226+
// Verify minimum_commitment_epoch is set (this is calculated by the system)
227+
assert!(minimum_commitment_epoch > 0,
228+
"Minimum commitment epoch should be positive, got {}", minimum_commitment_epoch);
229+
}
154230
}

0 commit comments

Comments
 (0)