Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(node): support l2 value tests #1242

Merged
merged 4 commits into from
Dec 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion contracts/contracts/errors/IPCErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ enum InvalidXnetMessageReason {
Value,
Kind,
CannotSendToItself,
CommonParentNotExist
CommonParentNotExist,
IncompatibleSupplySource
}

string constant ERR_PERMISSIONED_AND_BOOTSTRAPPED = "Method not allowed if permissioned is enabled and subnet bootstrapped";
Expand Down
10 changes: 7 additions & 3 deletions contracts/contracts/gateway/GatewayMessengerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ contract GatewayMessengerFacet is GatewayActorModifiers {
revert InvalidXnetMessage(InvalidXnetMessageReason.Sender);
}

ISubnetActor(s.networkName.getActor()).supplySource().lock(envelope.value);

// Will revert if the message won't deserialize into a CallMsg.
abi.decode(envelope.message, (CallMsg));

Expand All @@ -63,7 +61,7 @@ contract GatewayMessengerFacet is GatewayActorModifiers {
nonce: 0 // nonce will be updated by LibGateway.commitValidatedCrossMessage
});

CrossMessageValidationOutcome outcome = committed.validateCrossMessage();
(CrossMessageValidationOutcome outcome, IPCMsgType applyType) = committed.validateCrossMessage();

if (outcome != CrossMessageValidationOutcome.Valid) {
if (outcome == CrossMessageValidationOutcome.InvalidDstSubnet) {
Expand All @@ -75,6 +73,12 @@ contract GatewayMessengerFacet is GatewayActorModifiers {
}
}

if (applyType == IPCMsgType.TopDown) {
(, SubnetID memory nextHop) = committed.to.subnetId.down(s.networkName);
// lock funds on the current subnet gateway for the next hop
ISubnetActor(nextHop.getActor()).supplySource().lock(envelope.value);
}

// Commit xnet message for dispatch.
bool shouldBurn = LibGateway.commitValidatedCrossMessage(committed);

Expand Down
2 changes: 1 addition & 1 deletion contracts/contracts/interfaces/ISubnetActor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import {Asset} from "../structs/Subnet.sol";

/// @title Subnet actor interface
interface ISubnetActor {
function supplySource() external view returns(Asset memory);
function supplySource() external view returns (Asset memory);
}
3 changes: 3 additions & 0 deletions contracts/contracts/lib/AssetHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,7 @@ library AssetHelper {
return Asset({kind: AssetKind.Native, tokenAddress: address(0)});
}

function erc20(address token) internal pure returns (Asset memory) {
return Asset({kind: AssetKind.ERC20, tokenAddress: token});
}
}
4 changes: 2 additions & 2 deletions contracts/contracts/lib/CrossMsgHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ library CrossMsgHelper {
return true;
}

function validateCrossMessage(IpcEnvelope memory crossMsg) internal view returns (CrossMessageValidationOutcome) {
return LibGateway.validateCrossMessage(crossMsg);
function validateCrossMessage(IpcEnvelope memory crossMsg) internal view returns (CrossMessageValidationOutcome, IPCMsgType) {
return LibGateway.checkCrossMessage(crossMsg);
}
}
43 changes: 29 additions & 14 deletions contracts/contracts/lib/LibGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ library LibGateway {
emit MessageStoredInPostbox({id: crossMsg.toDeterministicHash()});
return;
}

// execute the message and get the receipt.
(bool success, bytes memory ret) = executeCrossMsg(crossMsg, supplySource);
if (success) {
Expand Down Expand Up @@ -611,64 +611,78 @@ library LibGateway {

/// @notice Validates a cross message before committing it.
function validateCrossMessage(IpcEnvelope memory envelope) internal view returns (CrossMessageValidationOutcome) {
(CrossMessageValidationOutcome outcome, ) = checkCrossMessage(envelope);
return outcome;
}

/// @notice Validates a cross message and returns the applyType if the message is valid
function checkCrossMessage(IpcEnvelope memory envelope) internal view returns (CrossMessageValidationOutcome, IPCMsgType applyType) {
SubnetID memory toSubnetId = envelope.to.subnetId;
if (toSubnetId.isEmpty()) {
return CrossMessageValidationOutcome.InvalidDstSubnet;
return (CrossMessageValidationOutcome.InvalidDstSubnet, applyType);
}

GatewayActorStorage storage s = LibGatewayActorStorage.appStorage();
SubnetID memory currentNetwork = s.networkName;

// We cannot send a cross message to the same subnet.
if (toSubnetId.equals(currentNetwork)) {
return CrossMessageValidationOutcome.CannotSendToItself;
return (CrossMessageValidationOutcome.CannotSendToItself, applyType);
}

// Lowest common ancestor subnet
bool isLCA = toSubnetId.commonParent(envelope.from.subnetId).equals(currentNetwork);
IPCMsgType applyType = envelope.applyType(currentNetwork);
applyType = envelope.applyType(currentNetwork);

// If the directionality is top-down, or if we're inverting the direction
// else we need to check if the common parent exists.
if (applyType == IPCMsgType.TopDown || isLCA) {
(bool foundChildSubnetId, SubnetID memory childSubnetId) = toSubnetId.down(currentNetwork);
if (!foundChildSubnetId) {
return CrossMessageValidationOutcome.InvalidDstSubnet;
return (CrossMessageValidationOutcome.InvalidDstSubnet, applyType);
}

(bool foundSubnet,) = LibGateway.getSubnet(childSubnetId);
if (!foundSubnet) {
return CrossMessageValidationOutcome.InvalidDstSubnet;
return (CrossMessageValidationOutcome.InvalidDstSubnet, applyType);
}
} else {
SubnetID memory commonParent = toSubnetId.commonParent(currentNetwork);
if (commonParent.isEmpty()) {
return CrossMessageValidationOutcome.CommonParentNotExist;
return (CrossMessageValidationOutcome.CommonParentNotExist, applyType);
}
}

// starting/ending subnet, no need check supply sources
if (envelope.from.subnetId.equals(currentNetwork) || envelope.to.subnetId.equals(currentNetwork)) {
return (CrossMessageValidationOutcome.Valid, applyType);
}

bool supplySourcesCompatible = checkSubnetsSupplyCompatible({
isLCA: isLCA,
applyType: applyType,
incoming: envelope.from.subnetId,
outgoing: envelope.to.subnetId,
current: currentNetwork
});
if (supplySourcesCompatible) {
return CrossMessageValidationOutcome.IncompatibleSupplySource;

if (!supplySourcesCompatible) {
return (CrossMessageValidationOutcome.IncompatibleSupplySource, applyType);
}

return CrossMessageValidationOutcome.Valid;
return (CrossMessageValidationOutcome.Valid, applyType);
}

// Function to map CrossMessageValidationOutcome to InvalidXnetMessageReason
// Function to map CrossMessageValidationOutcome to InvalidXnetMessageReason
function validationOutcomeToInvalidXnetMsgReason(CrossMessageValidationOutcome outcome) internal pure returns (InvalidXnetMessageReason) {
if (outcome == CrossMessageValidationOutcome.InvalidDstSubnet) {
return InvalidXnetMessageReason.DstSubnet;
} else if (outcome == CrossMessageValidationOutcome.CannotSendToItself) {
return InvalidXnetMessageReason.CannotSendToItself;
} else if (outcome == CrossMessageValidationOutcome.CommonParentNotExist) {
return InvalidXnetMessageReason.CommonParentNotExist;
} else if (outcome == CrossMessageValidationOutcome.IncompatibleSupplySource) {
return InvalidXnetMessageReason.IncompatibleSupplySource;
}

revert("Unhandled validation outcome");
Expand All @@ -681,10 +695,11 @@ library LibGateway {
GatewayActorStorage storage s = LibGatewayActorStorage.appStorage();

uint256 keysLength = s.postboxKeys.length();
bytes32[] memory ids = new bytes32[](keysLength);

bytes32[] memory values = s.postboxKeys.values();

for (uint256 i = 0; i < keysLength; ) {
bytes32 msgCid = s.postboxKeys.at(i);
ids[i] = msgCid;
bytes32 msgCid = values[i];
LibGateway.propagatePostboxMessage(msgCid);

unchecked {
Expand Down
2 changes: 1 addition & 1 deletion contracts/test/integration/GatewayDiamondToken.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ contract GatewayDiamondTokenTest is Test, IntegrationTestBase {
vm.prank(address(saDiamond));
vm.expectCall(recipient, abi.encodeCall(IIpcHandler.handleIpcMessage, (msgs[0])), 1);
gatewayDiamond.checkpointer().commitCheckpoint(batch);
assertEq(token.balanceOf(recipient), 0);
assertEq(token.balanceOf(recipient), 8);
}

function test_propagation() public {
Expand Down
Loading
Loading