From 0f880327e34f2d6ea4fdaa9d72f38293638dc9a2 Mon Sep 17 00:00:00 2001 From: Zehui Zheng Date: Thu, 25 Jan 2024 02:36:06 +0800 Subject: [PATCH] feat!: blockchain agnostic inputs --- .../rollups/.changeset/grumpy-coins-drop.md | 5 ++ .../.changeset/seven-teachers-behave.md | 1 + onchain/rollups/.changeset/six-doors-grow.md | 12 +++ .../contracts/common/CanonicalMachine.sol | 4 +- .../contracts/common/InputEncoding.sol | 12 +-- onchain/rollups/contracts/common/Inputs.sol | 26 +++++++ .../rollups/contracts/inputs/IInputBox.sol | 24 +++--- onchain/rollups/contracts/inputs/InputBox.sol | 31 ++++---- .../rollups/contracts/library/LibInput.sol | 45 ------------ .../contracts/portals/ERC1155BatchPortal.sol | 4 +- .../contracts/portals/ERC1155SinglePortal.sol | 4 +- .../rollups/contracts/portals/ERC20Portal.sol | 4 +- .../contracts/portals/ERC721Portal.sol | 4 +- .../rollups/contracts/portals/EtherPortal.sol | 4 +- .../relays/ApplicationAddressRelay.sol | 4 +- .../test/foundry/inputs/InputBox.t.sol | 73 +++++++++++++------ .../foundry/portals/ERC1155BatchPortal.t.sol | 14 ++-- .../foundry/portals/ERC1155SinglePortal.t.sol | 14 ++-- .../test/foundry/portals/ERC20Portal.t.sol | 18 ++--- .../test/foundry/portals/ERC721Portal.t.sol | 14 ++-- .../test/foundry/portals/EtherPortal.t.sol | 15 ++-- .../relays/ApplicationAddressRelay.t.sol | 12 ++- .../test/foundry/util/EvmAdvanceEncoder.sol | 21 ++++++ 23 files changed, 204 insertions(+), 161 deletions(-) create mode 100644 onchain/rollups/.changeset/grumpy-coins-drop.md create mode 100644 onchain/rollups/.changeset/six-doors-grow.md create mode 100644 onchain/rollups/contracts/common/Inputs.sol delete mode 100644 onchain/rollups/contracts/library/LibInput.sol create mode 100644 onchain/rollups/test/foundry/util/EvmAdvanceEncoder.sol diff --git a/onchain/rollups/.changeset/grumpy-coins-drop.md b/onchain/rollups/.changeset/grumpy-coins-drop.md new file mode 100644 index 00000000..7b79c017 --- /dev/null +++ b/onchain/rollups/.changeset/grumpy-coins-drop.md @@ -0,0 +1,5 @@ +--- +"@cartesi/rollups": major +--- + +Inputs are now blockchain-agnostic and self-contained blobs. diff --git a/onchain/rollups/.changeset/seven-teachers-behave.md b/onchain/rollups/.changeset/seven-teachers-behave.md index 27877b47..4e0634f7 100644 --- a/onchain/rollups/.changeset/seven-teachers-behave.md +++ b/onchain/rollups/.changeset/seven-teachers-behave.md @@ -11,3 +11,4 @@ Removed: - the `AuthorityHistoryPairFactory` contract. - the `IAuthorityHistoryPairFactory` interface. - the `OutputEncoding` library. +- the `LibInput` library. diff --git a/onchain/rollups/.changeset/six-doors-grow.md b/onchain/rollups/.changeset/six-doors-grow.md new file mode 100644 index 00000000..9f97aea5 --- /dev/null +++ b/onchain/rollups/.changeset/six-doors-grow.md @@ -0,0 +1,12 @@ +--- +"@cartesi/rollups": major +--- + +Modified the `IInputBox` interface: + +- Modified the `InputAdded` event: + + - Removed the `sender` parameter. + - Changed the semantics of the `input` parameter. + +- Added an `InputTooLarge` error. diff --git a/onchain/rollups/contracts/common/CanonicalMachine.sol b/onchain/rollups/contracts/common/CanonicalMachine.sol index f54488e8..82505520 100644 --- a/onchain/rollups/contracts/common/CanonicalMachine.sol +++ b/onchain/rollups/contracts/common/CanonicalMachine.sol @@ -20,9 +20,9 @@ library CanonicalMachine { /// @notice Keccak-256 output size (32 bytes). Log2Size constant KECCAK_LOG2_SIZE = Log2Size.wrap(5); - /// @notice Maximum input payload size (~2 megabytes). + /// @notice Maximum input size (~2 megabytes). /// @dev The offset and size fields use up the extra 64 bytes. - uint256 constant INPUT_PAYLOAD_MAX_SIZE = (1 << 21) - 64; + uint256 constant INPUT_MAX_SIZE = (1 << 21) - 64; /// @notice Maximum output metadata memory range (2 megabytes). Log2Size constant OUTPUT_METADATA_LOG2_SIZE = Log2Size.wrap(21); diff --git a/onchain/rollups/contracts/common/InputEncoding.sol b/onchain/rollups/contracts/common/InputEncoding.sol index d81dea68..45e528d6 100644 --- a/onchain/rollups/contracts/common/InputEncoding.sol +++ b/onchain/rollups/contracts/common/InputEncoding.sol @@ -16,7 +16,7 @@ library InputEncoding { /// @param sender The Ether sender /// @param value The amount of Ether being sent in Wei /// @param execLayerData Additional data to be interpreted by the execution layer - /// @return The encoded input + /// @return The encoded input payload function encodeEtherDeposit( address sender, uint256 value, @@ -35,7 +35,7 @@ library InputEncoding { /// @param sender The token sender /// @param amount The amount of tokens being sent /// @param execLayerData Additional data to be interpreted by the execution layer - /// @return The encoded input + /// @return The encoded input payload function encodeERC20Deposit( IERC20 token, address sender, @@ -57,7 +57,7 @@ library InputEncoding { /// @param tokenId The token identifier /// @param baseLayerData Additional data to be interpreted by the base layer /// @param execLayerData Additional data to be interpreted by the execution layer - /// @return The encoded input + /// @return The encoded input payload /// @dev `baseLayerData` should be forwarded to `token`. function encodeERC721Deposit( IERC721 token, @@ -83,7 +83,7 @@ library InputEncoding { /// @param value Transfer amount /// @param baseLayerData Additional data to be interpreted by the base layer /// @param execLayerData Additional data to be interpreted by the execution layer - /// @return The encoded input + /// @return The encoded input payload /// @dev `baseLayerData` should be forwarded to `token`. function encodeSingleERC1155Deposit( IERC1155 token, @@ -111,7 +111,7 @@ library InputEncoding { /// @param values Transfer amounts per token type /// @param baseLayerData Additional data to be interpreted by the base layer /// @param execLayerData Additional data to be interpreted by the execution layer - /// @return The encoded input + /// @return The encoded input payload /// @dev `baseLayerData` should be forwarded to `token`. function encodeBatchERC1155Deposit( IERC1155 token, @@ -137,7 +137,7 @@ library InputEncoding { /// @notice Encode an application address relay. /// @param app The application address - /// @return The encoded input + /// @return The encoded input payload function encodeApplicationAddressRelay( address app ) internal pure returns (bytes memory) { diff --git a/onchain/rollups/contracts/common/Inputs.sol b/onchain/rollups/contracts/common/Inputs.sol new file mode 100644 index 00000000..6fc05c06 --- /dev/null +++ b/onchain/rollups/contracts/common/Inputs.sol @@ -0,0 +1,26 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +pragma solidity ^0.8.8; + +/// @title Inputs +/// @notice Defines the signatures of inputs. +interface Inputs { + /// @notice An advance request from an EVM-compatible blockchain to a Cartesi Machine. + /// @param sender The address of whoever sent the input + /// @param blockNumber The number of the block in which the input was added + /// @param blockTimestamp The timestamp of the block in which the input was added + /// @param index The input index + /// @param payload The payload provided by the sender + function EvmAdvance( + address sender, + uint256 blockNumber, + uint256 blockTimestamp, + uint256 index, + bytes calldata payload + ) external; + + /// @notice An inspect request to a Cartesi Machine. + /// @param payload The inspect payload + function EvmInspect(bytes calldata payload) external; +} diff --git a/onchain/rollups/contracts/inputs/IInputBox.sol b/onchain/rollups/contracts/inputs/IInputBox.sol index 7ea894b6..84d9da9d 100644 --- a/onchain/rollups/contracts/inputs/IInputBox.sol +++ b/onchain/rollups/contracts/inputs/IInputBox.sol @@ -12,29 +12,23 @@ interface IInputBox { /// @notice MUST trigger when an input is added. /// @param app The application address /// @param index The input index - /// @param sender The input sender address - /// @param payload The input payload - event InputAdded( - address indexed app, - uint256 indexed index, - address sender, - bytes payload - ); + /// @param input The input blob + event InputAdded(address indexed app, uint256 indexed index, bytes input); - /// @notice Payload is too large. + /// @notice Input is too large. /// @param app The application address - /// @param payloadLength The payload length - /// @param maxPayloadLength The maximum payload length - error PayloadTooLarge( + /// @param inputLength The input length + /// @param maxInputLength The maximum input length + error InputTooLarge( address app, - uint256 payloadLength, - uint256 maxPayloadLength + uint256 inputLength, + uint256 maxInputLength ); /// @notice Send an input to an application. /// @param app The application address /// @param payload The input payload - /// @return The input hash + /// @return The hash of the input blob /// @dev MUST fire an `InputAdded` event. function addInput( address app, diff --git a/onchain/rollups/contracts/inputs/InputBox.sol b/onchain/rollups/contracts/inputs/InputBox.sol index 6127ee81..67db7f58 100644 --- a/onchain/rollups/contracts/inputs/InputBox.sol +++ b/onchain/rollups/contracts/inputs/InputBox.sol @@ -4,8 +4,8 @@ pragma solidity ^0.8.8; import {IInputBox} from "./IInputBox.sol"; -import {LibInput} from "../library/LibInput.sol"; import {CanonicalMachine} from "../common/CanonicalMachine.sol"; +import {Inputs} from "../common/Inputs.sol"; contract InputBox is IInputBox { /// @notice Mapping of application addresses to arrays of input hashes. @@ -16,29 +16,28 @@ contract InputBox is IInputBox { address app, bytes calldata payload ) external override returns (bytes32) { - if (payload.length > CanonicalMachine.INPUT_PAYLOAD_MAX_SIZE) { - revert PayloadTooLarge( - app, - payload.length, - CanonicalMachine.INPUT_PAYLOAD_MAX_SIZE - ); - } - bytes32[] storage inputBox = _inputBoxes[app]; uint256 index = inputBox.length; - bytes32 inputHash = LibInput.computeInputHash( - msg.sender, - block.number, - block.timestamp, - index, - payload + bytes memory input = abi.encodeCall( + Inputs.EvmAdvance, + (msg.sender, block.number, block.timestamp, index, payload) ); + if (input.length > CanonicalMachine.INPUT_MAX_SIZE) { + revert InputTooLarge( + app, + input.length, + CanonicalMachine.INPUT_MAX_SIZE + ); + } + + bytes32 inputHash = keccak256(input); + inputBox.push(inputHash); - emit InputAdded(app, index, msg.sender, payload); + emit InputAdded(app, index, input); return inputHash; } diff --git a/onchain/rollups/contracts/library/LibInput.sol b/onchain/rollups/contracts/library/LibInput.sol deleted file mode 100644 index 542db97f..00000000 --- a/onchain/rollups/contracts/library/LibInput.sol +++ /dev/null @@ -1,45 +0,0 @@ -// (c) Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: Apache-2.0 (see LICENSE) - -pragma solidity ^0.8.8; - -library LibInput { - /// @notice Compute the hash of an input. - /// @param sender The input sender address - /// @param blockNumber The block number - /// @param blockTimestamp The block timestamp - /// @param index The input index - /// @param payload The input payload - /// @return The input hash - function computeInputHash( - address sender, - uint256 blockNumber, - uint256 blockTimestamp, - uint256 index, - bytes calldata payload - ) internal pure returns (bytes32) { - bytes memory metadata = encodeInputMetadata( - sender, - blockNumber, - blockTimestamp, - index - ); - - return keccak256(abi.encode(keccak256(metadata), keccak256(payload))); - } - - /// @notice Encode the metadata of an input. - /// @param sender The input sender address - /// @param blockNumber The block number - /// @param blockTimestamp The block timestamp - /// @param index The input index - /// @return The encoded input metadata - function encodeInputMetadata( - address sender, - uint256 blockNumber, - uint256 blockTimestamp, - uint256 index - ) internal pure returns (bytes memory) { - return abi.encode(sender, blockNumber, blockTimestamp, 0, index); - } -} diff --git a/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol b/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol index 1831ca48..67d7fa08 100644 --- a/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol +++ b/onchain/rollups/contracts/portals/ERC1155BatchPortal.sol @@ -36,7 +36,7 @@ contract ERC1155BatchPortal is IERC1155BatchPortal, InputRelay { baseLayerData ); - bytes memory input = InputEncoding.encodeBatchERC1155Deposit( + bytes memory payload = InputEncoding.encodeBatchERC1155Deposit( token, msg.sender, tokenIds, @@ -45,7 +45,7 @@ contract ERC1155BatchPortal is IERC1155BatchPortal, InputRelay { execLayerData ); - _inputBox.addInput(app, input); + _inputBox.addInput(app, payload); } function supportsInterface( diff --git a/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol b/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol index a9f70960..5534557e 100644 --- a/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol +++ b/onchain/rollups/contracts/portals/ERC1155SinglePortal.sol @@ -30,7 +30,7 @@ contract ERC1155SinglePortal is IERC1155SinglePortal, InputRelay { ) external override { token.safeTransferFrom(msg.sender, app, tokenId, value, baseLayerData); - bytes memory input = InputEncoding.encodeSingleERC1155Deposit( + bytes memory payload = InputEncoding.encodeSingleERC1155Deposit( token, msg.sender, tokenId, @@ -39,7 +39,7 @@ contract ERC1155SinglePortal is IERC1155SinglePortal, InputRelay { execLayerData ); - _inputBox.addInput(app, input); + _inputBox.addInput(app, payload); } function supportsInterface( diff --git a/onchain/rollups/contracts/portals/ERC20Portal.sol b/onchain/rollups/contracts/portals/ERC20Portal.sol index df53afab..b557e40d 100644 --- a/onchain/rollups/contracts/portals/ERC20Portal.sol +++ b/onchain/rollups/contracts/portals/ERC20Portal.sol @@ -32,14 +32,14 @@ contract ERC20Portal is IERC20Portal, InputRelay { revert ERC20TransferFailed(); } - bytes memory input = InputEncoding.encodeERC20Deposit( + bytes memory payload = InputEncoding.encodeERC20Deposit( token, msg.sender, amount, execLayerData ); - _inputBox.addInput(app, input); + _inputBox.addInput(app, payload); } function supportsInterface( diff --git a/onchain/rollups/contracts/portals/ERC721Portal.sol b/onchain/rollups/contracts/portals/ERC721Portal.sol index 5de5acd6..a4c01404 100644 --- a/onchain/rollups/contracts/portals/ERC721Portal.sol +++ b/onchain/rollups/contracts/portals/ERC721Portal.sol @@ -29,7 +29,7 @@ contract ERC721Portal is IERC721Portal, InputRelay { ) external override { token.safeTransferFrom(msg.sender, app, tokenId, baseLayerData); - bytes memory input = InputEncoding.encodeERC721Deposit( + bytes memory payload = InputEncoding.encodeERC721Deposit( token, msg.sender, tokenId, @@ -37,7 +37,7 @@ contract ERC721Portal is IERC721Portal, InputRelay { execLayerData ); - _inputBox.addInput(app, input); + _inputBox.addInput(app, payload); } function supportsInterface( diff --git a/onchain/rollups/contracts/portals/EtherPortal.sol b/onchain/rollups/contracts/portals/EtherPortal.sol index fdaad2bd..5f7808b7 100644 --- a/onchain/rollups/contracts/portals/EtherPortal.sol +++ b/onchain/rollups/contracts/portals/EtherPortal.sol @@ -29,13 +29,13 @@ contract EtherPortal is IEtherPortal, InputRelay { revert EtherTransferFailed(); } - bytes memory input = InputEncoding.encodeEtherDeposit( + bytes memory payload = InputEncoding.encodeEtherDeposit( msg.sender, msg.value, execLayerData ); - _inputBox.addInput(app, input); + _inputBox.addInput(app, payload); } function supportsInterface( diff --git a/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol b/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol index 1cd044fa..866c2d14 100644 --- a/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol +++ b/onchain/rollups/contracts/relays/ApplicationAddressRelay.sol @@ -20,8 +20,8 @@ contract ApplicationAddressRelay is IApplicationAddressRelay, InputRelay { constructor(IInputBox inputBox) InputRelay(inputBox) {} function relayApplicationAddress(address app) external override { - bytes memory input = InputEncoding.encodeApplicationAddressRelay(app); - _inputBox.addInput(app, input); + bytes memory payload = InputEncoding.encodeApplicationAddressRelay(app); + _inputBox.addInput(app, payload); } function supportsInterface( diff --git a/onchain/rollups/test/foundry/inputs/InputBox.t.sol b/onchain/rollups/test/foundry/inputs/InputBox.t.sol index 85261b0a..138b8b49 100644 --- a/onchain/rollups/test/foundry/inputs/InputBox.t.sol +++ b/onchain/rollups/test/foundry/inputs/InputBox.t.sol @@ -7,7 +7,9 @@ import {Test} from "forge-std/Test.sol"; import {InputBox} from "contracts/inputs/InputBox.sol"; import {IInputBox} from "contracts/inputs/IInputBox.sol"; import {CanonicalMachine} from "contracts/common/CanonicalMachine.sol"; -import {LibInput} from "contracts/library/LibInput.sol"; +import {Inputs} from "contracts/common/Inputs.sol"; + +import {EvmAdvanceEncoder} from "../util/EvmAdvanceEncoder.sol"; contract InputBoxTest is Test { InputBox _inputBox; @@ -22,55 +24,67 @@ contract InputBoxTest is Test { function testAddLargeInput() public { address app = vm.addr(1); - uint256 max = CanonicalMachine.INPUT_PAYLOAD_MAX_SIZE; + uint256 max = _getMaxInputPayloadLength(); _inputBox.addInput(app, new bytes(max)); + bytes memory largePayload = new bytes(max + 1); + uint256 largeLength = EvmAdvanceEncoder + .encode(address(this), 1, largePayload) + .length; vm.expectRevert( abi.encodeWithSelector( - IInputBox.PayloadTooLarge.selector, + IInputBox.InputTooLarge.selector, app, - max + 1, - max + largeLength, + CanonicalMachine.INPUT_MAX_SIZE ) ); - _inputBox.addInput(app, new bytes(max + 1)); + _inputBox.addInput(app, largePayload); } - function testAddInput(address app, bytes[] calldata inputs) public { - uint256 numInputs = inputs.length; - bytes32[] memory returnedValues = new bytes32[](numInputs); + function testAddInput(address app, bytes[] calldata payloads) public { + uint256 numPayloads = payloads.length; + bytes32[] memory returnedValues = new bytes32[](numPayloads); uint256 year2022 = 1641070800; // Unix Timestamp for 2022 - // assume #bytes for each input is within bounds - for (uint256 i; i < numInputs; ++i) { - vm.assume( - inputs[i].length <= CanonicalMachine.INPUT_PAYLOAD_MAX_SIZE - ); + // assume #bytes for each payload is within bounds + for (uint256 i; i < numPayloads; ++i) { + vm.assume(payloads[i].length <= _getMaxInputPayloadLength()); } // adding inputs - for (uint256 i; i < numInputs; ++i) { + for (uint256 i; i < numPayloads; ++i) { // test for different block number and timestamp vm.roll(i); vm.warp(i + year2022); vm.expectEmit(true, true, false, true, address(_inputBox)); - emit IInputBox.InputAdded(app, i, address(this), inputs[i]); + bytes memory input = EvmAdvanceEncoder.encode( + address(this), + i, + payloads[i] + ); + emit IInputBox.InputAdded(app, i, input); - returnedValues[i] = _inputBox.addInput(app, inputs[i]); + returnedValues[i] = _inputBox.addInput(app, payloads[i]); assertEq(i + 1, _inputBox.getNumberOfInputs(app)); } // testing added inputs - for (uint256 i; i < numInputs; ++i) { - bytes32 inputHash = LibInput.computeInputHash( - address(this), - i, // block.number - i + year2022, // block.timestamp - i, // index - inputs[i] + for (uint256 i; i < numPayloads; ++i) { + bytes32 inputHash = keccak256( + abi.encodeCall( + Inputs.EvmAdvance, + ( + address(this), + i, // block.number + i + year2022, // block.timestamp + i, // inputBox.length + payloads[i] + ) + ) ); // test if input hash is the same as in InputBox assertEq(inputHash, _inputBox.getInputHash(app, i)); @@ -78,4 +92,15 @@ contract InputBoxTest is Test { assertEq(inputHash, returnedValues[i]); } } + + function _getMaxInputPayloadLength() internal pure returns (uint256) { + bytes memory blob = abi.encodeCall( + Inputs.EvmAdvance, + (address(0), 0, 0, 0, new bytes(32)) + ); + // number of bytes in input blob excluding input payload + uint256 extraBytes = blob.length - 32; + // because it's abi encoded, input payloads are stored as multiples of 32 bytes + return ((CanonicalMachine.INPUT_MAX_SIZE - extraBytes) / 32) * 32; + } } diff --git a/onchain/rollups/test/foundry/portals/ERC1155BatchPortal.t.sol b/onchain/rollups/test/foundry/portals/ERC1155BatchPortal.t.sol index e4d9892b..c8112aa0 100644 --- a/onchain/rollups/test/foundry/portals/ERC1155BatchPortal.t.sol +++ b/onchain/rollups/test/foundry/portals/ERC1155BatchPortal.t.sol @@ -76,14 +76,14 @@ contract ERC1155BatchPortalTest is Test { vm.mockCall(address(_token), safeBatchTransferFrom, abi.encode()); vm.expectCall(address(_token), safeBatchTransferFrom, 1); - bytes memory input = _encodeInput( + bytes memory payload = _encodePayload( tokenIds, values, baseLayerData, execLayerData ); - bytes memory addInputCall = _encodeAddInput(input); + bytes memory addInputCall = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInputCall, abi.encode(bytes32(0))); vm.expectCall(address(_inputBox), addInputCall, 1); @@ -115,14 +115,14 @@ contract ERC1155BatchPortalTest is Test { vm.mockCall(address(_token), safeBatchTransferFrom, abi.encode()); vm.mockCallRevert(address(_token), safeBatchTransferFrom, errorData); - bytes memory input = _encodeInput( + bytes memory payload = _encodePayload( tokenIds, values, baseLayerData, execLayerData ); - bytes memory addInputCall = _encodeAddInput(input); + bytes memory addInputCall = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInputCall, abi.encode(bytes32(0))); @@ -205,7 +205,7 @@ contract ERC1155BatchPortalTest is Test { } } - function _encodeInput( + function _encodePayload( uint256[] calldata tokenIds, uint256[] calldata values, bytes calldata baseLayerData, @@ -223,9 +223,9 @@ contract ERC1155BatchPortalTest is Test { } function _encodeAddInput( - bytes memory input + bytes memory payload ) internal view returns (bytes memory) { - return abi.encodeCall(IInputBox.addInput, (_app, input)); + return abi.encodeCall(IInputBox.addInput, (_app, payload)); } function _encodeSafeBatchTransferFrom( diff --git a/onchain/rollups/test/foundry/portals/ERC1155SinglePortal.t.sol b/onchain/rollups/test/foundry/portals/ERC1155SinglePortal.t.sol index 1d5c9772..1bd82d99 100644 --- a/onchain/rollups/test/foundry/portals/ERC1155SinglePortal.t.sol +++ b/onchain/rollups/test/foundry/portals/ERC1155SinglePortal.t.sol @@ -76,14 +76,14 @@ contract ERC1155SinglePortalTest is Test { vm.mockCall(address(_token), safeTransferFrom, abi.encode()); vm.expectCall(address(_token), safeTransferFrom, 1); - bytes memory input = _encodeInput( + bytes memory payload = _encodePayload( tokenId, value, baseLayerData, execLayerData ); - bytes memory addInputCall = _encodeAddInput(input); + bytes memory addInputCall = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInputCall, abi.encode(bytes32(0))); vm.expectCall(address(_inputBox), addInputCall, 1); @@ -115,14 +115,14 @@ contract ERC1155SinglePortalTest is Test { vm.mockCall(address(_token), safeTransferFrom, abi.encode()); vm.mockCallRevert(address(_token), safeTransferFrom, errorData); - bytes memory input = _encodeInput( + bytes memory payload = _encodePayload( tokenId, value, baseLayerData, execLayerData ); - bytes memory addInputCall = _encodeAddInput(input); + bytes memory addInputCall = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInputCall, abi.encode(bytes32(0))); @@ -191,7 +191,7 @@ contract ERC1155SinglePortalTest is Test { assertEq(_token.balanceOf(address(_portal), tokenId), 0); } - function _encodeInput( + function _encodePayload( uint256 tokenId, uint256 value, bytes calldata baseLayerData, @@ -209,9 +209,9 @@ contract ERC1155SinglePortalTest is Test { } function _encodeAddInput( - bytes memory input + bytes memory payload ) internal view returns (bytes memory) { - return abi.encodeCall(IInputBox.addInput, (_app, input)); + return abi.encodeCall(IInputBox.addInput, (_app, payload)); } function _encodeSafeTransferFrom( diff --git a/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol b/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol index 44aabb73..3c6f5859 100644 --- a/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol +++ b/onchain/rollups/test/foundry/portals/ERC20Portal.t.sol @@ -60,9 +60,9 @@ contract ERC20PortalTest is Test { vm.mockCall(address(_token), transferFrom, abi.encode(true)); - bytes memory input = _encodeInput(amount, data); + bytes memory payload = _encodePayload(amount, data); - bytes memory addInput = _encodeAddInput(input); + bytes memory addInput = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInput, abi.encode(bytes32(0))); @@ -79,9 +79,9 @@ contract ERC20PortalTest is Test { vm.mockCall(address(_token), transferFrom, abi.encode(false)); - bytes memory input = _encodeInput(amount, data); + bytes memory payload = _encodePayload(amount, data); - bytes memory addInput = _encodeAddInput(input); + bytes memory addInput = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInput, abi.encode(bytes32(0))); @@ -100,9 +100,9 @@ contract ERC20PortalTest is Test { vm.mockCallRevert(address(_token), transferFrom, errorData); - bytes memory input = _encodeInput(amount, data); + bytes memory payload = _encodePayload(amount, data); - bytes memory addInput = _encodeAddInput(input); + bytes memory addInput = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInput, abi.encode(bytes32(0))); @@ -150,7 +150,7 @@ contract ERC20PortalTest is Test { assertEq(token.balanceOf(address(_portal)), 0); } - function _encodeInput( + function _encodePayload( uint256 amount, bytes calldata data ) internal view returns (bytes memory) { @@ -164,8 +164,8 @@ contract ERC20PortalTest is Test { } function _encodeAddInput( - bytes memory _input + bytes memory payload ) internal view returns (bytes memory) { - return abi.encodeCall(IInputBox.addInput, (_app, _input)); + return abi.encodeCall(IInputBox.addInput, (_app, payload)); } } diff --git a/onchain/rollups/test/foundry/portals/ERC721Portal.t.sol b/onchain/rollups/test/foundry/portals/ERC721Portal.t.sol index 7f7087cf..117e95e2 100644 --- a/onchain/rollups/test/foundry/portals/ERC721Portal.t.sol +++ b/onchain/rollups/test/foundry/portals/ERC721Portal.t.sol @@ -71,13 +71,13 @@ contract ERC721PortalTest is Test { vm.mockCall(address(_token), safeTransferFrom, abi.encode()); vm.expectCall(address(_token), safeTransferFrom, 1); - bytes memory input = _encodeInput( + bytes memory payload = _encodePayload( tokenId, baseLayerData, execLayerData ); - bytes memory addInputCall = _encodeAddInput(input); + bytes memory addInputCall = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInputCall, abi.encode(bytes32(0))); vm.expectCall(address(_inputBox), addInputCall, 1); @@ -106,13 +106,13 @@ contract ERC721PortalTest is Test { vm.mockCall(address(_token), safeTransferFrom, abi.encode()); vm.mockCallRevert(address(_token), safeTransferFrom, errorData); - bytes memory input = _encodeInput( + bytes memory payload = _encodePayload( tokenId, baseLayerData, execLayerData ); - bytes memory addInputCall = _encodeAddInput(input); + bytes memory addInputCall = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInputCall, abi.encode(bytes32(0))); @@ -166,7 +166,7 @@ contract ERC721PortalTest is Test { assertEq(token.ownerOf(tokenId), _app); } - function _encodeInput( + function _encodePayload( uint256 tokenId, bytes calldata baseLayerData, bytes calldata execLayerData @@ -182,9 +182,9 @@ contract ERC721PortalTest is Test { } function _encodeAddInput( - bytes memory input + bytes memory payload ) internal view returns (bytes memory) { - return abi.encodeCall(IInputBox.addInput, (_app, input)); + return abi.encodeCall(IInputBox.addInput, (_app, payload)); } function _encodeSafeTransferFrom( diff --git a/onchain/rollups/test/foundry/portals/EtherPortal.t.sol b/onchain/rollups/test/foundry/portals/EtherPortal.t.sol index dc8a5d0d..ee6ee023 100644 --- a/onchain/rollups/test/foundry/portals/EtherPortal.t.sol +++ b/onchain/rollups/test/foundry/portals/EtherPortal.t.sol @@ -3,7 +3,6 @@ pragma solidity ^0.8.22; -import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {EtherPortal} from "contracts/portals/EtherPortal.sol"; @@ -47,9 +46,9 @@ contract EtherPortalTest is Test { function testDeposit(uint256 value, bytes calldata data) public { value = _boundValue(value); - bytes memory input = _encodeInput(value, data); + bytes memory payload = _encodePayload(value, data); - bytes memory addInput = _encodeAddInput(input); + bytes memory addInput = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInput, abi.encode(bytes32(0))); @@ -75,9 +74,9 @@ contract EtherPortalTest is Test { vm.mockCallRevert(_app, value, abi.encode(), errorData); - bytes memory input = _encodeInput(value, data); + bytes memory payload = _encodePayload(value, data); - bytes memory addInput = _encodeAddInput(input); + bytes memory addInput = _encodeAddInput(payload); vm.mockCall(address(_inputBox), addInput, abi.encode(bytes32(0))); @@ -88,7 +87,7 @@ contract EtherPortalTest is Test { _portal.depositEther{value: value}(_app, data); } - function _encodeInput( + function _encodePayload( uint256 value, bytes calldata data ) internal view returns (bytes memory) { @@ -96,9 +95,9 @@ contract EtherPortalTest is Test { } function _encodeAddInput( - bytes memory input + bytes memory payload ) internal view returns (bytes memory) { - return abi.encodeCall(IInputBox.addInput, (_app, input)); + return abi.encodeCall(IInputBox.addInput, (_app, payload)); } function _boundValue(uint256 value) internal view returns (uint256) { diff --git a/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol b/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol index 5a50aefe..f1c608a5 100644 --- a/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol +++ b/onchain/rollups/test/foundry/relays/ApplicationAddressRelay.t.sol @@ -10,9 +10,10 @@ import {IApplicationAddressRelay} from "contracts/relays/IApplicationAddressRela import {ApplicationAddressRelay} from "contracts/relays/ApplicationAddressRelay.sol"; import {IInputBox} from "contracts/inputs/IInputBox.sol"; import {InputBox} from "contracts/inputs/InputBox.sol"; -import {InputEncoding} from "contracts/common/InputEncoding.sol"; import {IInputRelay} from "contracts/inputs/IInputRelay.sol"; +import {EvmAdvanceEncoder} from "../util/EvmAdvanceEncoder.sol"; + contract ApplicationAddressRelayTest is Test { IInputBox _inputBox; IApplicationAddressRelay _relay; @@ -48,11 +49,16 @@ contract ApplicationAddressRelayTest is Test { assertEq(_inputBox.getNumberOfInputs(app), 0); // Construct the application address relay input - bytes memory input = abi.encodePacked(app); + bytes memory payload = abi.encodePacked(app); + bytes memory input = EvmAdvanceEncoder.encode( + address(_relay), + 0, + payload + ); // Expect InputAdded to be emitted with the right arguments vm.expectEmit(true, true, false, true, address(_inputBox)); - emit IInputBox.InputAdded(app, 0, address(_relay), input); + emit IInputBox.InputAdded(app, 0, input); // Relay the application's address _relay.relayApplicationAddress(app); diff --git a/onchain/rollups/test/foundry/util/EvmAdvanceEncoder.sol b/onchain/rollups/test/foundry/util/EvmAdvanceEncoder.sol new file mode 100644 index 00000000..d8d7f074 --- /dev/null +++ b/onchain/rollups/test/foundry/util/EvmAdvanceEncoder.sol @@ -0,0 +1,21 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +/// @title EVM Advance Encoder +pragma solidity ^0.8.22; + +import {Inputs} from "contracts/common/Inputs.sol"; + +library EvmAdvanceEncoder { + function encode( + address sender, + uint256 index, + bytes memory payload + ) internal view returns (bytes memory) { + return + abi.encodeCall( + Inputs.EvmAdvance, + (sender, block.number, block.timestamp, index, payload) + ); + } +}