diff --git a/overridden_contracts/src/Gateway.sol b/overridden_contracts/src/Gateway.sol index ab37001..fa8515f 100644 --- a/overridden_contracts/src/Gateway.sol +++ b/overridden_contracts/src/Gateway.sol @@ -123,6 +123,15 @@ contract Gateway is IOGateway, IInitializable, IUpgradable { _; } + // Can only be called by the middleware + modifier onlyMiddleware() { + GatewayCoreStorage.Layout storage layout = GatewayCoreStorage.layout(); + if (msg.sender != layout.middleware) { + revert Unauthorized(); + } + _; + } + constructor( address beefyClient, address agentExecutor, @@ -522,9 +531,10 @@ contract Gateway is IOGateway, IInitializable, IUpgradable { } function sendOperatorsData( - bytes32[] calldata data - ) external { - Ticket memory ticket = Operators.encodeOperatorsData(data); + bytes32[] calldata data, + uint48 epoch + ) external onlyMiddleware { + Ticket memory ticket = Operators.encodeOperatorsData(data, epoch); _submitOutboundToChannel(PRIMARY_GOVERNANCE_CHANNEL_ID, ticket.payload); } diff --git a/overridden_contracts/src/Operators.sol b/overridden_contracts/src/Operators.sol index 99e7906..8c68674 100644 --- a/overridden_contracts/src/Operators.sol +++ b/overridden_contracts/src/Operators.sol @@ -29,7 +29,8 @@ library Operators { uint16 private constant MAX_OPERATORS = 1000; function encodeOperatorsData( - bytes32[] calldata operatorsKeys + bytes32[] calldata operatorsKeys, + uint48 epoch ) internal returns (Ticket memory ticket) { if (operatorsKeys.length == 0) { revert Operators__OperatorsKeysCannotBeEmpty(); @@ -45,7 +46,7 @@ library Operators { // TODO For now mock it to 0 ticket.costs = Costs(0, 0); - ticket.payload = OSubstrateTypes.EncodedOperatorsData(operatorsKeys, uint32(validatorsKeysLength)); + ticket.payload = OSubstrateTypes.EncodedOperatorsData(operatorsKeys, uint32(validatorsKeysLength), epoch); emit IOGateway.OperatorsDataCreated(validatorsKeysLength, ticket.payload); } } diff --git a/overridden_contracts/src/interfaces/IOGateway.sol b/overridden_contracts/src/interfaces/IOGateway.sol index 8f50be5..b93a457 100644 --- a/overridden_contracts/src/interfaces/IOGateway.sol +++ b/overridden_contracts/src/interfaces/IOGateway.sol @@ -30,7 +30,8 @@ interface IOGateway is IGateway { function s_middleware() external view returns(address); function sendOperatorsData( - bytes32[] calldata data + bytes32[] calldata data, + uint48 epoch ) external; function setMiddleware( diff --git a/overridden_contracts/src/libraries/OSubstrateTypes.sol b/overridden_contracts/src/libraries/OSubstrateTypes.sol index 61cd84e..f5f5d2d 100644 --- a/overridden_contracts/src/libraries/OSubstrateTypes.sol +++ b/overridden_contracts/src/libraries/OSubstrateTypes.sol @@ -28,7 +28,8 @@ library OSubstrateTypes { function EncodedOperatorsData( bytes32[] calldata operatorsKeys, - uint32 operatorsCount + uint32 operatorsCount, + uint48 epoch ) internal view returns (bytes memory) { bytes memory operatorsFlattened = new bytes(operatorsCount * 32); for (uint32 i = 0; i < operatorsCount; i++) { @@ -43,7 +44,7 @@ library OSubstrateTypes { bytes1(uint8(OutboundCommandV1.ReceiveValidators)), ScaleCodec.encodeCompactU32(operatorsCount), operatorsFlattened, - ScaleCodec.encodeU64(uint64(block.timestamp)) + ScaleCodec.encodeU64(uint64(epoch)) ); } } diff --git a/overridden_contracts/test/override_test/Gateway.t.sol b/overridden_contracts/test/override_test/Gateway.t.sol index 916f2fc..0622532 100644 --- a/overridden_contracts/test/override_test/Gateway.t.sol +++ b/overridden_contracts/test/override_test/Gateway.t.sol @@ -69,6 +69,7 @@ contract GatewayTest is Test { address public account1; address public account2; + address public middleware; uint64 public maxDispatchGas = 500_000; uint256 public maxRefund = 1 ether; @@ -133,6 +134,7 @@ contract GatewayTest is Test { account1 = makeAddr("account1"); account2 = makeAddr("account2"); + middleware = makeAddr("middleware"); // create tokens for account 1 hoax(account1); @@ -145,6 +147,9 @@ contract GatewayTest is Test { recipientAddress20 = multiAddressFromBytes20(bytes20(keccak256("recipient"))); dotTokenID = bytes32(uint256(1)); + + // set middleware + IOGateway(address(gateway)).setMiddleware(middleware); } bytes private constant FINAL_VALIDATORS_PAYLOAD = @@ -180,19 +185,24 @@ contract GatewayTest is Test { } function testSendOperatorsDataX() public { + // FINAL_VALIDATORS_PAYLOAD has been encoded with epoch 1. + uint48 epoch = 1; + // Create mock agent and paraID - vm.warp(1); + vm.prank(middleware); vm.expectEmit(true, false, false, true); emit IGateway.OutboundMessageAccepted(PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, FINAL_VALIDATORS_PAYLOAD); - IOGateway(address(gateway)).sendOperatorsData(VALIDATORS_DATA); + IOGateway(address(gateway)).sendOperatorsData(VALIDATORS_DATA, epoch); } function testShouldNotSendOperatorsDataBecauseOperatorsTooLong() public { bytes32[] memory longOperatorsData = createLongOperatorsData(); + uint48 epoch = 42; + vm.prank(middleware); vm.expectRevert(Operators.Operators__OperatorsLengthTooLong.selector); - IOGateway(address(gateway)).sendOperatorsData(longOperatorsData); + IOGateway(address(gateway)).sendOperatorsData(longOperatorsData, epoch); } function testSendOperatorsDataWith50Entries() public { @@ -206,13 +216,13 @@ contract GatewayTest is Test { // Get accounts array bytes32[] memory accounts = abi.decode(vm.parseJson(json, "$.accounts"), (bytes32[])); - uint64 timestamp = abi.decode(vm.parseJson(json, "$.timestamp"), (uint64)); - vm.warp(timestamp); + uint48 epoch = abi.decode(vm.parseJson(json, "$.epoch"), (uint48)); + vm.prank(middleware); vm.expectEmit(true, false, false, true); emit IGateway.OutboundMessageAccepted(PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, final_payload); - IOGateway(address(gateway)).sendOperatorsData(accounts); + IOGateway(address(gateway)).sendOperatorsData(accounts, epoch); } function testSendOperatorsDataWith400Entries() public { @@ -225,13 +235,13 @@ contract GatewayTest is Test { // Get accounts array bytes32[] memory accounts = abi.decode(vm.parseJson(json, "$.accounts"), (bytes32[])); - uint64 timestamp = abi.decode(vm.parseJson(json, "$.timestamp"), (uint64)); - vm.warp(timestamp); + uint48 epoch = abi.decode(vm.parseJson(json, "$.epoch"), (uint48)); + vm.prank(middleware); vm.expectEmit(true, false, false, true); emit IGateway.OutboundMessageAccepted(PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, final_payload); - IOGateway(address(gateway)).sendOperatorsData(accounts); + IOGateway(address(gateway)).sendOperatorsData(accounts, epoch); } function testSendOperatorsDataWith1000Entries() public { @@ -244,18 +254,18 @@ contract GatewayTest is Test { // Get accounts array bytes32[] memory accounts = abi.decode(vm.parseJson(json, "$.accounts"), (bytes32[])); - uint64 timestamp = abi.decode(vm.parseJson(json, "$.timestamp"), (uint64)); - vm.warp(timestamp); + uint48 epoch = abi.decode(vm.parseJson(json, "$.epoch"), (uint48)); + vm.prank(middleware); vm.expectEmit(true, false, false, true); emit IGateway.OutboundMessageAccepted(PRIMARY_GOVERNANCE_CHANNEL_ID, 1, messageID, final_payload); - IOGateway(address(gateway)).sendOperatorsData(accounts); + IOGateway(address(gateway)).sendOperatorsData(accounts, epoch); } function testOwnerCanChangeMiddleware() public { vm.expectEmit(true, true, false, false); - emit IOGateway.MiddlewareChanged(address(0), 0x0123456789012345678901234567890123456789); + emit IOGateway.MiddlewareChanged(address(middleware), 0x0123456789012345678901234567890123456789); IOGateway(address(gateway)).setMiddleware(0x0123456789012345678901234567890123456789); diff --git a/overridden_contracts/test/snowbridge-data/test_vector_message_validator_1000.json b/overridden_contracts/test/snowbridge-data/test_vector_message_validator_1000.json index ab6a18b..c16dd68 100644 --- a/overridden_contracts/test/snowbridge-data/test_vector_message_validator_1000.json +++ b/overridden_contracts/test/snowbridge-data/test_vector_message_validator_1000.json @@ -1002,5 +1002,5 @@ "0x00000000000000000000000000000000000000000000000000000000000003e7", "0x00000000000000000000000000000000000000000000000000000000000003e8" ], - "timestamp": 10157 + "epoch": 10157 } diff --git a/overridden_contracts/test/snowbridge-data/test_vector_message_validator_400.json b/overridden_contracts/test/snowbridge-data/test_vector_message_validator_400.json index 640368e..77eb391 100644 --- a/overridden_contracts/test/snowbridge-data/test_vector_message_validator_400.json +++ b/overridden_contracts/test/snowbridge-data/test_vector_message_validator_400.json @@ -402,5 +402,5 @@ "0x000000000000000000000000000000000000000000000000000000000000018f", "0x0000000000000000000000000000000000000000000000000000000000000190" ], - "timestamp": 289461593 + "epoch": 289461593 } diff --git a/overridden_contracts/test/snowbridge-data/test_vector_message_validator_50.json b/overridden_contracts/test/snowbridge-data/test_vector_message_validator_50.json index 6abbaca..121a1af 100644 --- a/overridden_contracts/test/snowbridge-data/test_vector_message_validator_50.json +++ b/overridden_contracts/test/snowbridge-data/test_vector_message_validator_50.json @@ -52,5 +52,5 @@ "0x0000000000000000000000000000000000000000000000000000000000000031", "0x0000000000000000000000000000000000000000000000000000000000000032" ], - "timestamp": 1736769558000 + "epoch": 1736769558000 }