@@ -4,34 +4,41 @@ pragma solidity ^0.8.23;
44import {GatewayActorModifiers} from "../lib/LibGatewayActorStorage.sol " ;
55import {IpcEnvelope, CallMsg, IpcMsgKind} from "../structs/CrossNet.sol " ;
66import {IPCMsgType} from "../enums/IPCMsgType.sol " ;
7- import {SubnetID, AssetKind, IPCAddress} from "../structs/Subnet.sol " ;
8- import {InvalidXnetMessage, InvalidXnetMessageReason, CannotSendCrossMsgToItself, MethodNotAllowed} from "../errors/IPCErrors.sol " ;
7+ import {Subnet, SubnetID, AssetKind, IPCAddress, Asset } from "../structs/Subnet.sol " ;
8+ import {InvalidXnetMessage, InvalidXnetMessageReason, MethodNotAllowed} from "../errors/IPCErrors.sol " ;
99import {SubnetIDHelper} from "../lib/SubnetIDHelper.sol " ;
1010import {LibGateway} from "../lib/LibGateway.sol " ;
1111import {FilAddress} from "fevmate/contracts/utils/FilAddress.sol " ;
1212import {AssetHelper} from "../lib/AssetHelper.sol " ;
1313import {CrossMsgHelper} from "../lib/CrossMsgHelper.sol " ;
1414import {FvmAddressHelper} from "../lib/FvmAddressHelper.sol " ;
15+ import {ISubnetActor} from "../interfaces/ISubnetActor.sol " ;
16+
17+ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol " ;
1518
1619string constant ERR_GENERAL_CROSS_MSG_DISABLED = "Support for general-purpose cross-net messages is disabled " ;
1720string constant ERR_MULTILEVEL_CROSS_MSG_DISABLED = "Support for multi-level cross-net messages is disabled " ;
1821
1922contract GatewayMessengerFacet is GatewayActorModifiers {
2023 using FilAddress for address payable ;
2124 using SubnetIDHelper for SubnetID;
25+ using EnumerableSet for EnumerableSet.Bytes32Set;
26+ using CrossMsgHelper for IpcEnvelope;
27+ using AssetHelper for Asset;
2228
2329 /**
2430 * @dev Sends a general-purpose cross-message from the local subnet to the destination subnet.
25- * Any value in msg.value will be forwarded in the call.
31+ * IMPORTANT: Native tokens via msg.value are treated as a contribution toward gas costs associated with message propagation.
32+ * There is no strict enforcement of the exact gas cost, and any msg.value provided will be accepted.
2633 *
2734 * IMPORTANT: Only smart contracts are allowed to trigger these cross-net messages. User wallets can send funds
2835 * from their address to the destination subnet and then run the transaction in the destination normally.
2936 *
30- * @param envelope - the original envelope, which will be validated, stamped and committed during the send.
37+ * @param envelope - the original envelope, which will be validated, stamped, and committed during the send.
3138 * @return committed envelope.
3239 */
3340 function sendContractXnetMessage (
34- IpcEnvelope calldata envelope
41+ IpcEnvelope memory envelope
3542 ) external payable returns (IpcEnvelope memory committed ) {
3643 if (! s.generalPurposeCrossMsg) {
3744 revert MethodNotAllowed (ERR_GENERAL_CROSS_MSG_DISABLED);
@@ -42,28 +49,33 @@ contract GatewayMessengerFacet is GatewayActorModifiers {
4249 revert InvalidXnetMessage (InvalidXnetMessageReason.Sender);
4350 }
4451
45- if (envelope.value != msg .value ) {
46- revert InvalidXnetMessage (InvalidXnetMessageReason.Value);
47- }
48-
49- if (envelope.kind != IpcMsgKind.Call) {
50- revert InvalidXnetMessage (InvalidXnetMessageReason.Kind);
51- }
52-
5352 // Will revert if the message won't deserialize into a CallMsg.
5453 abi.decode (envelope.message, (CallMsg));
5554
5655 committed = IpcEnvelope ({
5756 kind: IpcMsgKind.Call,
5857 from: IPCAddress ({subnetId: s.networkName, rawAddress: FvmAddressHelper.from (msg .sender )}),
5958 to: envelope.to,
60- value: msg .value ,
59+ value: envelope .value,
6160 message: envelope.message,
62- nonce: 0 // nonce will be updated by LibGateway.commitCrossMessage
61+ // nonce and originalNonce will be updated by LibGateway.commitValidatedCrossMessage
62+ originalNonce: 0 ,
63+ localNonce: 0
6364 });
6465
66+ (bool valid , InvalidXnetMessageReason reason , IPCMsgType applyType ) = committed.validateCrossMessage ();
67+ if (! valid) {
68+ revert InvalidXnetMessage (reason);
69+ }
70+
71+ if (applyType == IPCMsgType.TopDown) {
72+ (, SubnetID memory nextHop ) = committed.to.subnetId.down (s.networkName);
73+ // lock funds on the current subnet gateway for the next hop
74+ ISubnetActor (nextHop.getActor ()).supplySource ().lock (envelope.value);
75+ }
76+
6577 // Commit xnet message for dispatch.
66- bool shouldBurn = LibGateway.commitCrossMessage (committed);
78+ bool shouldBurn = LibGateway.commitValidatedCrossMessage (committed);
6779
6880 // Apply side effects, such as burning funds.
6981 LibGateway.crossMsgSideEffects ({v: committed.value, shouldBurn: shouldBurn});
@@ -75,23 +87,9 @@ contract GatewayMessengerFacet is GatewayActorModifiers {
7587 }
7688
7789 /**
78- * @dev propagates the populated cross net message for the given cid
79- * @param msgCid - the cid of the cross-net message
90+ * @dev Propagates all the populated cross-net messages from the postbox.
8091 */
81- function propagate (bytes32 msgCid ) external payable {
82- if (! s.multiLevelCrossMsg) {
83- revert MethodNotAllowed (ERR_MULTILEVEL_CROSS_MSG_DISABLED);
84- }
85-
86- IpcEnvelope storage crossMsg = s.postbox[msgCid];
87-
88- bool shouldBurn = LibGateway.commitCrossMessage (crossMsg);
89- // We must delete the message first to prevent potential re-entrancies,
90- // and as the message is deleted and we don't have a reference to the object
91- // anymore, we need to pull the data from the message to trigger the side-effects.
92- uint256 v = crossMsg.value;
93- delete s.postbox[msgCid];
94-
95- LibGateway.crossMsgSideEffects ({v: v, shouldBurn: shouldBurn});
92+ function propagateAll () external payable {
93+ LibGateway.propagateAllPostboxMessages ();
9694 }
9795}
0 commit comments