diff --git a/charts/screener/Chart.yaml b/charts/screener/Chart.yaml index 24800f9148..9212c210d8 100644 --- a/charts/screener/Chart.yaml +++ b/charts/screener/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.2.4 +version: 0.2.5 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/screener/templates/configmap.yaml b/charts/screener/templates/configmap.yaml index 2339458155..24b942c92c 100644 --- a/charts/screener/templates/configmap.yaml +++ b/charts/screener/templates/configmap.yaml @@ -9,5 +9,5 @@ metadata: release: {{ .Release.Name }} heritage: {{ .Release.Service }} data: -{{ toYaml .Values.files | indent 2 }} +{{ tpl (toYaml .Values.files) . | indent 2 }} {{- end }} diff --git a/contrib/screener-api/screener/screener.go b/contrib/screener-api/screener/screener.go index 50fde4ae68..33b2bba172 100644 --- a/contrib/screener-api/screener/screener.go +++ b/contrib/screener-api/screener/screener.go @@ -90,6 +90,7 @@ func NewScreener(ctx context.Context, cfg config.Config, metricHandler metrics.H } screener.router = ginhelper.New(logger) + screener.router.Use(screener.metrics.Gin()) screener.router.Handle(http.MethodGet, "/:ruleset/address/:address", screener.screenAddress) screener.router.Handle(http.MethodPost, "/api/data/sync", screener.authMiddleware(cfg), screener.blacklistAddress) @@ -144,6 +145,12 @@ func (s *screenerImpl) fetchBlacklist(ctx context.Context) { // @Produce json // @Router /api/data/sync [post]. func (s *screenerImpl) blacklistAddress(c *gin.Context) { + var err error + ctx, span := s.metrics.Tracer().Start(c.Request.Context(), "blacklistAddress") + defer func() { + metrics.EndSpanWithErr(span, err) + }() + var blacklistBody client.BlackListBody // Grab the body of the JSON request and unmarshal it into the blacklistBody struct. @@ -152,6 +159,14 @@ func (s *screenerImpl) blacklistAddress(c *gin.Context) { return } + span.SetAttributes(attribute.String("type", blacklistBody.TypeReq)) + span.SetAttributes(attribute.String("id", blacklistBody.ID)) + span.SetAttributes(attribute.String("data", blacklistBody.Data)) + span.SetAttributes(attribute.String("network", blacklistBody.Network)) + span.SetAttributes(attribute.String("tag", blacklistBody.Tag)) + span.SetAttributes(attribute.String("remark", blacklistBody.Remark)) + span.SetAttributes(attribute.String("address", blacklistBody.Address)) + blacklistedAddress := db.BlacklistedAddress{ TypeReq: blacklistBody.TypeReq, ID: blacklistBody.ID, @@ -164,7 +179,8 @@ func (s *screenerImpl) blacklistAddress(c *gin.Context) { switch blacklistBody.TypeReq { case "create": - if err := s.db.PutBlacklistedAddress(c, blacklistedAddress); err != nil { + if err := s.db.PutBlacklistedAddress(ctx, blacklistedAddress); err != nil { + span.AddEvent("error", trace.WithAttributes(attribute.String("error", err.Error()))) c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } @@ -262,7 +278,7 @@ func (s *screenerImpl) Start(ctx context.Context) error { // @Success 200 {object} map[string]bool "Returns the risk assessment result" // @Failure 400 {object} map[string]string "Returns error if the required parameters are missing or invalid" // @Failure 500 {object} map[string]string "Returns error if there are problems processing the indicators" -// @Router /screen/{ruleset}/{address} [get] +// @Router /screen/{ruleset}/{address} [get]. func (s *screenerImpl) screenAddress(c *gin.Context) { var err error diff --git a/packages/contracts-communication/CHANGELOG.md b/packages/contracts-communication/CHANGELOG.md index 70315a3406..6708ce73d8 100644 --- a/packages/contracts-communication/CHANGELOG.md +++ b/packages/contracts-communication/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.6.1](https://github.com/synapsecns/sanguine/compare/contracts-communication@1.6.0...contracts-communication@1.6.1) (2024-05-09) + + +### Bug Fixes + +* **contracts-communication:** interchain module ignore nonces ([#2604](https://github.com/synapsecns/sanguine/issues/2604)) ([be4351b](https://github.com/synapsecns/sanguine/commit/be4351be2a5954e6d2c11471b5e93de99b3e42b6)) + + + + + +# [1.6.0](https://github.com/synapsecns/sanguine/compare/contracts-communication@1.5.4...contracts-communication@1.6.0) (2024-05-09) + + +### Features + +* **contracts-communication:** remove batching ([#2599](https://github.com/synapsecns/sanguine/issues/2599)) ([e6588f7](https://github.com/synapsecns/sanguine/commit/e6588f7dab0d4314e1c18b834708264177abdc7a)) + + + + + ## [1.5.4](https://github.com/synapsecns/sanguine/compare/contracts-communication@1.5.3...contracts-communication@1.5.4) (2024-05-08) **Note:** Version bump only for package contracts-communication diff --git a/packages/contracts-communication/configs/global/MessageBus.testnet.json b/packages/contracts-communication/configs/global/MessageBus.testnet.json index 4e571d1be7..37dbadfc03 100644 --- a/packages/contracts-communication/configs/global/MessageBus.testnet.json +++ b/packages/contracts-communication/configs/global/MessageBus.testnet.json @@ -4,8 +4,8 @@ "latestInterchainClient": "InterchainClientV1", "trustedModules": ["SynapseModule"], "appConfig": { - "0_requiredResponses": 1, - "1_optimisticPeriod": 30 + "requiredResponses": 1, + "optimisticPeriod": 30 }, "messageLengthEstimate": 1024 } diff --git a/packages/contracts-communication/configs/global/PingPongApp.testnet.json b/packages/contracts-communication/configs/global/PingPongApp.testnet.json index d1e027a150..040729e7a2 100644 --- a/packages/contracts-communication/configs/global/PingPongApp.testnet.json +++ b/packages/contracts-communication/configs/global/PingPongApp.testnet.json @@ -4,8 +4,8 @@ "latestInterchainClient": "InterchainClientV1", "trustedModules": ["SynapseModule"], "appConfig": { - "0_requiredResponses": 1, - "1_optimisticPeriod": 30 + "requiredResponses": 1, + "optimisticPeriod": 30 }, "gasLimit": 500000 } diff --git a/packages/contracts-communication/configs/global/SynapseModule.testnet.json b/packages/contracts-communication/configs/global/SynapseModule.testnet.json index 1095687b76..d00255052d 100644 --- a/packages/contracts-communication/configs/global/SynapseModule.testnet.json +++ b/packages/contracts-communication/configs/global/SynapseModule.testnet.json @@ -1,6 +1,6 @@ { "claimFeeBPS": 10, - "feeCollector": "0xAe61329Ce0AfFA55A7174916214fC2560a1CdD9f", + "feeRecipient": "0xAe61329Ce0AfFA55A7174916214fC2560a1CdD9f", "gasOracleName": "SynapseGasOracleV1", "threshold": 6, "verifiers": [ diff --git a/packages/contracts-communication/contracts/InterchainClientV1.sol b/packages/contracts-communication/contracts/InterchainClientV1.sol index 80c5d22a48..ebaec2d966 100644 --- a/packages/contracts-communication/contracts/InterchainClientV1.sol +++ b/packages/contracts-communication/contracts/InterchainClientV1.sol @@ -9,8 +9,7 @@ import {IInterchainClientV1} from "./interfaces/IInterchainClientV1.sol"; import {IInterchainDB} from "./interfaces/IInterchainDB.sol"; import {AppConfigV1, AppConfigLib, APP_CONFIG_GUARD_DISABLED, APP_CONFIG_GUARD_DEFAULT} from "./libs/AppConfig.sol"; -import {BatchingV1Lib} from "./libs/BatchingV1.sol"; -import {InterchainBatch, BATCH_UNVERIFIED, BATCH_CONFLICT} from "./libs/InterchainBatch.sol"; +import {InterchainEntry, InterchainEntryLib, ENTRY_UNVERIFIED, ENTRY_CONFLICT} from "./libs/InterchainEntry.sol"; import { InterchainTransaction, InterchainTxDescriptor, InterchainTransactionLib } from "./libs/InterchainTransaction.sol"; @@ -37,8 +36,8 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli /// @notice Address of the InterchainDB contract, set at the time of deployment. address public immutable INTERCHAIN_DB; - /// @notice Address of the Guard module used to verify the validity of batches. - /// Note: batches marked as invalid by the Guard could not be used for message execution, + /// @notice Address of the Guard module used to verify the validity of entries. + /// Note: entries marked as invalid by the Guard could not be used for message execution, /// if the app opts in to use the Guard. address public defaultGuard; @@ -52,7 +51,7 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli } /// @notice Allows the contract owner to set the address of the Guard module. - /// Note: batches marked as invalid by the Guard could not be used for message execution, + /// Note: entries marked as invalid by the Guard could not be used for message execution, /// if the app opts in to use the Guard. /// @param guard The address of the Guard module. function setDefaultGuard(address guard) external onlyOwner { @@ -87,8 +86,7 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli /// @param message The message to be sent. /// @return desc The descriptor of the sent transaction: /// - transactionId: the ID of the transaction that was sent. - /// - dbNonce: the database nonce of the batch containing the written entry for transaction. - /// - entryIndex: the index of the written entry for transaction within the batch. + /// - dbNonce: the database nonce of the entry containing the transaction. function interchainSend( uint64 dstChainId, bytes32 receiver, @@ -122,25 +120,17 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli } /// @notice Executes a transaction that has been sent via the Interchain Communication Protocol. - /// Note: The transaction must be proven to be included in one of the InterchainDB batches. + /// Note: The transaction must be proven to be included in one of the InterchainDB entries. /// Note: Transaction data includes the requested gas limit, but the executors could specify a different gas limit. /// If the specified gas limit is lower than requested, the requested gas limit will be used. /// Otherwise, the specified gas limit will be used. /// This allows to execute the transactions with requested gas limit set too low. /// @param gasLimit The gas limit to use for the execution. /// @param transaction The transaction data. - /// @param proof The Merkle proof for transaction execution, fetched from the source chain. - function interchainExecute( - uint256 gasLimit, - bytes calldata transaction, - bytes32[] calldata proof - ) - external - payable - { + function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable { InterchainTransaction memory icTx = _assertCorrectTransaction(transaction); bytes32 transactionId = keccak256(transaction); - _assertExecutable(icTx, transactionId, proof); + _assertExecutable(icTx, transactionId); _txExecutor[transactionId] = msg.sender; OptionsV1 memory decodedOptions = icTx.options.decodeOptionsV1(); @@ -160,45 +150,46 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli srcChainId: icTx.srcChainId, sender: icTx.srcSender, dbNonce: icTx.dbNonce, - entryIndex: icTx.entryIndex, message: icTx.message }); - emit InterchainTransactionReceived( - transactionId, icTx.dbNonce, icTx.entryIndex, icTx.srcChainId, icTx.srcSender, icTx.dstReceiver - ); + emit InterchainTransactionReceived({ + transactionId: transactionId, + dbNonce: icTx.dbNonce, + srcChainId: icTx.srcChainId, + srcSender: icTx.srcSender, + dstReceiver: icTx.dstReceiver + }); } /// @notice Writes the proof of execution for a transaction into the InterchainDB. /// @dev Will revert if the transaction has not been executed. /// @param transactionId The ID of the transaction to write the proof for. - /// @return dbNonce The database nonce of the batch containing the written proof for transaction. - /// @return entryIndex The index of the written proof for transaction within the batch. - function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce, uint64 entryIndex) { + /// @return dbNonce The database nonce of the entry containing the written proof for transaction. + function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce) { address executor = _txExecutor[transactionId]; if (executor == address(0)) { revert InterchainClientV1__TxNotExecuted(transactionId); } bytes memory proof = abi.encode(transactionId, executor); - (dbNonce, entryIndex) = IInterchainDB(INTERCHAIN_DB).writeEntry(keccak256(proof)); - emit ExecutionProofWritten(transactionId, dbNonce, entryIndex, executor); + dbNonce = IInterchainDB(INTERCHAIN_DB).writeEntry(keccak256(proof)); + emit ExecutionProofWritten({transactionId: transactionId, dbNonce: dbNonce, executor: executor}); } // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ /// @notice Determines if a transaction meets the criteria to be executed based on: - /// - If approved modules have verified the batch in the InterchainDB + /// - If approved modules have verified the entry in the InterchainDB /// - If the threshold of approved modules have been met /// - If the optimistic window has passed for all modules - /// - If the Guard module (if opted in) has not submitted a batch that conflicts with the approved modules + /// - If the Guard module (if opted in) has not submitted an entry that conflicts with the approved modules /// @dev Will revert with a specific error message if the transaction is not executable. /// @param encodedTx The encoded transaction to check for executable status. - /// @param proof The Merkle proof for the transaction, fetched from the source chain. - function isExecutable(bytes calldata encodedTx, bytes32[] calldata proof) external view returns (bool) { + function isExecutable(bytes calldata encodedTx) external view returns (bool) { InterchainTransaction memory icTx = _assertCorrectTransaction(encodedTx); // Check that options could be decoded icTx.options.decodeOptionsV1(); bytes32 transactionId = keccak256(encodedTx); - _assertExecutable(icTx, transactionId, proof); + _assertExecutable(icTx, transactionId); return true; } @@ -207,10 +198,10 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli /// - Ready: the transaction is ready to be executed. /// - AlreadyExecuted: the transaction has already been executed. /// - `firstArg` is the transaction ID. - /// - BatchAwaitingResponses: not enough responses have been received for the transaction. + /// - EntryAwaitingResponses: not enough responses have been received for the transaction. /// - `firstArg` is the number of responses received. /// - `secondArg` is the number of responses required. - /// - BatchConflict: one of the modules have submitted a conflicting batch. + /// - EntryConflict: one of the modules have submitted a conflicting entry. /// - `firstArg` is the address of the module. /// - This is either one of the modules that the app trusts, or the Guard module used by the app. /// - ReceiverNotICApp: the receiver is not an Interchain app. @@ -222,16 +213,13 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli /// /// Note: the arguments are abi-encoded bytes32 values (as their types could be different). // solhint-disable-next-line code-complexity - function getTxReadinessV1( - InterchainTransaction memory icTx, - bytes32[] calldata proof - ) + function getTxReadinessV1(InterchainTransaction memory icTx) external view returns (TxReadiness status, bytes32 firstArg, bytes32 secondArg) { bytes memory encodedTx = encodeTransaction(icTx); - try this.isExecutable(encodedTx, proof) returns (bool) { + try this.isExecutable(encodedTx) returns (bool) { return (TxReadiness.Ready, 0, 0); } catch (bytes memory errorData) { bytes4 selector; @@ -239,9 +227,9 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli if (selector == InterchainClientV1__TxAlreadyExecuted.selector) { status = TxReadiness.AlreadyExecuted; } else if (selector == InterchainClientV1__ResponsesAmountBelowMin.selector) { - status = TxReadiness.BatchAwaitingResponses; - } else if (selector == InterchainClientV1__BatchConflict.selector) { - status = TxReadiness.BatchConflict; + status = TxReadiness.EntryAwaitingResponses; + } else if (selector == InterchainClientV1__EntryConflict.selector) { + status = TxReadiness.EntryConflict; } else if (selector == InterchainClientV1__ReceiverNotICApp.selector) { status = TxReadiness.ReceiverNotICApp; } else if (selector == InterchainClientV1__ReceiverZeroRequiredResponses.selector) { @@ -381,23 +369,22 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli if (msg.value < verificationFee) { revert InterchainClientV1__FeeAmountBelowMin(msg.value, verificationFee); } - (desc.dbNonce, desc.entryIndex) = IInterchainDB(INTERCHAIN_DB).getNextEntryIndex(); + desc.dbNonce = IInterchainDB(INTERCHAIN_DB).getDBNonce(); InterchainTransaction memory icTx = InterchainTransactionLib.constructLocalTransaction({ srcSender: msg.sender, dstReceiver: receiver, dstChainId: dstChainId, dbNonce: desc.dbNonce, - entryIndex: desc.entryIndex, options: options, message: message }); desc.transactionId = keccak256(encodeTransaction(icTx)); // Sanity check: nonce returned from DB should match the nonce used to construct the transaction { - (uint64 dbNonce, uint64 entryIndex) = IInterchainDB(INTERCHAIN_DB).writeEntryWithVerification{ - value: verificationFee - }(icTx.dstChainId, desc.transactionId, srcModules); - assert(dbNonce == desc.dbNonce && entryIndex == desc.entryIndex); + uint64 dbNonce = IInterchainDB(INTERCHAIN_DB).writeEntryRequestVerification{value: verificationFee}( + icTx.dstChainId, desc.transactionId, srcModules + ); + assert(dbNonce == desc.dbNonce); } uint256 executionFee; unchecked { @@ -409,45 +396,32 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli transactionId: desc.transactionId, options: options }); - emit InterchainTransactionSent( - desc.transactionId, - icTx.dbNonce, - icTx.entryIndex, - icTx.dstChainId, - icTx.srcSender, - icTx.dstReceiver, - verificationFee, - executionFee, - icTx.options, - icTx.message - ); + emit InterchainTransactionSent({ + transactionId: desc.transactionId, + dbNonce: desc.dbNonce, + dstChainId: icTx.dstChainId, + srcSender: icTx.srcSender, + dstReceiver: icTx.dstReceiver, + verificationFee: verificationFee, + executionFee: executionFee, + options: icTx.options, + message: icTx.message + }); } // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════ /// @dev Asserts that the transaction is executable. - function _assertExecutable( - InterchainTransaction memory icTx, - bytes32 transactionId, - bytes32[] calldata proof - ) - internal - view - { + function _assertExecutable(InterchainTransaction memory icTx, bytes32 transactionId) internal view { bytes32 linkedClient = _assertLinkedClient(icTx.srcChainId); if (_txExecutor[transactionId] != address(0)) { revert InterchainClientV1__TxAlreadyExecuted(transactionId); } - // Construct expected batch based on interchain transaction data - InterchainBatch memory batch = InterchainBatch({ + // Construct expected entry based on interchain transaction data + InterchainEntry memory entry = InterchainEntry({ srcChainId: icTx.srcChainId, dbNonce: icTx.dbNonce, - batchRoot: BatchingV1Lib.getBatchRoot({ - srcWriter: linkedClient, - dataHash: transactionId, - entryIndex: icTx.entryIndex, - proof: proof - }) + entryValue: InterchainEntryLib.getEntryValue({srcWriter: linkedClient, digest: transactionId}) }); address receiver = icTx.dstReceiver.bytes32ToAddress(); (AppConfigV1 memory appConfig, address[] memory approvedModules) = getAppReceivingConfigV1(receiver); @@ -455,8 +429,8 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli revert InterchainClientV1__ReceiverZeroRequiredResponses(receiver); } // Verify against the Guard if the app opts in to use it - _assertNoGuardConflict(_getGuard(appConfig), batch); - uint256 finalizedResponses = _getFinalizedResponsesCount(approvedModules, batch, appConfig.optimisticPeriod); + _assertNoGuardConflict(_getGuard(appConfig), entry); + uint256 finalizedResponses = _getFinalizedResponsesCount(approvedModules, entry, appConfig.optimisticPeriod); if (finalizedResponses < appConfig.requiredResponses) { revert InterchainClientV1__ResponsesAmountBelowMin(finalizedResponses, appConfig.requiredResponses); } @@ -473,12 +447,12 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli } } - /// @dev Asserts that the Guard has not submitted a conflicting batch. - function _assertNoGuardConflict(address guard, InterchainBatch memory batch) internal view { + /// @dev Asserts that the Guard has not submitted a conflicting entry. + function _assertNoGuardConflict(address guard, InterchainEntry memory entry) internal view { if (guard != address(0)) { - uint256 confirmedAt = IInterchainDB(INTERCHAIN_DB).checkBatchVerification(guard, batch); - if (confirmedAt == BATCH_CONFLICT) { - revert InterchainClientV1__BatchConflict(guard); + uint256 confirmedAt = IInterchainDB(INTERCHAIN_DB).checkEntryVerification(guard, entry); + if (confirmedAt == ENTRY_CONFLICT) { + revert InterchainClientV1__EntryConflict(guard); } } } @@ -494,11 +468,11 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli return appConfig.guard; } - /// @dev Counts the number of finalized responses for the given batch. - /// Note: Reverts if a conflicting batch has been verified by any of the approved modules. + /// @dev Counts the number of finalized responses for the given entry. + /// Note: Reverts if a conflicting entry has been verified by any of the approved modules. function _getFinalizedResponsesCount( address[] memory approvedModules, - InterchainBatch memory batch, + InterchainEntry memory entry, uint256 optimisticPeriod ) internal @@ -507,16 +481,16 @@ contract InterchainClientV1 is Ownable, InterchainClientV1Events, IInterchainCli { for (uint256 i = 0; i < approvedModules.length; ++i) { address module = approvedModules[i]; - uint256 confirmedAt = IInterchainDB(INTERCHAIN_DB).checkBatchVerification(module, batch); - // No-op if the module has not verified anything with the same batch key - if (confirmedAt == BATCH_UNVERIFIED) { + uint256 confirmedAt = IInterchainDB(INTERCHAIN_DB).checkEntryVerification(module, entry); + // No-op if the module has not verified anything with the same entry key + if (confirmedAt == ENTRY_UNVERIFIED) { continue; } - // Revert if the module has verified a conflicting batch with the same batch key - if (confirmedAt == BATCH_CONFLICT) { - revert InterchainClientV1__BatchConflict(module); + // Revert if the module has verified a conflicting entry with the same entry key + if (confirmedAt == ENTRY_CONFLICT) { + revert InterchainClientV1__EntryConflict(module); } - // The module has verified this exact batch, check if optimistic period has passed + // The module has verified this exact entry, check if optimistic period has passed if (confirmedAt + optimisticPeriod < block.timestamp) { unchecked { ++finalizedResponses; diff --git a/packages/contracts-communication/contracts/InterchainDB.sol b/packages/contracts-communication/contracts/InterchainDB.sol index 47797017d6..41d02adad1 100644 --- a/packages/contracts-communication/contracts/InterchainDB.sol +++ b/packages/contracts-communication/contracts/InterchainDB.sol @@ -5,33 +5,31 @@ import {InterchainDBEvents} from "./events/InterchainDBEvents.sol"; import {IInterchainDB} from "./interfaces/IInterchainDB.sol"; import {IInterchainModule} from "./interfaces/IInterchainModule.sol"; -import {BatchingV1Lib} from "./libs/BatchingV1.sol"; import { - InterchainBatch, InterchainBatchLib, BatchKey, BATCH_UNVERIFIED, BATCH_CONFLICT -} from "./libs/InterchainBatch.sol"; -import {InterchainEntry, InterchainEntryLib} from "./libs/InterchainEntry.sol"; + InterchainEntry, InterchainEntryLib, EntryKey, ENTRY_UNVERIFIED, ENTRY_CONFLICT +} from "./libs/InterchainEntry.sol"; import {VersionedPayloadLib} from "./libs/VersionedPayload.sol"; import {TypeCasts} from "./libs/TypeCasts.sol"; contract InterchainDB is InterchainDBEvents, IInterchainDB { using VersionedPayloadLib for bytes; - /// @notice Struct representing a batch of entries from the remote Interchain DataBase, + /// @notice Struct representing an entry from the remote Interchain DataBase, /// verified by the Interchain Module. /// @param verifiedAt The block timestamp at which the entry was verified by the module - /// @param batchRoot The Merkle root of the batch - struct RemoteBatch { + /// @param entryValue The value of the entry: srcWriter + digest hashed together + struct RemoteEntry { uint256 verifiedAt; - bytes32 batchRoot; + bytes32 entryValue; } - /// @notice The version of the Interchain DataBase. Must match the version of the batches. + /// @notice The version of the Interchain DataBase. Must match the version of the entries. uint16 public constant DB_VERSION = 1; /// @dev The entry values written on the local chain. bytes32[] internal _entryValues; - /// @dev The remote batches verified by the modules. - mapping(address module => mapping(BatchKey batchKey => RemoteBatch batch)) internal _remoteBatches; + /// @dev The remote entries verified by the modules. + mapping(address module => mapping(EntryKey entryKey => RemoteEntry entry)) internal _remoteEntries; /// @dev Checks if the chain id is not the same as the local chain id. modifier onlyRemoteChainId(uint64 chainId) { @@ -43,28 +41,26 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB { // ═══════════════════════════════════════════════ WRITER-FACING ═══════════════════════════════════════════════════ - /// @notice Write data to the Interchain DataBase as a new entry in the current batch. + /// @notice Write a data digest to the Interchain DataBase as a new entry. /// Note: there are no guarantees that this entry will be available for reading on any of the remote chains. - /// Use `requestBatchVerification` to ensure that the entry is available for reading on the destination chain. - /// @param dataHash The hash of the data to be written to the Interchain DataBase as a new entry - /// @return dbNonce The database nonce of the batch containing the written entry - /// @return entryIndex The index of the written entry within the batch - function writeEntry(bytes32 dataHash) external returns (uint64 dbNonce, uint64 entryIndex) { - InterchainEntry memory entry = _writeEntry(dataHash); - (dbNonce, entryIndex) = (entry.dbNonce, entry.entryIndex); + /// Use `requestEntryVerification` to ensure that the entry is available for reading on the destination chain. + /// @param digest The digest of the data to be written to the Interchain DataBase + /// @return dbNonce The database nonce of the entry + function writeEntry(bytes32 digest) external returns (uint64 dbNonce) { + InterchainEntry memory entry = _writeEntry(digest); + dbNonce = entry.dbNonce; } - /// @notice Request the given Interchain Modules to verify an existing batch. - /// If the batch is not finalized, the module will verify it after finalization. - /// For the finalized batch the batch root is already available, and the module can verify it immediately. + /// @notice Request the given Interchain Modules to verify an existing entry. /// Note: every module has a separate fee paid in the native gas token of the source chain, /// and `msg.value` must be equal to the sum of all fees. - /// Note: this method is permissionless, and anyone can request verification for any batch. - /// @dev Will revert if the batch with the given nonce does not exist. + /// Note: this method is permissionless, and anyone can request verification for any entry. + /// Note: will request the verification of an empty entry, if the entry with the given nonce does not exist. + /// This could be useful for providing the proof of non-existence of the entry. /// @param dstChainId The chain id of the destination chain - /// @param dbNonce The database nonce of the existing batch + /// @param dbNonce The database nonce of the existing entry /// @param srcModules The source chain addresses of the Interchain Modules to use for verification - function requestBatchVerification( + function requestEntryVerification( uint64 dstChainId, uint64 dbNonce, address[] calldata srcModules @@ -73,225 +69,132 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB { payable onlyRemoteChainId(dstChainId) { - InterchainBatch memory batch = getBatch(dbNonce); - _requestVerification(dstChainId, batch, srcModules); + InterchainEntry memory entry = getEntry(dbNonce); + _requestVerification(dstChainId, entry, srcModules); } - /// @notice Write data to the Interchain DataBase as a new entry in the current batch. - /// Then request the Interchain Modules to verify the batch containing the written entry on the destination chain. - /// See `writeEntry` and `requestBatchVerification` for more details. + /// @notice Write a data digest to the Interchain DataBase as a new entry. + /// Then request the Interchain Modules to verify the entry on the destination chain. + /// See `writeEntry` and `requestEntryVerification` for more details. /// @dev Will revert if the empty array of modules is provided. /// @param dstChainId The chain id of the destination chain - /// @param dataHash The hash of the data to be written to the Interchain DataBase as a new entry + /// @param digest The digest of the data to be written to the Interchain DataBase /// @param srcModules The source chain addresses of the Interchain Modules to use for verification - /// @return dbNonce The database nonce of the batch containing the written entry - /// @return entryIndex The index of the written entry within the batch - function writeEntryWithVerification( + /// @return dbNonce The database nonce of the entry + function writeEntryRequestVerification( uint64 dstChainId, - bytes32 dataHash, + bytes32 digest, address[] calldata srcModules ) external payable onlyRemoteChainId(dstChainId) - returns (uint64 dbNonce, uint64 entryIndex) + returns (uint64 dbNonce) { - InterchainEntry memory entry = _writeEntry(dataHash); - (dbNonce, entryIndex) = (entry.dbNonce, entry.entryIndex); - // In "no batching" mode: the batch root is the same as the entry value - InterchainBatch memory batch = InterchainBatchLib.constructLocalBatch(dbNonce, entry.entryValue()); - _requestVerification(dstChainId, batch, srcModules); + InterchainEntry memory entry = _writeEntry(digest); + _requestVerification(dstChainId, entry, srcModules); + return entry.dbNonce; } // ═══════════════════════════════════════════════ MODULE-FACING ═══════════════════════════════════════════════════ - /// @notice Allows the Interchain Module to verify the batch coming from the remote chain. - /// The module SHOULD verify the exact finalized batch from the remote chain. If the batch with a given nonce - /// is not finalized or does not exist, module CAN verify it with an empty root value. Once the batch is - /// finalized, the module SHOULD re-verify the batch with the correct root value. - /// Note: The DB will only accept the batch of the same version as the DB itself. - /// @dev Will revert if the batch with the same nonce but a different non-empty root is already verified. - /// @param versionedBatch The versioned Interchain Batch to verify - function verifyRemoteBatch(bytes calldata versionedBatch) external { - InterchainBatch memory batch = _assertCorrectBatch(versionedBatch); - BatchKey batchKey = InterchainBatchLib.encodeBatchKey({srcChainId: batch.srcChainId, dbNonce: batch.dbNonce}); - RemoteBatch memory existingBatch = _remoteBatches[msg.sender][batchKey]; - // Check if that's the first time module verifies the batch - if (existingBatch.verifiedAt == 0) { - _saveVerifiedBatch(msg.sender, batchKey, batch); + /// @notice Allows the Interchain Module to verify the entry coming from the remote chain. + /// The module SHOULD verify the exact finalized entry from the remote chain. If the entry with a given nonce + /// does not exist, module CAN verify it with an empty entry value. + /// Once the entry exists, the module SHOULD re-verify the entry with the correct entry value. + /// Note: The DB will only accept the entry of the same version as the DB itself. + /// @dev Will revert if the entry with the same nonce but a different non-empty entry value is already verified. + /// @param encodedEntry The versioned Interchain Entry to verify + function verifyRemoteEntry(bytes calldata encodedEntry) external { + InterchainEntry memory entry = _assertCorrectEntry(encodedEntry); + EntryKey entryKey = InterchainEntryLib.encodeEntryKey({srcChainId: entry.srcChainId, dbNonce: entry.dbNonce}); + RemoteEntry memory existingEntry = _remoteEntries[msg.sender][entryKey]; + // Check if that's the first time module verifies the entry + if (existingEntry.verifiedAt == 0) { + _saveVerifiedEntry(msg.sender, entryKey, entry); return; } - // No-op if the batch root is the same - if (existingBatch.batchRoot == batch.batchRoot) { + // No-op if the entry value is the same + if (existingEntry.entryValue == entry.entryValue) { return; } - // Overwriting an empty (non-existent) batch with a different one is allowed - if (existingBatch.batchRoot == 0) { - _saveVerifiedBatch(msg.sender, batchKey, batch); + // Overwriting an empty (non-existent) entry with a different one is allowed + if (existingEntry.entryValue == 0) { + _saveVerifiedEntry(msg.sender, entryKey, entry); return; } - // Overwriting an existing batch with a different one is not allowed - revert InterchainDB__BatchConflict(msg.sender, existingBatch.batchRoot, batch); + // Overwriting an existing entry with a different one is not allowed + revert InterchainDB__EntryConflict(msg.sender, entry); } // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ - /// @notice Returns the list of leafs of the finalized batch with the given nonce. - /// Note: the leafs are ordered by the index of the written entry in the current batch, - /// and the leafs value match the value of the written entry (srcWriter + dataHash hashed together). - /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. - /// @param dbNonce The database nonce of the finalized batch - function getBatchLeafs(uint64 dbNonce) external view returns (bytes32[] memory leafs) { - uint256 batchSize = getBatchSize(dbNonce); - leafs = new bytes32[](batchSize); - for (uint64 i = 0; i < batchSize; ++i) { - leafs[i] = getEntryValue(dbNonce, i); - } - } - - /// @notice Returns the list of leafs of the finalized batch with the given nonce, - /// paginated by the given start and end indexes. The end index is exclusive. - /// Note: this is useful when the batch contains a large number of leafs, and calling `getBatchLeafs` - /// would result in a gas limit exceeded error. - /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. - /// Will revert if the provided range is invalid. - /// @param dbNonce The database nonce of the finalized batch - /// @param start The start index of the paginated leafs, inclusive - /// @param end The end index of the paginated leafs, exclusive - function getBatchLeafsPaginated( - uint64 dbNonce, - uint64 start, - uint64 end - ) - external - view - returns (bytes32[] memory leafs) - { - uint256 size = getBatchSize(dbNonce); - if (start > end || end > size) { - revert InterchainDB__EntryRangeInvalid(dbNonce, start, end); - } - leafs = new bytes32[](end - start); - for (uint64 i = start; i < end; ++i) { - leafs[i - start] = getEntryValue(dbNonce, i); - } - } - - /// @notice Get the Merkle proof of inclusion for the entry with the given index - /// in the finalized batch with the given nonce. - /// @dev Will revert if the batch with the given nonce does not exist, or is not finalized. - /// Will revert if the entry with the given index does not exist within the batch. - /// @param dbNonce The database nonce of the finalized batch - /// @param entryIndex The index of the written entry within the batch - /// @return proof The Merkle proof of inclusion for the entry - function getEntryProof(uint64 dbNonce, uint64 entryIndex) external view returns (bytes32[] memory proof) { - // In "no batching" mode: the batch root is the same as the entry value, hence the proof is empty - _assertEntryExists(dbNonce, entryIndex); - return new bytes32[](0); - } - /// @notice Get the fee for writing data to the Interchain DataBase, and verifying it on the destination chain /// using the provided Interchain Modules. /// @dev Will revert if the empty array of modules is provided. /// @param dstChainId The chain id of the destination chain /// @param srcModules The source chain addresses of the Interchain Modules to use for verification function getInterchainFee(uint64 dstChainId, address[] calldata srcModules) external view returns (uint256 fee) { - (, fee) = _getModuleFees(dstChainId, getDBNonce(), srcModules); + (, fee) = _getModuleFees(dstChainId, srcModules); } - /// @notice Get the index of the next entry to be written to the database. - /// @return dbNonce The database nonce of the batch including the next entry - /// @return entryIndex The index of the next entry within that batch - function getNextEntryIndex() external view returns (uint64 dbNonce, uint64 entryIndex) { - // In "no batching" mode: entry index is 0, batch size is 1 - dbNonce = getDBNonce(); - entryIndex = 0; - } - - /// @notice Check if the batch is verified by the Interchain Module on the destination chain. - /// - returned value `BATCH_UNVERIFIED` indicates that the module has not verified the batch. - /// - returned value `BATCH_CONFLICT` indicates that the module has verified a different batch root - /// for the same batch key. + /// @notice Check if the entry is verified by the Interchain Module on the destination chain. + /// - returned value `ENTRY_UNVERIFIED` indicates that the module has not verified the entry. + /// - returned value `ENTRY_CONFLICT` indicates that the module has verified a different entry value + /// for the same entry key. /// @param dstModule The destination chain addresses of the Interchain Modules to use for verification - /// @param batch The Interchain Batch to check - /// @return moduleVerifiedAt The block timestamp at which the batch was verified by the module, - /// BATCH_UNVERIFIED if the module has not verified the batch, - /// BATCH_CONFLICT if the module has verified a different batch root for the same batch key. - function checkBatchVerification( + /// @param entry The Interchain Entry to check + /// @return moduleVerifiedAt The block timestamp at which the entry was verified by the module, + /// ENTRY_UNVERIFIED if the module has not verified the entry, + /// ENTRY_CONFLICT if the module has verified a different entry value for the same entry key. + function checkEntryVerification( address dstModule, - InterchainBatch memory batch + InterchainEntry memory entry ) external view - onlyRemoteChainId(batch.srcChainId) + onlyRemoteChainId(entry.srcChainId) returns (uint256 moduleVerifiedAt) { - BatchKey batchKey = InterchainBatchLib.encodeBatchKey({srcChainId: batch.srcChainId, dbNonce: batch.dbNonce}); - RemoteBatch memory remoteBatch = _remoteBatches[dstModule][batchKey]; - // Check if module verified anything for this batch key first - if (remoteBatch.verifiedAt == 0) { - return BATCH_UNVERIFIED; + EntryKey entryKey = InterchainEntryLib.encodeEntryKey({srcChainId: entry.srcChainId, dbNonce: entry.dbNonce}); + RemoteEntry memory remoteEntry = _remoteEntries[dstModule][entryKey]; + // Check if module verified anything for this entry key first + if (remoteEntry.verifiedAt == 0) { + return ENTRY_UNVERIFIED; } - // Check if the batch root matches the one verified by the module - return remoteBatch.batchRoot == batch.batchRoot ? remoteBatch.verifiedAt : BATCH_CONFLICT; + // Check if the entry value matches the one verified by the module + return remoteEntry.entryValue == entry.entryValue ? remoteEntry.verifiedAt : ENTRY_CONFLICT; } - /// @notice Get the versioned Interchain Batch with the given nonce. - /// Note: will return a batch with an empty root if the batch does not exist, or is not finalized. - /// @param dbNonce The database nonce of the batch - function getVersionedBatch(uint64 dbNonce) external view returns (bytes memory versionedBatch) { - InterchainBatch memory batch = getBatch(dbNonce); + /// @notice Get the versioned Interchain Entry with the given nonce. + /// Note: will return an entry with an empty value if the entry does not exist. + /// @param dbNonce The database nonce of the entry + function getEncodedEntry(uint64 dbNonce) external view returns (bytes memory) { + InterchainEntry memory entry = getEntry(dbNonce); return VersionedPayloadLib.encodeVersionedPayload({ version: DB_VERSION, - payload: InterchainBatchLib.encodeBatch(batch) + payload: InterchainEntryLib.encodeEntry(entry) }); } - /// @notice Get the batch root containing the Interchain Entry with the given index. - /// @param entry The Interchain Entry to get the batch root for - /// @param proof The Merkle proof of inclusion for the entry in the batch - function getBatchRoot(InterchainEntry memory entry, bytes32[] calldata proof) external pure returns (bytes32) { - return BatchingV1Lib.getBatchRoot({ - srcWriter: entry.srcWriter, - dataHash: entry.dataHash, - entryIndex: entry.entryIndex, - proof: proof - }); - } - - /// @notice Returns the size of the finalized batch with the given nonce. - /// @dev Will return 0 for non-existent or non-finalized batches. - /// @param dbNonce The database nonce of the finalized batch - function getBatchSize(uint64 dbNonce) public view returns (uint64) { - // In "no batching" mode: the finalized batch size is 1, the pending batch size is 0 - // We also return 0 for non-existent batches - return dbNonce < getDBNonce() ? 1 : 0; - } - - /// @notice Get the finalized Interchain Batch with the given nonce. - /// @dev Will return a batch with an empty root if the batch does not exist, or is not finalized. - /// @param dbNonce The database nonce of the finalized batch - function getBatch(uint64 dbNonce) public view returns (InterchainBatch memory) { - // In "no batching" mode: the batch root is the same as the entry hash. - // For non-finalized or non-existent batches, the batch root is 0. - bytes32 batchRoot = dbNonce < getDBNonce() ? getEntryValue(dbNonce, 0) : bytes32(0); - return InterchainBatchLib.constructLocalBatch(dbNonce, batchRoot); + /// @notice Get the Interchain Entry with the given nonce written on the local chain. + /// @dev Will return an entry with an empty value if the entry does not exist. + /// @param dbNonce The database nonce of the entry + function getEntry(uint64 dbNonce) public view returns (InterchainEntry memory) { + return InterchainEntryLib.constructLocalEntry({dbNonce: dbNonce, entryValue: getEntryValue(dbNonce)}); } - /// @notice Get the Interchain Entry's value written on the local chain with the given batch nonce and entry index. + /// @notice Get the Interchain Entry's value written on the local chain with the given nonce. /// Entry value is calculated as the hash of the writer address and the written data hash. - /// Note: the batch does not have to be finalized to fetch the entry value. - /// @dev Will revert if the batch with the given nonce does not exist, - /// or the entry with the given index does not exist within the batch. - /// @param dbNonce The database nonce of the existing batch - /// @param entryIndex The index of the written entry within the batch - function getEntryValue(uint64 dbNonce, uint64 entryIndex) public view returns (bytes32) { - _assertEntryExists(dbNonce, entryIndex); - return _entryValues[dbNonce]; + /// @dev Will return an empty value if the entry does not exist. + /// @param dbNonce The database nonce of the entry + function getEntryValue(uint64 dbNonce) public view returns (bytes32) { + // For non-existent entries, the value is zero + return dbNonce < getDBNonce() ? _entryValues[dbNonce] : bytes32(0); } - /// @notice Get the nonce of the database, which is incremented every time a new batch is finalized. - /// This is the nonce of the current non-finalized batch. + /// @notice Get the nonce of the database, which is incremented every time a new entry is written. + /// This is the nonce of the next entry to be written. function getDBNonce() public view returns (uint64) { // We can do the unsafe cast here as writing more than 2^64 entries is practically impossible return uint64(_entryValues.length); @@ -300,36 +203,25 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB { // ══════════════════════════════════════════════ INTERNAL LOGIC ═══════════════════════════════════════════════════ /// @dev Write the entry to the database and emit the event. - function _writeEntry(bytes32 dataHash) internal returns (InterchainEntry memory entry) { + function _writeEntry(bytes32 digest) internal returns (InterchainEntry memory entry) { uint64 dbNonce = getDBNonce(); - entry = InterchainEntryLib.constructLocalEntry({ - dbNonce: dbNonce, - entryIndex: 0, - writer: msg.sender, - dataHash: dataHash - }); - bytes32 entryValue = entry.entryValue(); + bytes32 srcWriter = TypeCasts.addressToBytes32(msg.sender); + bytes32 entryValue = InterchainEntryLib.getEntryValue({srcWriter: msg.sender, digest: digest}); _entryValues.push(entryValue); - emit InterchainEntryWritten({ - dbNonce: dbNonce, - entryIndex: 0, - srcWriter: TypeCasts.addressToBytes32(msg.sender), - dataHash: dataHash - }); - // In the InterchainDB V1 the batch is finalized immediately after the entry is written - emit InterchainBatchFinalized({dbNonce: dbNonce, batchRoot: entryValue}); + entry = InterchainEntryLib.constructLocalEntry({dbNonce: dbNonce, entryValue: entryValue}); + emit InterchainEntryWritten({dbNonce: dbNonce, srcWriter: srcWriter, digest: digest, entryValue: entryValue}); } /// @dev Request the verification of the entry by the modules, and emit the event. /// Note: the validity of the passed entry and chain id being remote is enforced in the calling function. function _requestVerification( uint64 dstChainId, - InterchainBatch memory batch, + InterchainEntry memory entry, address[] calldata srcModules ) internal { - (uint256[] memory fees, uint256 totalFee) = _getModuleFees(dstChainId, batch.dbNonce, srcModules); + (uint256[] memory fees, uint256 totalFee) = _getModuleFees(dstChainId, srcModules); if (msg.value < totalFee) { revert InterchainDB__FeeAmountBelowMin(msg.value, totalFee); } else if (msg.value > totalFee) { @@ -337,52 +229,40 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB { fees[0] += msg.value - totalFee; } uint256 len = srcModules.length; - bytes memory versionedBatch = VersionedPayloadLib.encodeVersionedPayload({ + bytes memory versionedEntry = VersionedPayloadLib.encodeVersionedPayload({ version: DB_VERSION, - payload: InterchainBatchLib.encodeBatch(batch) + payload: InterchainEntryLib.encodeEntry(entry) }); for (uint256 i = 0; i < len; ++i) { - IInterchainModule(srcModules[i]).requestBatchVerification{value: fees[i]}( - dstChainId, batch.dbNonce, versionedBatch - ); + IInterchainModule(srcModules[i]).requestEntryVerification{value: fees[i]}(dstChainId, versionedEntry); } - emit InterchainBatchVerificationRequested(dstChainId, batch.dbNonce, batch.batchRoot, srcModules); + emit InterchainEntryVerificationRequested(dstChainId, entry.dbNonce, srcModules); } - /// @dev Save the verified batch to the database and emit the event. - function _saveVerifiedBatch(address module, BatchKey batchKey, InterchainBatch memory batch) internal { - _remoteBatches[module][batchKey] = RemoteBatch({verifiedAt: block.timestamp, batchRoot: batch.batchRoot}); - emit InterchainBatchVerified(module, batch.srcChainId, batch.dbNonce, batch.batchRoot); + /// @dev Save the verified entry to the database and emit the event. + function _saveVerifiedEntry(address module, EntryKey entryKey, InterchainEntry memory entry) internal { + _remoteEntries[module][entryKey] = RemoteEntry({verifiedAt: block.timestamp, entryValue: entry.entryValue}); + emit InterchainEntryVerified(module, entry.srcChainId, entry.dbNonce, entry.entryValue); } // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════ - /// @dev Asserts that the batch version is correct and that batch originates from a remote chain. - /// Note: returns the decoded batch for chaining purposes. - function _assertCorrectBatch(bytes calldata versionedBatch) internal view returns (InterchainBatch memory batch) { - uint16 dbVersion = versionedBatch.getVersion(); + /// @dev Asserts that the entry version is correct and that entry originates from a remote chain. + /// Note: returns the decoded entry for chaining purposes. + function _assertCorrectEntry(bytes calldata versionedEntry) internal view returns (InterchainEntry memory entry) { + uint16 dbVersion = versionedEntry.getVersion(); if (dbVersion != DB_VERSION) { - revert InterchainDB__BatchVersionMismatch(dbVersion, DB_VERSION); - } - batch = InterchainBatchLib.decodeBatch(versionedBatch.getPayload()); - if (batch.srcChainId == block.chainid) { - revert InterchainDB__ChainIdNotRemote(batch.srcChainId); + revert InterchainDB__EntryVersionMismatch(dbVersion, DB_VERSION); } - } - - /// @dev Check that the entry index is within the batch size. Also checks that the batch exists. - function _assertEntryExists(uint64 dbNonce, uint64 entryIndex) internal view { - // This will revert if the batch does not exist - uint64 batchSize = getBatchSize(dbNonce); - if (entryIndex >= batchSize) { - revert InterchainDB__EntryIndexOutOfRange(dbNonce, entryIndex, batchSize); + entry = InterchainEntryLib.decodeEntry(versionedEntry.getPayload()); + if (entry.srcChainId == block.chainid) { + revert InterchainDB__ChainIdNotRemote(entry.srcChainId); } } /// @dev Get the verification fees for the modules function _getModuleFees( uint64 dstChainId, - uint64 dbNonce, address[] calldata srcModules ) internal @@ -395,7 +275,7 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB { } fees = new uint256[](len); for (uint256 i = 0; i < len; ++i) { - fees[i] = IInterchainModule(srcModules[i]).getModuleFee(dstChainId, dbNonce); + fees[i] = IInterchainModule(srcModules[i]).getModuleFee(dstChainId); totalFee += fees[i]; } } diff --git a/packages/contracts-communication/contracts/apps/AbstractICApp.sol b/packages/contracts-communication/contracts/apps/AbstractICApp.sol index 358c3d641a..4a12ed0251 100644 --- a/packages/contracts-communication/contracts/apps/AbstractICApp.sol +++ b/packages/contracts-communication/contracts/apps/AbstractICApp.sol @@ -25,19 +25,9 @@ abstract contract AbstractICApp is AbstractICAppEvents, IInterchainApp { /// @dev App is responsible for keeping track of interchain clients, and must verify the message sender. /// @param srcChainId Chain ID of the source chain, where the message was sent from. /// @param sender Sender address on the source chain, as a bytes32 value. - /// @param dbNonce The Interchain DB nonce of the batch containing the message entry. - /// @param entryIndex The index of the message entry within the batch. + /// @param dbNonce The Interchain DB nonce of the message entry. /// @param message The message being sent. - function appReceive( - uint64 srcChainId, - bytes32 sender, - uint64 dbNonce, - uint64 entryIndex, - bytes calldata message - ) - external - payable - { + function appReceive(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes calldata message) external payable { if (!_isInterchainClient(msg.sender)) { revert InterchainApp__CallerNotInterchainClient(msg.sender); } @@ -47,7 +37,7 @@ abstract contract AbstractICApp is AbstractICAppEvents, IInterchainApp { if (!_isAllowedSender(srcChainId, sender)) { revert InterchainApp__SrcSenderNotAllowed(srcChainId, sender); } - _receiveMessage(srcChainId, sender, dbNonce, entryIndex, message); + _receiveMessage(srcChainId, sender, dbNonce, message); } /// @notice Returns the verification configuration of the Interchain App. @@ -173,7 +163,6 @@ abstract contract AbstractICApp is AbstractICAppEvents, IInterchainApp { uint64 srcChainId, bytes32 sender, uint64 dbNonce, - uint64 entryIndex, bytes calldata message ) internal diff --git a/packages/contracts-communication/contracts/apps/examples/ExampleAppV1.sol b/packages/contracts-communication/contracts/apps/examples/ExampleAppV1.sol index 64b8a1cdd6..88eedbf139 100644 --- a/packages/contracts-communication/contracts/apps/examples/ExampleAppV1.sol +++ b/packages/contracts-communication/contracts/apps/examples/ExampleAppV1.sol @@ -9,8 +9,8 @@ import {OptionsV1} from "../../libs/Options.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; contract ExampleAppV1 is ICAppV1 { - event MessageReceived(uint64 srcChainId, bytes32 sender, uint64 dbNonce, uint64 entryIndex, bytes message); - event MessageSent(uint64 dstChainId, uint64 dbNonce, uint64 entryIndex, bytes32 transactionId); + event MessageReceived(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes message); + event MessageSent(uint64 dstChainId, uint64 dbNonce, bytes32 transactionId); constructor(address admin) ICAppV1(admin) { _grantRole(IC_GOVERNOR_ROLE, admin); @@ -37,7 +37,7 @@ contract ExampleAppV1 is ICAppV1 { options: OptionsV1({gasLimit: gasLimit, gasAirdrop: gasAirdrop}), message: message }); - emit MessageSent(dstChainId, desc.dbNonce, desc.entryIndex, desc.transactionId); + emit MessageSent(dstChainId, desc.dbNonce, desc.transactionId); } /// @notice Returns the fee required to send a message using `sendMessage`. @@ -59,12 +59,11 @@ contract ExampleAppV1 is ICAppV1 { uint64 srcChainId, bytes32 sender, uint64 dbNonce, - uint64 entryIndex, bytes calldata message ) internal override { - emit MessageReceived(srcChainId, sender, dbNonce, entryIndex, message); + emit MessageReceived(srcChainId, sender, dbNonce, message); } } diff --git a/packages/contracts-communication/contracts/apps/examples/PingPongApp.sol b/packages/contracts-communication/contracts/apps/examples/PingPongApp.sol index d159c78a44..f6c869b777 100644 --- a/packages/contracts-communication/contracts/apps/examples/PingPongApp.sol +++ b/packages/contracts-communication/contracts/apps/examples/PingPongApp.sol @@ -16,8 +16,8 @@ contract PingPongApp is ICAppV1 { event GasLimitSet(uint256 gasLimit); event PingDisrupted(uint256 counter); - event PingReceived(uint256 counter, uint64 dbNonce, uint64 entryIndex); - event PingSent(uint256 counter, uint64 dbNonce, uint64 entryIndex); + event PingReceived(uint256 counter, uint64 dbNonce); + event PingSent(uint256 counter, uint64 dbNonce); constructor(address admin) ICAppV1(admin) { _grantRole(IC_GOVERNOR_ROLE, admin); @@ -55,14 +55,13 @@ contract PingPongApp is ICAppV1 { uint64 srcChainId, bytes32, // sender uint64 dbNonce, - uint64 entryIndex, bytes calldata message ) internal override { uint256 counter = abi.decode(message, (uint256)); - emit PingReceived(counter, dbNonce, entryIndex); + emit PingReceived(counter, dbNonce); if (counter > 0) { // Don't revert if the balance is low, just stop sending messages. _sendPingPongMessage({dstChainId: srcChainId, counter: counter - 1, lowBalanceRevert: false}); @@ -81,7 +80,7 @@ contract PingPongApp is ICAppV1 { return; } InterchainTxDescriptor memory desc = _sendToLinkedApp(dstChainId, messageFee, options, message); - emit PingSent(counter, desc.dbNonce, desc.entryIndex); + emit PingSent(counter, desc.dbNonce); } /// @dev Sets the gas limit for the interchain messages. diff --git a/packages/contracts-communication/contracts/events/InterchainClientV1Events.sol b/packages/contracts-communication/contracts/events/InterchainClientV1Events.sol index d655e5b8c4..621c118558 100644 --- a/packages/contracts-communication/contracts/events/InterchainClientV1Events.sol +++ b/packages/contracts-communication/contracts/events/InterchainClientV1Events.sol @@ -14,19 +14,17 @@ abstract contract InterchainClientV1Events { /// @notice Emitted when a new interchain transaction is sent through the InterchainClientV1. /// The Receiver on the destination chain will receive the specified message once the transaction is executed. /// @param transactionId The unique identifier of the interchain transaction. - /// @param dbNonce The nonce of batch containing the transaction's DB entry. - /// @param entryIndex The index of the transaction's DB entry in the batch. + /// @param dbNonce The nonce of entry containing the transaction. /// @param dstChainId The chain ID of the destination chain. /// @param srcSender The sender of the transaction on the source chain. /// @param dstReceiver The receiver of the transaction on the destination chain. - /// @param verificationFee The fee paid to verify the batch on the destination chain. + /// @param verificationFee The fee paid to verify the entry on the destination chain. /// @param executionFee The fee paid to execute the transaction on the destination chain. /// @param options The execution options for the transaction. /// @param message The payload of the message being sent. event InterchainTransactionSent( bytes32 indexed transactionId, uint64 dbNonce, - uint64 entryIndex, uint64 dstChainId, bytes32 indexed srcSender, bytes32 indexed dstReceiver, @@ -39,15 +37,13 @@ abstract contract InterchainClientV1Events { /// @notice Emitted when an interchain transaction is received by the InterchainClientV1. /// The Receiver on the destination chain has just received the message sent from the source chain. /// @param transactionId The unique identifier of the interchain transaction. - /// @param dbNonce The nonce of batch containing the transaction's DB entry. - /// @param entryIndex The index of the transaction's DB entry in the batch. + /// @param dbNonce The nonce of entry containing the transaction. /// @param srcChainId The chain ID of the source chain. /// @param srcSender The sender of the transaction on the source chain. /// @param dstReceiver The receiver of the transaction on the destination chain. event InterchainTransactionReceived( bytes32 indexed transactionId, uint64 dbNonce, - uint64 entryIndex, uint64 srcChainId, bytes32 indexed srcSender, bytes32 indexed dstReceiver @@ -56,10 +52,7 @@ abstract contract InterchainClientV1Events { /// @notice Emitted when the proof of execution is written to InterchainDB. This allows the source chain /// to verify that the transaction was executed by a specific executor, if necessary. /// @param transactionId The unique identifier of the interchain transaction. - /// @param dbNonce The nonce of batch containing the written proof's DB entry. - /// @param entryIndex The index of the written proof's DB entry in the batch. + /// @param dbNonce The nonce of entry containing the transaction. /// @param executor The address of the executor that completed the transaction. - event ExecutionProofWritten( - bytes32 indexed transactionId, uint64 dbNonce, uint64 entryIndex, address indexed executor - ); + event ExecutionProofWritten(bytes32 indexed transactionId, uint64 dbNonce, address indexed executor); } diff --git a/packages/contracts-communication/contracts/events/InterchainDBEvents.sol b/packages/contracts-communication/contracts/events/InterchainDBEvents.sol index e9813d1357..1acf760712 100644 --- a/packages/contracts-communication/contracts/events/InterchainDBEvents.sol +++ b/packages/contracts-communication/contracts/events/InterchainDBEvents.sol @@ -3,35 +3,25 @@ pragma solidity ^0.8.0; abstract contract InterchainDBEvents { /// @notice Emitted when a local entry is written to the database. - /// @param dbNonce The nonce of the batch containing the entry. - /// @param entryIndex The index of the entry within the batch. - /// @param srcWriter The address of the writer. - /// @param dataHash The written data hash. - event InterchainEntryWritten( - uint64 indexed dbNonce, uint64 entryIndex, bytes32 indexed srcWriter, bytes32 dataHash - ); - - /// @notice Emitted when a local batch is finalized. - /// @param dbNonce The nonce of the finalized batch. - /// @param batchRoot The Merkle root hash of the finalized batch. - event InterchainBatchFinalized(uint64 indexed dbNonce, bytes32 batchRoot); + /// @param dbNonce The nonce of the written entry. + /// @param srcWriter The address of the entry writer. + /// @param digest The written data digest. + /// @param entryValue The value of the written entry: keccak256(abi.encode(srcWriter, digest)). + event InterchainEntryWritten(uint64 indexed dbNonce, bytes32 indexed srcWriter, bytes32 digest, bytes32 entryValue); - /// @notice Emitted when a remote batch is verified by the Interchain Module. - /// @param module The address of the Interchain Module that verified the batch. + /// @notice Emitted when a remote entry is verified by the Interchain Module. + /// @param module The address of the Interchain Module that verified the entry. /// @param srcChainId The ID of the source chain. - /// @param dbNonce The nonce of the verified batch. - /// @param batchRoot The Merkle root hash of the verified batch. - event InterchainBatchVerified( - address indexed module, uint64 indexed srcChainId, uint64 indexed dbNonce, bytes32 batchRoot + /// @param dbNonce The nonce of the verified entry. + /// @param entryValue The value of the verified entry: keccak256(abi.encode(srcWriter, digest)). + event InterchainEntryVerified( + address indexed module, uint64 indexed srcChainId, uint64 indexed dbNonce, bytes32 entryValue ); - /// @notice Emitted when a local batch is requested to be verified on a remote chain + /// @notice Emitted when a local entry is requested to be verified on a remote chain /// using the set of Interchain Modules. /// @param dstChainId The ID of the destination chain. - /// @param dbNonce The nonce of the batch to be verified. - /// @param batchRoot The Merkle root hash of the batch to be verified. - /// @param srcModules The addresses of the Interchain Modules that will verify the batch. - event InterchainBatchVerificationRequested( - uint64 indexed dstChainId, uint64 indexed dbNonce, bytes32 batchRoot, address[] srcModules - ); + /// @param dbNonce The nonce of the entry to be verified. + /// @param srcModules The addresses of the Interchain Modules that will verify the entry. + event InterchainEntryVerificationRequested(uint64 indexed dstChainId, uint64 indexed dbNonce, address[] srcModules); } diff --git a/packages/contracts-communication/contracts/events/InterchainModuleEvents.sol b/packages/contracts-communication/contracts/events/InterchainModuleEvents.sol index 4cc0702ea8..986d245611 100644 --- a/packages/contracts-communication/contracts/events/InterchainModuleEvents.sol +++ b/packages/contracts-communication/contracts/events/InterchainModuleEvents.sol @@ -2,15 +2,15 @@ pragma solidity ^0.8.0; abstract contract InterchainModuleEvents { - /// @notice Emitted when a batch verification on a remote chain is requested. + /// @notice Emitted when an entry verification on a remote chain is requested. /// @param dstChainId The chain ID of the destination chain. - /// @param batch The encoded batch to be verified. - /// @param ethSignedBatchHash The digest of the batch (EIP-191 personal signed). - event BatchVerificationRequested(uint64 indexed dstChainId, bytes batch, bytes32 ethSignedBatchHash); + /// @param entry The encoded entry to be verified. + /// @param ethSignedEntryHash The digest of the entry (EIP-191 personal signed). + event EntryVerificationRequested(uint64 indexed dstChainId, bytes entry, bytes32 ethSignedEntryHash); - /// @notice Emitted when a batch from the remote chain is verified. + /// @notice Emitted when an entry from the remote chain is verified. /// @param srcChainId The chain ID of the source chain. - /// @param batch The encoded batch that was verified. - /// @param ethSignedBatchHash The digest of the batch (EIP-191 personal signed). - event BatchVerified(uint64 indexed srcChainId, bytes batch, bytes32 ethSignedBatchHash); + /// @param entry The encoded entry that was verified. + /// @param ethSignedEntryHash The digest of the entry (EIP-191 personal signed). + event EntryVerified(uint64 indexed srcChainId, bytes entry, bytes32 ethSignedEntryHash); } diff --git a/packages/contracts-communication/contracts/events/SynapseModuleEvents.sol b/packages/contracts-communication/contracts/events/SynapseModuleEvents.sol index 4d7570c53e..ec66c02cba 100644 --- a/packages/contracts-communication/contracts/events/SynapseModuleEvents.sol +++ b/packages/contracts-communication/contracts/events/SynapseModuleEvents.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; abstract contract SynapseModuleEvents { - /// @notice Emitted when a verifier is added. The verifier signatures are required to verify a batch. + /// @notice Emitted when a verifier is added. The verifier signatures are required to verify an entry. /// @param verifier The address of the verifier. event VerifierAdded(address verifier); @@ -11,18 +11,18 @@ abstract contract SynapseModuleEvents { event VerifierRemoved(address verifier); /// @notice Emitted when a threshold is set. - /// The threshold is the minimum number of verifiers required to verify a batch. + /// The threshold is the minimum number of verifiers required to verify an entry. /// @param threshold The threshold value. event ThresholdSet(uint256 threshold); /// @notice Emitted when a gas oracle is set. The gas oracle will be used to estimate the gas cost of - /// verifying a batch on the remote chain. + /// verifying an entry on the remote chain. /// @param gasOracle The address of the gas oracle. event GasOracleSet(address gasOracle); /// @notice Emitted when the gas limit estimate is set for a chain. /// @param chainId The chain ID of the chain. - /// @param gasLimit The gas limit estimate for verifying a batch on the chain. + /// @param gasLimit The gas limit estimate for verifying an entry on the chain. event VerifyGasLimitSet(uint64 chainId, uint256 gasLimit); /// @notice Emitted when the gas data from the gas oracle is sent to the remote chain. diff --git a/packages/contracts-communication/contracts/interfaces/IInterchainApp.sol b/packages/contracts-communication/contracts/interfaces/IInterchainApp.sol index 27983c6ef3..0f64c6a133 100644 --- a/packages/contracts-communication/contracts/interfaces/IInterchainApp.sol +++ b/packages/contracts-communication/contracts/interfaces/IInterchainApp.sol @@ -3,15 +3,7 @@ pragma solidity ^0.8.0; /// @notice Minimal interface for the Interchain App to work with the Interchain Client. interface IInterchainApp { - function appReceive( - uint64 srcChainId, - bytes32 sender, - uint64 dbNonce, - uint64 entryIndex, - bytes calldata message - ) - external - payable; + function appReceive(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes calldata message) external payable; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ diff --git a/packages/contracts-communication/contracts/interfaces/IInterchainClientV1.sol b/packages/contracts-communication/contracts/interfaces/IInterchainClientV1.sol index 1c2aba1cee..0f9b8e1e2b 100644 --- a/packages/contracts-communication/contracts/interfaces/IInterchainClientV1.sol +++ b/packages/contracts-communication/contracts/interfaces/IInterchainClientV1.sol @@ -7,18 +7,18 @@ interface IInterchainClientV1 { enum TxReadiness { Ready, AlreadyExecuted, - BatchAwaitingResponses, - BatchConflict, + EntryAwaitingResponses, + EntryConflict, ReceiverNotICApp, ReceiverZeroRequiredResponses, TxWrongDstChainId, UndeterminedRevert } - error InterchainClientV1__BatchConflict(address module); error InterchainClientV1__ChainIdNotLinked(uint64 chainId); error InterchainClientV1__ChainIdNotRemote(uint64 chainId); error InterchainClientV1__DstChainIdNotLocal(uint64 chainId); + error InterchainClientV1__EntryConflict(address module); error InterchainClientV1__ExecutionServiceZeroAddress(); error InterchainClientV1__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired); error InterchainClientV1__GasLeftBelowMin(uint256 gasLeft, uint256 minRequired); @@ -60,26 +60,18 @@ interface IInterchainClientV1 { payable returns (InterchainTxDescriptor memory desc); - function interchainExecute( - uint256 gasLimit, - bytes calldata transaction, - bytes32[] calldata proof - ) - external - payable; + function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable; - function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce, uint64 entryIndex); + function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce); // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ - function isExecutable(bytes calldata transaction, bytes32[] calldata proof) external view returns (bool); - function getTxReadinessV1( - InterchainTransaction memory icTx, - bytes32[] calldata proof - ) + function isExecutable(bytes calldata transaction) external view returns (bool); + function getTxReadinessV1(InterchainTransaction memory icTx) external view returns (TxReadiness status, bytes32 firstArg, bytes32 secondArg); + function getInterchainFee( uint64 dstChainId, address srcExecutionService, diff --git a/packages/contracts-communication/contracts/interfaces/IInterchainDB.sol b/packages/contracts-communication/contracts/interfaces/IInterchainDB.sol index bf7dca27be..e52cd7046a 100644 --- a/packages/contracts-communication/contracts/interfaces/IInterchainDB.sol +++ b/packages/contracts-communication/contracts/interfaces/IInterchainDB.sol @@ -1,21 +1,18 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {InterchainBatch} from "../libs/InterchainBatch.sol"; import {InterchainEntry} from "../libs/InterchainEntry.sol"; interface IInterchainDB { - error InterchainDB__BatchConflict(address module, bytes32 existingBatchRoot, InterchainBatch newBatch); - error InterchainDB__BatchVersionMismatch(uint16 version, uint16 required); error InterchainDB__ChainIdNotRemote(uint64 chainId); - error InterchainDB__EntryIndexOutOfRange(uint64 dbNonce, uint64 entryIndex, uint64 batchSize); - error InterchainDB__EntryRangeInvalid(uint64 dbNonce, uint64 start, uint64 end); + error InterchainDB__EntryConflict(address module, InterchainEntry newEntry); + error InterchainDB__EntryVersionMismatch(uint16 version, uint16 required); error InterchainDB__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired); error InterchainDB__ModulesNotProvided(); - function writeEntry(bytes32 dataHash) external returns (uint64 dbNonce, uint64 entryIndex); + function writeEntry(bytes32 digest) external returns (uint64 dbNonce); - function requestBatchVerification( + function requestEntryVerification( uint64 dstChainId, uint64 dbNonce, address[] memory srcModules @@ -23,51 +20,35 @@ interface IInterchainDB { external payable; - function writeEntryWithVerification( + function writeEntryRequestVerification( uint64 dstChainId, - bytes32 dataHash, + bytes32 digest, address[] memory srcModules ) external payable - returns (uint64 dbNonce, uint64 entryIndex); + returns (uint64 dbNonce); - function verifyRemoteBatch(bytes memory versionedBatch) external; + function verifyRemoteEntry(bytes memory encodedEntry) external; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ function getInterchainFee(uint64 dstChainId, address[] memory srcModules) external view returns (uint256); - function getBatchLeafs(uint64 dbNonce) external view returns (bytes32[] memory); - function getBatchLeafsPaginated( - uint64 dbNonce, - uint64 start, - uint64 end - ) - external - view - returns (bytes32[] memory); - - function getBatchSize(uint64 dbNonce) external view returns (uint64); - function getBatch(uint64 dbNonce) external view returns (InterchainBatch memory); - function getVersionedBatch(uint64 dbNonce) external view returns (bytes memory); - - function getEntryValue(uint64 dbNonce, uint64 entryIndex) external view returns (bytes32); - function getEntryProof(uint64 dbNonce, uint64 entryIndex) external view returns (bytes32[] memory proof); + function getEncodedEntry(uint64 dbNonce) external view returns (bytes memory); + function getEntry(uint64 dbNonce) external view returns (InterchainEntry memory); + function getEntryValue(uint64 dbNonce) external view returns (bytes32); function getDBNonce() external view returns (uint64); - function getNextEntryIndex() external view returns (uint64 dbNonce, uint64 entryIndex); - function checkBatchVerification( + function checkEntryVerification( address dstModule, - InterchainBatch memory batch + InterchainEntry memory entry ) external view returns (uint256 moduleVerifiedAt); - function getBatchRoot(InterchainEntry memory entry, bytes32[] memory proof) external pure returns (bytes32); - // solhint-disable-next-line func-name-mixedcase function DB_VERSION() external pure returns (uint16); } diff --git a/packages/contracts-communication/contracts/interfaces/IInterchainModule.sol b/packages/contracts-communication/contracts/interfaces/IInterchainModule.sol index fd12643cc9..868dbd94b4 100644 --- a/packages/contracts-communication/contracts/interfaces/IInterchainModule.sol +++ b/packages/contracts-communication/contracts/interfaces/IInterchainModule.sol @@ -8,15 +8,9 @@ interface IInterchainModule { error InterchainModule__ChainIdNotRemote(uint64 chainId); error InterchainModule__FeeAmountBelowMin(uint256 feeAmount, uint256 minRequired); - function requestBatchVerification( - uint64 dstChainId, - uint64 batchNonce, - bytes memory versionedBatch - ) - external - payable; + function requestEntryVerification(uint64 dstChainId, bytes memory versionedEntry) external payable; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ - function getModuleFee(uint64 dstChainId, uint64 dbNonce) external view returns (uint256); + function getModuleFee(uint64 dstChainId) external view returns (uint256); } diff --git a/packages/contracts-communication/contracts/interfaces/ISynapseModule.sol b/packages/contracts-communication/contracts/interfaces/ISynapseModule.sol index 52d7b9701d..263e753b0c 100644 --- a/packages/contracts-communication/contracts/interfaces/ISynapseModule.sol +++ b/packages/contracts-communication/contracts/interfaces/ISynapseModule.sol @@ -19,7 +19,7 @@ interface ISynapseModule is IInterchainModule { function setGasOracle(address gasOracle_) external; function setVerifyGasLimit(uint64 chainId, uint256 gasLimit) external; - function verifyRemoteBatch(bytes calldata encodedBatch, bytes calldata signatures) external; + function verifyRemoteEntry(bytes calldata encodedEntry, bytes calldata signatures) external; // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ diff --git a/packages/contracts-communication/contracts/legacy/MessageBus.sol b/packages/contracts-communication/contracts/legacy/MessageBus.sol index 4db4c4747a..1aabf801a5 100644 --- a/packages/contracts-communication/contracts/legacy/MessageBus.sol +++ b/packages/contracts-communication/contracts/legacy/MessageBus.sol @@ -125,7 +125,6 @@ contract MessageBus is ICAppV1, MessageBusEvents, IMessageBus { uint64 srcChainId, bytes32, // sender uint64, // dbNonce - uint64, // entryIndex bytes calldata encodedLegacyMsg ) internal diff --git a/packages/contracts-communication/contracts/libs/BatchingV1.sol b/packages/contracts-communication/contracts/libs/BatchingV1.sol deleted file mode 100644 index 6007f1ad9d..0000000000 --- a/packages/contracts-communication/contracts/libs/BatchingV1.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {InterchainEntryLib} from "./InterchainEntry.sol"; - -library BatchingV1Lib { - error BatchingV1__EntryIndexNotZero(uint64 entryIndex); - error BatchingV1__ProofNotEmpty(); - - /// @notice Get the batch root containing the Interchain Entry with the given index. - /// @param srcWriter The entry writer of the source chain - /// @param dataHash The hash of the data of the entry - /// @param entryIndex The index of the entry in the batch - /// @param proof The Merkle proof of inclusion for the entry in the batch - /// @return batchRoot The root of the batch containing the entry - function getBatchRoot( - bytes32 srcWriter, - bytes32 dataHash, - uint64 entryIndex, - bytes32[] calldata proof - ) - internal - pure - returns (bytes32 batchRoot) - { - // In "no batching" mode: entry index is 0, proof is empty - if (entryIndex != 0) { - revert BatchingV1__EntryIndexNotZero(entryIndex); - } - if (proof.length != 0) { - revert BatchingV1__ProofNotEmpty(); - } - // In "no batching" mode: the batch root is the same as the entry value - return InterchainEntryLib.getEntryValue({srcWriter: srcWriter, dataHash: dataHash}); - } -} diff --git a/packages/contracts-communication/contracts/libs/InterchainBatch.sol b/packages/contracts-communication/contracts/libs/InterchainBatch.sol deleted file mode 100644 index ae19454373..0000000000 --- a/packages/contracts-communication/contracts/libs/InterchainBatch.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import {VersionedPayloadLib} from "./VersionedPayload.sol"; - -import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; - -type BatchKey is uint128; - -/// @notice Struct representing a batch of entries in the Interchain DataBase. -/// Batched entries are put together in a Merkle tree, which root is saved. -/// Batch has a globally unique identifier (key) and a value. -/// - key: srcChainId + dbNonce -/// - value: batchRoot -/// @param srcChainId The chain id of the source chain -/// @param dbNonce The database nonce of the batch -/// @param batchRoot The root of the Merkle tree containing the batched entries -struct InterchainBatch { - uint64 srcChainId; - uint64 dbNonce; - bytes32 batchRoot; -} - -/// @dev Signals that the module has not verified any batch with the given key. -uint256 constant BATCH_UNVERIFIED = 0; -/// @dev Signals that the module has verified a conflicting batch with the given key. -uint256 constant BATCH_CONFLICT = type(uint256).max; - -library InterchainBatchLib { - using VersionedPayloadLib for bytes; - - /// @notice Constructs an InterchainBatch struct to be saved on the local chain. - /// @param dbNonce The database nonce of the batch - /// @param batchRoot The root of the Merkle tree containing the batched entries - /// @return batch The constructed InterchainBatch struct - function constructLocalBatch( - uint64 dbNonce, - bytes32 batchRoot - ) - internal - view - returns (InterchainBatch memory batch) - { - return InterchainBatch({srcChainId: SafeCast.toUint64(block.chainid), dbNonce: dbNonce, batchRoot: batchRoot}); - } - - /// @notice Encodes the InterchainBatch struct into a non-versioned batch payload. - function encodeBatch(InterchainBatch memory batch) internal pure returns (bytes memory) { - return abi.encode(encodeBatchKey(batch.srcChainId, batch.dbNonce), batch.batchRoot); - } - - /// @notice Decodes the InterchainBatch struct from a non-versioned batch payload in calldata. - function decodeBatch(bytes calldata data) internal pure returns (InterchainBatch memory batch) { - BatchKey key; - (key, batch.batchRoot) = abi.decode(data, (BatchKey, bytes32)); - (batch.srcChainId, batch.dbNonce) = decodeBatchKey(key); - } - - /// @notice Decodes the InterchainBatch struct from a non-versioned batch payload in memory. - function decodeBatchFromMemory(bytes memory data) internal pure returns (InterchainBatch memory batch) { - BatchKey key; - (key, batch.batchRoot) = abi.decode(data, (BatchKey, bytes32)); - (batch.srcChainId, batch.dbNonce) = decodeBatchKey(key); - } - - /// @notice Encodes the uint128 key of the batch from uint64 srcChainId and uint64 dbNonce. - function encodeBatchKey(uint64 srcChainId, uint64 dbNonce) internal pure returns (BatchKey) { - return BatchKey.wrap((uint128(srcChainId) << 64) | dbNonce); - } - - /// @notice Decodes the uint128 key of the batch into uint64 srcChainId and uint64 dbNonce. - function decodeBatchKey(BatchKey key) internal pure returns (uint64 srcChainId, uint64 dbNonce) { - srcChainId = uint64(BatchKey.unwrap(key) >> 64); - dbNonce = uint64(BatchKey.unwrap(key)); - } -} diff --git a/packages/contracts-communication/contracts/libs/InterchainEntry.sol b/packages/contracts-communication/contracts/libs/InterchainEntry.sol index 8315e65b7f..268db1b55f 100644 --- a/packages/contracts-communication/contracts/libs/InterchainEntry.sol +++ b/packages/contracts-communication/contracts/libs/InterchainEntry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.13; +pragma solidity ^0.8.0; import {TypeCasts} from "./TypeCasts.sol"; @@ -7,55 +7,79 @@ import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; /// @notice Struct representing an entry in the Interchain DataBase. /// Entry has a globally unique identifier (key) and a value. -/// - key: srcChainId + dbNonce + entryIndex -/// - value: srcWriter + dataHash +/// Assuming `srcWriter` has written data `digest` on the source chain: +/// - key: (srcChainId, dbNonce) +/// - entryValue = keccak256(srcWriter, digest) /// @param srcChainId The chain id of the source chain -/// @param dbNonce The database nonce of the batch containing the entry -/// @param entryIndex The index of the entry in the batch -/// @param srcWriter The address of the writer on the source chain -/// @param dataHash The hash of the data written on the source chain +/// @param dbNonce The database nonce of the entry +/// @param entryValue The entry value struct InterchainEntry { uint64 srcChainId; uint64 dbNonce; - uint64 entryIndex; - bytes32 srcWriter; - bytes32 dataHash; + bytes32 entryValue; } -using InterchainEntryLib for InterchainEntry global; +type EntryKey is uint128; + +/// @dev Signals that the module has not verified any entry with the given key. +uint256 constant ENTRY_UNVERIFIED = 0; +/// @dev Signals that the module has verified a conflicting entry with the given key. +uint256 constant ENTRY_CONFLICT = type(uint256).max; library InterchainEntryLib { /// @notice Constructs an InterchainEntry struct to be written on the local chain /// @param dbNonce The database nonce of the entry on the source chain - /// @param writer The address of the writer on the local chain - /// @param dataHash The hash of the data written on the local chain + /// @param entryValue The value of the entry /// @return entry The constructed InterchainEntry struct function constructLocalEntry( uint64 dbNonce, - uint64 entryIndex, - address writer, - bytes32 dataHash + bytes32 entryValue ) internal view returns (InterchainEntry memory entry) { - return InterchainEntry({ - srcChainId: SafeCast.toUint64(block.chainid), - dbNonce: dbNonce, - entryIndex: entryIndex, - srcWriter: TypeCasts.addressToBytes32(writer), - dataHash: dataHash - }); + return InterchainEntry({srcChainId: SafeCast.toUint64(block.chainid), dbNonce: dbNonce, entryValue: entryValue}); + } + + /// @notice Returns the value of the entry: writer + digest hashed together + function getEntryValue(bytes32 srcWriter, bytes32 digest) internal pure returns (bytes32) { + return keccak256(abi.encode(srcWriter, digest)); + } + + /// @notice Returns the value of the entry: writer + digest hashed together. + /// Note: this is exposed for convenience to avoid typecasts prior to abi-encoding. + function getEntryValue(address srcWriter, bytes32 digest) internal pure returns (bytes32) { + return keccak256(abi.encode(srcWriter, digest)); + } + + /// @notice Encodes the InterchainEntry struct into a non-versioned entry payload. + function encodeEntry(InterchainEntry memory entry) internal pure returns (bytes memory) { + return abi.encode(encodeEntryKey(entry.srcChainId, entry.dbNonce), entry.entryValue); + } + + /// @notice Decodes the InterchainEntry struct from a non-versioned entry payload in calldata. + function decodeEntry(bytes calldata data) internal pure returns (InterchainEntry memory entry) { + EntryKey key; + (key, entry.entryValue) = abi.decode(data, (EntryKey, bytes32)); + (entry.srcChainId, entry.dbNonce) = decodeEntryKey(key); + } + + /// @notice Decodes the InterchainEntry struct from a non-versioned entry payload in memory. + function decodeEntryFromMemory(bytes memory data) internal pure returns (InterchainEntry memory entry) { + EntryKey key; + (key, entry.entryValue) = abi.decode(data, (EntryKey, bytes32)); + (entry.srcChainId, entry.dbNonce) = decodeEntryKey(key); } - /// @notice Returns the value of the entry: writer + dataHash hashed together - function entryValue(InterchainEntry memory entry) internal pure returns (bytes32) { - return getEntryValue(entry.srcWriter, entry.dataHash); + /// @notice Encodes the uint128 key of the entry from uint64 srcChainId and uint64 dbNonce. + function encodeEntryKey(uint64 srcChainId, uint64 dbNonce) internal pure returns (EntryKey) { + return EntryKey.wrap((uint128(srcChainId) << 64) | dbNonce); } - /// @notice Returns the value of the entry: writer + dataHash hashed together - function getEntryValue(bytes32 srcWriter, bytes32 dataHash) internal pure returns (bytes32) { - return keccak256(abi.encode(srcWriter, dataHash)); + /// @notice Decodes the uint128 key of the entry into uint64 srcChainId and uint64 dbNonce. + function decodeEntryKey(EntryKey key) internal pure returns (uint64 srcChainId, uint64 dbNonce) { + srcChainId = uint64(EntryKey.unwrap(key) >> 64); + dbNonce = uint64(EntryKey.unwrap(key)); } } diff --git a/packages/contracts-communication/contracts/libs/InterchainTransaction.sol b/packages/contracts-communication/contracts/libs/InterchainTransaction.sol index 397f5dd9c6..80ec40cad9 100644 --- a/packages/contracts-communication/contracts/libs/InterchainTransaction.sol +++ b/packages/contracts-communication/contracts/libs/InterchainTransaction.sol @@ -13,7 +13,6 @@ struct InterchainTransaction { uint64 srcChainId; uint64 dstChainId; uint64 dbNonce; - uint64 entryIndex; bytes32 srcSender; bytes32 dstReceiver; bytes options; @@ -23,7 +22,6 @@ struct InterchainTransaction { struct InterchainTxDescriptor { bytes32 transactionId; uint64 dbNonce; - uint64 entryIndex; } using InterchainTransactionLib for InterchainTransaction global; @@ -37,7 +35,6 @@ library InterchainTransactionLib { uint64 dstChainId, bytes32 dstReceiver, uint64 dbNonce, - uint64 entryIndex, bytes memory options, bytes memory message ) @@ -51,7 +48,6 @@ library InterchainTransactionLib { dstChainId: dstChainId, dstReceiver: dstReceiver, dbNonce: dbNonce, - entryIndex: entryIndex, options: options, message: message }); @@ -59,7 +55,7 @@ library InterchainTransactionLib { function encodeTransaction(InterchainTransaction memory transaction) internal pure returns (bytes memory) { return abi.encode( - encodeTxHeader(transaction.srcChainId, transaction.dstChainId, transaction.dbNonce, transaction.entryIndex), + encodeTxHeader(transaction.srcChainId, transaction.dstChainId, transaction.dbNonce), transaction.srcSender, transaction.dstReceiver, transaction.options, @@ -71,40 +67,28 @@ library InterchainTransactionLib { ICTxHeader header; (header, icTx.srcSender, icTx.dstReceiver, icTx.options, icTx.message) = abi.decode(transaction, (ICTxHeader, bytes32, bytes32, bytes, bytes)); - (icTx.srcChainId, icTx.dstChainId, icTx.dbNonce, icTx.entryIndex) = decodeTxHeader(header); + (icTx.srcChainId, icTx.dstChainId, icTx.dbNonce) = decodeTxHeader(header); } function payloadSize(uint256 optionsLen, uint256 messageLen) internal pure returns (uint256) { // 2 bytes are reserved for the transaction version // + 5 fields * 32 bytes (3 values for static, 2 offsets for dynamic) + 2 * 32 bytes (lengths for dynamic) = 226 - // (srcChainId, dstChainId, dbNonce, entryIndex) are merged into a single 32 bytes field + // (srcChainId, dstChainId, dbNonce) are merged into a single 32 bytes field // Both options and message are dynamic fields, which are padded up to 32 bytes return 226 + optionsLen.roundUpToWord() + messageLen.roundUpToWord(); } - function encodeTxHeader( - uint64 srcChainId, - uint64 dstChainId, - uint64 dbNonce, - uint64 entryIndex - ) - internal - pure - returns (ICTxHeader) - { - return ICTxHeader.wrap( - (uint256(srcChainId) << 192) | (uint256(dstChainId) << 128) | (uint256(dbNonce) << 64) | uint256(entryIndex) - ); + function encodeTxHeader(uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) internal pure returns (ICTxHeader) { + return ICTxHeader.wrap((uint256(srcChainId) << 128) | (uint256(dstChainId) << 64) | (uint256(dbNonce))); } function decodeTxHeader(ICTxHeader header) internal pure - returns (uint64 srcChainId, uint64 dstChainId, uint64 dbNonce, uint64 entryIndex) + returns (uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) { - srcChainId = uint64(ICTxHeader.unwrap(header) >> 192); - dstChainId = uint64(ICTxHeader.unwrap(header) >> 128); - dbNonce = uint64(ICTxHeader.unwrap(header) >> 64); - entryIndex = uint64(ICTxHeader.unwrap(header)); + srcChainId = uint64(ICTxHeader.unwrap(header) >> 128); + dstChainId = uint64(ICTxHeader.unwrap(header) >> 64); + dbNonce = uint64(ICTxHeader.unwrap(header)); } } diff --git a/packages/contracts-communication/contracts/libs/ModuleBatch.sol b/packages/contracts-communication/contracts/libs/ModuleBatch.sol deleted file mode 100644 index e88b211e89..0000000000 --- a/packages/contracts-communication/contracts/libs/ModuleBatch.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -library ModuleBatchLib { - /// @notice Encodes the versioned batch and the auxiliary module data into a single bytes array - /// @param versionedBatch The versioned batch to encode - /// @param moduleData The auxiliary module data to encode - /// @return encodedModuleBatch The encoded versioned module batch - function encodeVersionedModuleBatch( - bytes memory versionedBatch, - bytes memory moduleData - ) - internal - pure - returns (bytes memory encodedModuleBatch) - { - return abi.encode(versionedBatch, moduleData); - } - - /// @notice Decodes the bytes array into the versioned batch and the auxiliary module data - /// @param encodedModuleBatch The bytes array to decode - /// @return versionedBatch The decoded versioned batch - /// @return moduleData The decoded auxiliary module data - function decodeVersionedModuleBatch(bytes memory encodedModuleBatch) - internal - pure - returns (bytes memory versionedBatch, bytes memory moduleData) - { - return abi.decode(encodedModuleBatch, (bytes, bytes)); - } -} diff --git a/packages/contracts-communication/contracts/libs/ModuleEntry.sol b/packages/contracts-communication/contracts/libs/ModuleEntry.sol new file mode 100644 index 0000000000..ce405b1850 --- /dev/null +++ b/packages/contracts-communication/contracts/libs/ModuleEntry.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +library ModuleEntryLib { + /// @notice Encodes the versioned entry and the auxiliary module data into a single bytes array + /// @param versionedEntry The versioned entry to encode + /// @param moduleData The auxiliary module data to encode + /// @return encodedModuleEntry The encoded versioned module entry + function encodeVersionedModuleEntry( + bytes memory versionedEntry, + bytes memory moduleData + ) + internal + pure + returns (bytes memory encodedModuleEntry) + { + return abi.encode(versionedEntry, moduleData); + } + + /// @notice Decodes the bytes array into the versioned entry and the auxiliary module data + /// @param encodedModuleEntry The bytes array to decode + /// @return versionedEntry The decoded versioned entry + /// @return moduleData The decoded auxiliary module data + function decodeVersionedModuleEntry(bytes memory encodedModuleEntry) + internal + pure + returns (bytes memory versionedEntry, bytes memory moduleData) + { + return abi.decode(encodedModuleEntry, (bytes, bytes)); + } +} diff --git a/packages/contracts-communication/contracts/modules/InterchainModule.sol b/packages/contracts-communication/contracts/modules/InterchainModule.sol index 9dad8d8157..1ed9ae66ca 100644 --- a/packages/contracts-communication/contracts/modules/InterchainModule.sol +++ b/packages/contracts-communication/contracts/modules/InterchainModule.sol @@ -5,8 +5,8 @@ import {InterchainModuleEvents} from "../events/InterchainModuleEvents.sol"; import {IInterchainDB} from "../interfaces/IInterchainDB.sol"; import {IInterchainModule} from "../interfaces/IInterchainModule.sol"; -import {InterchainBatch, InterchainBatchLib} from "../libs/InterchainBatch.sol"; -import {ModuleBatchLib} from "../libs/ModuleBatch.sol"; +import {InterchainEntry, InterchainEntryLib} from "../libs/InterchainEntry.sol"; +import {ModuleEntryLib} from "../libs/ModuleEntry.sol"; import {VersionedPayloadLib} from "../libs/VersionedPayload.sol"; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; @@ -15,81 +15,70 @@ import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/Messa abstract contract InterchainModule is InterchainModuleEvents, IInterchainModule { using VersionedPayloadLib for bytes; - /// @notice The address of the Interchain DataBase contract: used for verifying the batches. + /// @notice The address of the Interchain DataBase contract: used for verifying the entries. address public immutable INTERCHAIN_DB; constructor(address interchainDB) { INTERCHAIN_DB = interchainDB; } - /// @notice Request the verification of a batch from the Interchain DataBase by the module. - /// If the batch is not yet finalized, the verification on destination chain will be delayed until - /// the finalization is done and batch root is saved on the source chain. + /// @notice Request the verification of an entry from the Interchain DataBase by the module. /// Note: a fee is paid to the module for verification, and could be retrieved by using `getModuleFee`. - /// Note: this will eventually trigger `InterchainDB.verifyRemoteBatch(batch)` function on destination chain, + /// Note: this will eventually trigger `InterchainDB.verifyRemoteEntry(entry)` function on destination chain, /// with no guarantee of ordering. /// @dev Could be only called by the Interchain DataBase contract. /// @param dstChainId The chain id of the destination chain - /// @param batchNonce The nonce of the batch on the source chain - /// @param versionedBatch The versioned batch to verify - function requestBatchVerification( - uint64 dstChainId, - uint64 batchNonce, - bytes calldata versionedBatch - ) - external - payable - { + /// @param versionedEntry The versioned entry to verify + function requestEntryVerification(uint64 dstChainId, bytes memory versionedEntry) external payable { if (msg.sender != INTERCHAIN_DB) { revert InterchainModule__CallerNotInterchainDB(msg.sender); } if (dstChainId == block.chainid) { revert InterchainModule__ChainIdNotRemote(dstChainId); } - uint256 requiredFee = _getModuleFee(dstChainId, batchNonce); + uint256 requiredFee = _getModuleFee(dstChainId); if (msg.value < requiredFee) { revert InterchainModule__FeeAmountBelowMin({feeAmount: msg.value, minRequired: requiredFee}); } - bytes memory moduleData = _fillModuleData(dstChainId, batchNonce); - bytes memory encodedBatch = ModuleBatchLib.encodeVersionedModuleBatch(versionedBatch, moduleData); - bytes32 ethSignedBatchHash = MessageHashUtils.toEthSignedMessageHash(keccak256(encodedBatch)); - _requestVerification(dstChainId, encodedBatch); - emit BatchVerificationRequested(dstChainId, encodedBatch, ethSignedBatchHash); + bytes memory moduleData = _fillModuleData(dstChainId); + bytes memory encodedEntry = ModuleEntryLib.encodeVersionedModuleEntry(versionedEntry, moduleData); + bytes32 ethSignedEntryHash = MessageHashUtils.toEthSignedMessageHash(keccak256(encodedEntry)); + _requestVerification(dstChainId, encodedEntry); + emit EntryVerificationRequested(dstChainId, encodedEntry, ethSignedEntryHash); } - /// @notice Get the Module fee for verifying a batch on the specified destination chain. + /// @notice Get the Module fee for verifying an entry on the specified destination chain. /// @param dstChainId The chain id of the destination chain - /// @param dbNonce The database nonce of the batch on the source chain - function getModuleFee(uint64 dstChainId, uint64 dbNonce) external view returns (uint256) { - return _getModuleFee(dstChainId, dbNonce); + function getModuleFee(uint64 dstChainId) external view returns (uint256) { + return _getModuleFee(dstChainId); } - /// @dev Should be called once the Module has verified the batch and needs to signal this + /// @dev Should be called once the Module has verified the entry and needs to signal this /// to the InterchainDB. - function _verifyBatch(bytes memory encodedModuleBatch) internal { - (bytes memory versionedBatch, bytes memory moduleData) = - ModuleBatchLib.decodeVersionedModuleBatch(encodedModuleBatch); - InterchainBatch memory batch = InterchainBatchLib.decodeBatchFromMemory(versionedBatch.getPayloadFromMemory()); - if (batch.srcChainId == block.chainid) { - revert InterchainModule__ChainIdNotRemote(batch.srcChainId); + function _verifyEntry(bytes memory encodedModuleEntry) internal { + (bytes memory versionedEntry, bytes memory moduleData) = + ModuleEntryLib.decodeVersionedModuleEntry(encodedModuleEntry); + InterchainEntry memory entry = InterchainEntryLib.decodeEntryFromMemory(versionedEntry.getPayloadFromMemory()); + if (entry.srcChainId == block.chainid) { + revert InterchainModule__ChainIdNotRemote(entry.srcChainId); } - IInterchainDB(INTERCHAIN_DB).verifyRemoteBatch(versionedBatch); - _receiveModuleData(batch.srcChainId, batch.dbNonce, moduleData); - emit BatchVerified( - batch.srcChainId, encodedModuleBatch, MessageHashUtils.toEthSignedMessageHash(keccak256(encodedModuleBatch)) + IInterchainDB(INTERCHAIN_DB).verifyRemoteEntry(versionedEntry); + _receiveModuleData(entry.srcChainId, entry.dbNonce, moduleData); + emit EntryVerified( + entry.srcChainId, encodedModuleEntry, MessageHashUtils.toEthSignedMessageHash(keccak256(encodedModuleEntry)) ); } // solhint-disable no-empty-blocks - /// @dev Internal logic to request the verification of an batch on the destination chain. - function _requestVerification(uint64 dstChainId, bytes memory encodedBatch) internal virtual {} + /// @dev Internal logic to request the verification of an entry on the destination chain. + function _requestVerification(uint64 dstChainId, bytes memory encodedEntry) internal virtual {} /// @dev Internal logic to fill the module data for the specified destination chain. - function _fillModuleData(uint64 dstChainId, uint64 dbNonce) internal virtual returns (bytes memory) {} + function _fillModuleData(uint64 dstChainId) internal virtual returns (bytes memory) {} /// @dev Internal logic to handle the auxiliary module data relayed from the remote chain. function _receiveModuleData(uint64 srcChainId, uint64 dbNonce, bytes memory moduleData) internal virtual {} - /// @dev Internal logic to get the module fee for verifying an batch on the specified destination chain. - function _getModuleFee(uint64 dstChainId, uint64 dbNonce) internal view virtual returns (uint256); + /// @dev Internal logic to get the module fee for verifying an entry on the specified destination chain. + function _getModuleFee(uint64 dstChainId) internal view virtual returns (uint256); } diff --git a/packages/contracts-communication/contracts/modules/SynapseModule.sol b/packages/contracts-communication/contracts/modules/SynapseModule.sol index c624ddb054..69ff42ef1d 100644 --- a/packages/contracts-communication/contracts/modules/SynapseModule.sol +++ b/packages/contracts-communication/contracts/modules/SynapseModule.sol @@ -20,7 +20,7 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul /// @dev Struct to hold the verifiers and the threshold for the module. ThresholdECDSA internal _verifiers; - /// @dev Gas limit for the verifyBatch function on the remote chain. + /// @dev Gas limit for the verifyEntry function on the remote chain. mapping(uint64 chainId => uint256 gasLimit) internal _verifyGasLimit; /// @dev Hash of the last gas data sent to the remote chain. mapping(uint64 chainId => bytes32 gasDataHash) internal _lastGasDataHash; @@ -109,7 +109,7 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul emit GasOracleSet(gasOracle_); } - /// @notice Sets the estimated gas limit for verifying a batch on the given chain. + /// @notice Sets the estimated gas limit for verifying an entry on the given chain. /// @dev Could be only called by the owner. /// @param chainId The chain ID for which to set the gas limit /// @param gasLimit The new gas limit for the verification on the specified chain @@ -120,15 +120,15 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul // ══════════════════════════════════════════════ PERMISSIONLESS ═══════════════════════════════════════════════════ - /// @notice Verifies a batch from the remote chain using a set of verifier signatures. - /// If the threshold is met, the batch will be marked as verified in the Interchain DataBase. + /// @notice Verifies an entry from the remote chain using a set of verifier signatures. + /// If the threshold is met, the entry will be marked as verified in the Interchain DataBase. /// @dev List of recovered signers from the signatures must be sorted in the ascending order. - /// @param encodedBatch The encoded batch to verify - /// @param signatures Signatures used to verify the batch, concatenated - function verifyRemoteBatch(bytes calldata encodedBatch, bytes calldata signatures) external { - bytes32 ethSignedHash = MessageHashUtils.toEthSignedMessageHash(keccak256(encodedBatch)); + /// @param encodedEntry The encoded entry to verify + /// @param signatures Signatures used to verify the entry, concatenated + function verifyRemoteEntry(bytes calldata encodedEntry, bytes calldata signatures) external { + bytes32 ethSignedHash = MessageHashUtils.toEthSignedMessageHash(keccak256(encodedEntry)); _verifiers.verifySignedHash(ethSignedHash, signatures); - _verifyBatch(encodedBatch); + _verifyEntry(encodedEntry); } // ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ @@ -148,7 +148,7 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul return _verifiers.getThreshold(); } - /// @notice Returns the estimated gas limit for verifying a batch on the given chain. + /// @notice Returns the estimated gas limit for verifying an entry on the given chain. /// Note: this defaults to DEFAULT_VERIFY_GAS_LIMIT if not set. function getVerifyGasLimit(uint64 chainId) public view override returns (uint256 gasLimit) { gasLimit = _verifyGasLimit[chainId]; @@ -195,14 +195,7 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul } /// @dev Internal logic to fill the module data for the specified destination chain. - function _fillModuleData( - uint64 dstChainId, - uint64 // dbNonce - ) - internal - override - returns (bytes memory moduleData) - { + function _fillModuleData(uint64 dstChainId) internal override returns (bytes memory moduleData) { moduleData = _getSynapseGasOracle().getLocalGasData(); // Exit early if data is empty if (moduleData.length == 0) { @@ -235,22 +228,14 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul // ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════ - /// @dev Internal logic to get the module fee for verifying an batch on the specified destination chain. - function _getModuleFee( - uint64 dstChainId, - uint64 // dbNonce - ) - internal - view - override - returns (uint256) - { - // On the remote chain the verifyRemoteBatch(batch, signatures) function will be called. + /// @dev Internal logic to get the module fee for verifying an entry on the specified destination chain. + function _getModuleFee(uint64 dstChainId) internal view override returns (uint256) { + // On the remote chain the verifyRemoteEntry(entry, signatures) function will be called. // We need to figure out the calldata size for the remote call. - // selector (4 bytes) + batch + signatures - // batch is 32 (length) + 32*3 (fields) = 128 + // selector (4 bytes) + entry + signatures + // entry is 32 (length) + 32*3 (fields) = 128 // signatures: 32 (length) + 65*threshold (padded up to be a multiple of 32 bytes) - // Total formula is: 4 + 32 (batch offset) + 32 (signatures offset) + 128 + 32 + // Total formula is: 4 + 32 (entry offset) + 32 (signatures offset) + 128 + 32 return _getSynapseGasOracle().estimateTxCostInLocalUnits({ remoteChainId: dstChainId, gasLimit: getVerifyGasLimit(dstChainId), diff --git a/packages/contracts-communication/deployments/arb_sepolia/ExecutionFees.json b/packages/contracts-communication/deployments/arb_sepolia/ExecutionFees.json deleted file mode 100644 index 17c3d66e17..0000000000 --- a/packages/contracts-communication/deployments/arb_sepolia/ExecutionFees.json +++ /dev/null @@ -1,534 +0,0 @@ -{ - "address": "0x3516cD6eF60c5287d749e53312C17D9FAF17aB24", - "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", - "receipt": { - "hash": "0x0311476d3123bf7ab04754697787226fb8b0a0a907d0a2d2dc2419e47c192a1a", - "blockNumber": 34358373 - }, - "abi": [ - { - "type": "constructor", - "inputs": [ - { - "name": "admin", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECORDER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "accumulatedRewards", - "inputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "totalAccumulated", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "addExecutionFee", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "claimExecutionFees", - "inputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "executionFee", - "inputs": [ - { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "fee", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "recordExecutor", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recordedExecutor", - "inputs": [ - { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "unclaimedRewards", - "inputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "totalClaimed", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "ExecutionFeeAdded", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "totalFee", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExecutionFeesAwarded", - "inputs": [ - { - "name": "executor", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExecutionFeesClaimed", - "inputs": [ - { - "name": "executor", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExecutorRecorded", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "executor", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "AddressInsufficientBalance", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - } - ] - }, - { - "type": "error", - "name": "ExecutionFees__AlreadyRecorded", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ] - }, - { - "type": "error", - "name": "ExecutionFees__ZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ExecutionFees__ZeroAmount", - "inputs": [] - }, - { - "type": "error", - "name": "FailedInnerCall", - "inputs": [] - } - ] -} \ No newline at end of file diff --git a/packages/contracts-communication/deployments/arb_sepolia/InterchainClientV1.json b/packages/contracts-communication/deployments/arb_sepolia/InterchainClientV1.json index d8640dfae1..f099dc05b6 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/InterchainClientV1.json +++ b/packages/contracts-communication/deployments/arb_sepolia/InterchainClientV1.json @@ -1,9 +1,9 @@ { - "address": "0x4AdfEb01C090e14BFA84411b74D0d03dDE12e39b", - "constructorArgs": "0x0000000000000000000000004361f461c5df0dcf109ba2cf0e46dfa26e73f54f000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", + "address": "0x15ACDFd1F2027aE084B4d92da20D22cc945d07Ec", + "constructorArgs": "0x000000000000000000000000943257ae5037f5997ab302c4e158efe48bbce89d000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xb4dbdb9daaf91ad88cb1d179d5855e995a45a10b11acb7475b636fc239fecd60", - "blockNumber": 34358231 + "hash": "0x7e7954ac15bf35ce836e9324532685bfcbfc51a1e6a6b8978253802ebc412484", + "blockNumber": 41157437 }, "abi": [ { @@ -79,6 +79,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "defaultGuard", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "encodeTransaction", @@ -140,19 +153,6 @@ ], "stateMutability": "pure" }, - { - "type": "function", - "name": "executionFees", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, { "type": "function", "name": "getAppReceivingConfigV1", @@ -178,6 +178,16 @@ "name": "optimisticPeriod", "type": "uint256", "internalType": "uint256" + }, + { + "name": "guardFlag", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "guard", + "type": "address", + "internalType": "address" } ] }, @@ -304,6 +314,82 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getTxReadinessV1", + "inputs": [ + { + "name": "icTx", + "type": "tuple", + "internalType": "struct InterchainTransaction", + "components": [ + { + "name": "srcChainId", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "dstChainId", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "srcSender", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "dstReceiver", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "options", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "message", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "proof", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "outputs": [ + { + "name": "status", + "type": "uint8", + "internalType": "enum IInterchainClientV1.TxReadiness" + }, + { + "name": "firstArg", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "secondArg", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "interchainExecute", @@ -495,10 +581,10 @@ }, { "type": "function", - "name": "setExecutionFees", + "name": "setDefaultGuard", "inputs": [ { - "name": "executionFees_", + "name": "guard", "type": "address", "internalType": "address" } @@ -563,10 +649,10 @@ }, { "type": "event", - "name": "ExecutionFeesSet", + "name": "DefaultGuardSet", "inputs": [ { - "name": "executionFees", + "name": "guard", "type": "address", "indexed": false, "internalType": "address" @@ -755,7 +841,7 @@ }, { "type": "error", - "name": "AppConfigLib__IncorrectVersion", + "name": "AppConfigLib__VersionInvalid", "inputs": [ { "name": "version", @@ -766,23 +852,34 @@ }, { "type": "error", - "name": "InterchainClientV1__FeeAmountTooLow", + "name": "BatchingV1__EntryIndexNotZero", "inputs": [ { - "name": "actual", - "type": "uint256", - "internalType": "uint256" - }, + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "BatchingV1__ProofNotEmpty", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainClientV1__BatchConflict", + "inputs": [ { - "name": "required", - "type": "uint256", - "internalType": "uint256" + "name": "module", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "InterchainClientV1__IncorrectDstChainId", + "name": "InterchainClientV1__ChainIdNotLinked", "inputs": [ { "name": "chainId", @@ -793,15 +890,42 @@ }, { "type": "error", - "name": "InterchainClientV1__IncorrectMsgValue", + "name": "InterchainClientV1__ChainIdNotRemote", "inputs": [ { - "name": "actual", + "name": "chainId", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__DstChainIdNotLocal", + "inputs": [ + { + "name": "chainId", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__ExecutionServiceZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainClientV1__FeeAmountBelowMin", + "inputs": [ + { + "name": "feeAmount", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -809,29 +933,28 @@ }, { "type": "error", - "name": "InterchainClientV1__InvalidTransactionVersion", + "name": "InterchainClientV1__GasLeftBelowMin", "inputs": [ { - "name": "version", - "type": "uint16", - "internalType": "uint16" + "name": "gasLeft", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "InterchainClientV1__NoLinkedClient", - "inputs": [ - { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - } - ] + "name": "InterchainClientV1__GuardZeroAddress", + "inputs": [] }, { "type": "error", - "name": "InterchainClientV1__NotEVMClient", + "name": "InterchainClientV1__LinkedClientNotEVM", "inputs": [ { "name": "client", @@ -842,15 +965,10 @@ }, { "type": "error", - "name": "InterchainClientV1__NotEnoughGasSupplied", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainClientV1__NotEnoughResponses", + "name": "InterchainClientV1__MsgValueMismatch", "inputs": [ { - "name": "actual", + "name": "msgValue", "type": "uint256", "internalType": "uint256" }, @@ -863,12 +981,44 @@ }, { "type": "error", - "name": "InterchainClientV1__NotRemoteChainId", + "name": "InterchainClientV1__ReceiverNotICApp", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "receiver", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__ReceiverZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainClientV1__ReceiverZeroRequiredResponses", + "inputs": [ + { + "name": "receiver", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__ResponsesAmountBelowMin", + "inputs": [ + { + "name": "responsesAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, @@ -896,17 +1046,23 @@ }, { "type": "error", - "name": "InterchainClientV1__ZeroReceiver", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainClientV1__ZeroRequiredResponses", - "inputs": [] + "name": "InterchainClientV1__TxVersionMismatch", + "inputs": [ + { + "name": "txVersion", + "type": "uint16", + "internalType": "uint16" + }, + { + "name": "required", + "type": "uint16", + "internalType": "uint16" + } + ] }, { "type": "error", - "name": "OptionsLib__IncorrectVersion", + "name": "OptionsLib__VersionInvalid", "inputs": [ { "name": "version", @@ -955,12 +1111,7 @@ }, { "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -968,6 +1119,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/arb_sepolia/InterchainDB.json b/packages/contracts-communication/deployments/arb_sepolia/InterchainDB.json index 03f8543645..f2c822b9ac 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/InterchainDB.json +++ b/packages/contracts-communication/deployments/arb_sepolia/InterchainDB.json @@ -1,9 +1,9 @@ { - "address": "0x4361F461c5Df0DCf109BA2CF0E46dfA26e73f54f", + "address": "0x943257aE5037f5997ab302c4E158EFe48BBCE89d", "constructorArgs": "0x", "receipt": { - "hash": "0x21b9241ce3df67fc40b23144c84cf01f3edf075fad4ebb9e0b0196a0462501a4", - "blockNumber": 34357459 + "hash": "0xa0586b35600ba365c0628535ca64244ab0c581c2f24394ad7d806c7b2c78b843", + "blockNumber": 41156776 }, "abi": [ { @@ -21,7 +21,7 @@ }, { "type": "function", - "name": "checkVerification", + "name": "checkBatchVerification", "inputs": [ { "name": "dstModule", @@ -29,9 +29,9 @@ "internalType": "address" }, { - "name": "entry", + "name": "batch", "type": "tuple", - "internalType": "struct InterchainEntry", + "internalType": "struct InterchainBatch", "components": [ { "name": "srcChainId", @@ -44,26 +44,11 @@ "internalType": "uint64" }, { - "name": "entryIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "srcWriter", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "dataHash", + "name": "batchRoot", "type": "bytes32", "internalType": "bytes32" } ] - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" } ], "outputs": [ @@ -159,6 +144,57 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getBatchRoot", + "inputs": [ + { + "name": "entry", + "type": "tuple", + "internalType": "struct InterchainEntry", + "components": [ + { + "name": "srcChainId", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "srcWriter", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "dataHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "proof", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "pure" + }, { "type": "function", "name": "getBatchSize", @@ -281,6 +317,25 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getVersionedBatch", + "inputs": [ + { + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "versionedBatch", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "requestBatchVerification", @@ -489,10 +544,10 @@ }, { "type": "error", - "name": "InterchainDB__BatchDoesNotExist", + "name": "BatchingV1__EntryIndexNotZero", "inputs": [ { - "name": "dbNonce", + "name": "entryIndex", "type": "uint64", "internalType": "uint64" } @@ -500,18 +555,12 @@ }, { "type": "error", - "name": "InterchainDB__BatchNotFinalized", - "inputs": [ - { - "name": "dbNonce", - "type": "uint64", - "internalType": "uint64" - } - ] + "name": "BatchingV1__ProofNotEmpty", + "inputs": [] }, { "type": "error", - "name": "InterchainDB__ConflictingBatches", + "name": "InterchainDB__BatchConflict", "inputs": [ { "name": "module", @@ -549,55 +598,55 @@ }, { "type": "error", - "name": "InterchainDB__EntryIndexOutOfRange", + "name": "InterchainDB__BatchVersionMismatch", "inputs": [ { - "name": "dbNonce", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "entryIndex", - "type": "uint64", - "internalType": "uint64" + "name": "version", + "type": "uint16", + "internalType": "uint16" }, { - "name": "batchSize", - "type": "uint64", - "internalType": "uint64" + "name": "required", + "type": "uint16", + "internalType": "uint16" } ] }, { "type": "error", - "name": "InterchainDB__IncorrectFeeAmount", + "name": "InterchainDB__ChainIdNotRemote", "inputs": [ { - "name": "actualFee", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "expectedFee", - "type": "uint256", - "internalType": "uint256" + "name": "chainId", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainDB__InvalidBatchVersion", + "name": "InterchainDB__EntryIndexOutOfRange", "inputs": [ { - "name": "version", - "type": "uint16", - "internalType": "uint16" + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "batchSize", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainDB__InvalidEntryRange", + "name": "InterchainDB__EntryRangeInvalid", "inputs": [ { "name": "dbNonce", @@ -618,20 +667,25 @@ }, { "type": "error", - "name": "InterchainDB__NoModulesSpecified", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainDB__SameChainId", + "name": "InterchainDB__FeeAmountBelowMin", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "feeAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, + { + "type": "error", + "name": "InterchainDB__ModulesNotProvided", + "inputs": [] + }, { "type": "error", "name": "SafeCastOverflowedUintDowncast", @@ -650,7 +704,7 @@ }, { "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", diff --git a/packages/contracts-communication/deployments/arb_sepolia/LegacyPingPong.json b/packages/contracts-communication/deployments/arb_sepolia/LegacyPingPong.json index 219931a00e..a732565350 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/LegacyPingPong.json +++ b/packages/contracts-communication/deployments/arb_sepolia/LegacyPingPong.json @@ -1,9 +1,9 @@ { - "address": "0xe5E2b525eaD8268b37764960ff38Bc915F2E8Bed", + "address": "0x30591abA8544f4DeB7Bc9846D303787482c75e13", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xf179a40cf7501865e642f943bbe3cdc0b3d9f48408c80d1d6da064693b2667bf", - "blockNumber": 34358837 + "hash": "0xfd725f0ef3a9ac913f78c709b3b15ad32c9c82c258daf1136d14fad2a3528968", + "blockNumber": 41157765 }, "abi": [ { @@ -336,7 +336,7 @@ }, { "type": "error", - "name": "LegacyReceiver__BalanceTooLow", + "name": "LegacyReceiver__BalanceBelowMin", "inputs": [ { "name": "actual", @@ -352,7 +352,7 @@ }, { "type": "error", - "name": "LegacyReceiver__NotMessageBus", + "name": "LegacyReceiver__CallerNotMessageBus", "inputs": [ { "name": "caller", @@ -363,34 +363,34 @@ }, { "type": "error", - "name": "LegacyReceiver__NotTrustedRemote", + "name": "LegacyReceiver__ChainIdNotRemote", "inputs": [ { "name": "chainId", "type": "uint256", "internalType": "uint256" - }, - { - "name": "srcCaller", - "type": "bytes32", - "internalType": "bytes32" } ] }, { "type": "error", - "name": "LegacyReceiver__SameChainId", + "name": "LegacyReceiver__SrcCallerNotTrusted", "inputs": [ { "name": "chainId", "type": "uint256", "internalType": "uint256" + }, + { + "name": "srcCaller", + "type": "bytes32", + "internalType": "bytes32" } ] }, { "type": "error", - "name": "LegacyReceiver__TrustedRemoteNotSet", + "name": "LegacyReceiver__TrustedRemoteZeroAddress", "inputs": [ { "name": "chainId", diff --git a/packages/contracts-communication/deployments/arb_sepolia/MessageBus.json b/packages/contracts-communication/deployments/arb_sepolia/MessageBus.json index e9fc456666..140b75fa1a 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/MessageBus.json +++ b/packages/contracts-communication/deployments/arb_sepolia/MessageBus.json @@ -1,9 +1,9 @@ { - "address": "0x8CeFD8163CaBd9BF67071E68668a959CFC50D5E2", + "address": "0x64118e2E5581FeC4496ef6886Abd24027A7f31A8", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0x682484b618db694da7d564f30f320ecb4ea3ebd39f62a2221ad373a208c9a459", - "blockNumber": 34689167 + "hash": "0xfbd3d645cb9117dd0e0918fb0f5112e61fd5df2d6a811e169dbdc3b252e70607", + "blockNumber": 41157647 }, "abi": [ { @@ -192,6 +192,16 @@ "name": "optimisticPeriod", "type": "uint256", "internalType": "uint256" + }, + { + "name": "guardFlag", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "guard", + "type": "address", + "internalType": "address" } ] } @@ -567,21 +577,14 @@ "name": "setAppConfigV1", "inputs": [ { - "name": "appConfig", - "type": "tuple", - "internalType": "struct AppConfigV1", - "components": [ - { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" - } - ] + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ], "outputs": [], @@ -996,31 +999,31 @@ }, { "type": "error", - "name": "InterchainApp__AlreadyLatestClient", + "name": "InterchainApp__AppConfigInvalid", "inputs": [ { - "name": "client", - "type": "address", - "internalType": "address" + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "InterchainApp__AppZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__BalanceTooLow", + "name": "InterchainApp__BalanceBelowMin", "inputs": [ { - "name": "actual", + "name": "balance", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -1028,10 +1031,10 @@ }, { "type": "error", - "name": "InterchainApp__ClientAlreadyAdded", + "name": "InterchainApp__CallerNotInterchainClient", "inputs": [ { - "name": "client", + "name": "caller", "type": "address", "internalType": "address" } @@ -1039,31 +1042,21 @@ }, { "type": "error", - "name": "InterchainApp__InterchainClientZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__InvalidAppConfig", + "name": "InterchainApp__ChainIdNotRemote", "inputs": [ { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" + "name": "chainId", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainApp__ModuleAlreadyAdded", + "name": "InterchainApp__InterchainClientAlreadyAdded", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -1071,10 +1064,10 @@ }, { "type": "error", - "name": "InterchainApp__ModuleNotAdded", + "name": "InterchainApp__InterchainClientAlreadyLatest", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -1082,12 +1075,12 @@ }, { "type": "error", - "name": "InterchainApp__ModuleZeroAddress", + "name": "InterchainApp__InterchainClientZeroAddress", "inputs": [] }, { "type": "error", - "name": "InterchainApp__NotEVMLinkedApp", + "name": "InterchainApp__LinkedAppNotEVM", "inputs": [ { "name": "linkedApp", @@ -1098,10 +1091,10 @@ }, { "type": "error", - "name": "InterchainApp__NotInterchainClient", + "name": "InterchainApp__ModuleAlreadyAdded", "inputs": [ { - "name": "account", + "name": "module", "type": "address", "internalType": "address" } @@ -1109,18 +1102,23 @@ }, { "type": "error", - "name": "InterchainApp__ReceiverNotSet", + "name": "InterchainApp__ModuleNotAdded", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "module", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "InterchainApp__SameChainId", + "name": "InterchainApp__ModuleZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__ReceiverZeroAddress", "inputs": [ { "name": "chainId", @@ -1131,7 +1129,12 @@ }, { "type": "error", - "name": "InterchainApp__SenderNotAllowed", + "name": "InterchainApp__RemoteAppZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__SrcSenderNotAllowed", "inputs": [ { "name": "srcChainId", @@ -1147,7 +1150,7 @@ }, { "type": "error", - "name": "LegacyOptionsLib__InvalidOptions", + "name": "LegacyOptionsLib__PayloadInvalid", "inputs": [ { "name": "legacyOpts", @@ -1158,7 +1161,7 @@ }, { "type": "error", - "name": "MessageBus__NotEVMReceiver", + "name": "MessageBus__ReceiverNotEVM", "inputs": [ { "name": "receiver", diff --git a/packages/contracts-communication/deployments/arb_sepolia/PingPongApp.json b/packages/contracts-communication/deployments/arb_sepolia/PingPongApp.json index 71f6e0226c..41f0eb254e 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/PingPongApp.json +++ b/packages/contracts-communication/deployments/arb_sepolia/PingPongApp.json @@ -1,9 +1,9 @@ { - "address": "0x8420DCB8dD1a5eDEa2F71bE26aD275d3fa61F3CF", + "address": "0x47E4b9e5F7Cb65E5c37D866F1Ad4470BF42e3068", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0x13d399215b2fef40032f26d1f63f9d1f701fd9537e3cbfddec6c145050205a0f", - "blockNumber": 34689074 + "hash": "0x76f8ae1503d7e18d455c17a151bbb214a55c1f0d6e5597b7e4bcd76fd730dc5d", + "blockNumber": 41157550 }, "abi": [ { @@ -143,6 +143,16 @@ "name": "optimisticPeriod", "type": "uint256", "internalType": "uint256" + }, + { + "name": "guardFlag", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "guard", + "type": "address", + "internalType": "address" } ] } @@ -483,21 +493,14 @@ "name": "setAppConfigV1", "inputs": [ { - "name": "appConfig", - "type": "tuple", - "internalType": "struct AppConfigV1", - "components": [ - { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" - } - ] + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ], "outputs": [], @@ -892,31 +895,31 @@ }, { "type": "error", - "name": "InterchainApp__AlreadyLatestClient", + "name": "InterchainApp__AppConfigInvalid", "inputs": [ { - "name": "client", - "type": "address", - "internalType": "address" + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "InterchainApp__AppZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__BalanceTooLow", + "name": "InterchainApp__BalanceBelowMin", "inputs": [ { - "name": "actual", + "name": "balance", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -924,10 +927,10 @@ }, { "type": "error", - "name": "InterchainApp__ClientAlreadyAdded", + "name": "InterchainApp__CallerNotInterchainClient", "inputs": [ { - "name": "client", + "name": "caller", "type": "address", "internalType": "address" } @@ -935,31 +938,21 @@ }, { "type": "error", - "name": "InterchainApp__InterchainClientZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__InvalidAppConfig", + "name": "InterchainApp__ChainIdNotRemote", "inputs": [ { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" + "name": "chainId", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainApp__ModuleAlreadyAdded", + "name": "InterchainApp__InterchainClientAlreadyAdded", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -967,10 +960,10 @@ }, { "type": "error", - "name": "InterchainApp__ModuleNotAdded", + "name": "InterchainApp__InterchainClientAlreadyLatest", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -978,12 +971,12 @@ }, { "type": "error", - "name": "InterchainApp__ModuleZeroAddress", + "name": "InterchainApp__InterchainClientZeroAddress", "inputs": [] }, { "type": "error", - "name": "InterchainApp__NotEVMLinkedApp", + "name": "InterchainApp__LinkedAppNotEVM", "inputs": [ { "name": "linkedApp", @@ -994,10 +987,10 @@ }, { "type": "error", - "name": "InterchainApp__NotInterchainClient", + "name": "InterchainApp__ModuleAlreadyAdded", "inputs": [ { - "name": "account", + "name": "module", "type": "address", "internalType": "address" } @@ -1005,18 +998,23 @@ }, { "type": "error", - "name": "InterchainApp__ReceiverNotSet", + "name": "InterchainApp__ModuleNotAdded", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "module", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "InterchainApp__SameChainId", + "name": "InterchainApp__ModuleZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__ReceiverZeroAddress", "inputs": [ { "name": "chainId", @@ -1027,7 +1025,12 @@ }, { "type": "error", - "name": "InterchainApp__SenderNotAllowed", + "name": "InterchainApp__RemoteAppZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__SrcSenderNotAllowed", "inputs": [ { "name": "srcChainId", diff --git a/packages/contracts-communication/deployments/arb_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json b/packages/contracts-communication/deployments/arb_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json index b31f7bbe17..2c4ea11e1e 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json +++ b/packages/contracts-communication/deployments/arb_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json @@ -1,9 +1,9 @@ { - "address": "0x7533f98Dc830E48f528e147fd31eA416F32a23d2", + "address": "0xFE299dd970f5E36b4dA31664e570EA511eb61a06", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xb1d77fb5b688a59dedcfd6b2b46322bdc1b8fc75092d1f95ffb1fc03bd3793f0", - "blockNumber": 34357743 + "hash": "0xe5bf1cf943d043fb36e72b542eb0570794b26580fc6114225cd7184d3c02a031", + "blockNumber": 41157184 }, "abi": [ { diff --git a/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.Implementation.json b/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.Implementation.json index df912e0cfb..b540e7908f 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.Implementation.json +++ b/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.Implementation.json @@ -1,9 +1,9 @@ { - "address": "0xCa30ceFa3321fB5B0eb32006ebC9f26757c78C9C", + "address": "0xAF3b718677Ae400Cb321A2143966cbae762A9EF6", "constructorArgs": "0x", "receipt": { - "hash": "0x6c222560826cb45e3eb293900a9f594e033465e1cf8b49ed2e5f66a23e38368d", - "blockNumber": 34357738 + "hash": "0x3f3223d43182992af1e8f5ae12b5952b86cbff6c070f90aefdb0c21a70ea42ee", + "blockNumber": 41157181 }, "abi": [ { @@ -50,6 +50,13 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "claimFees", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "executorEOA", @@ -76,6 +83,45 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getClaimableAmount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerFraction", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerReward", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getExecutionFee", @@ -105,6 +151,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getFeeRecipient", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getRoleAdmin", @@ -212,7 +271,7 @@ }, { "type": "function", - "name": "requestExecution", + "name": "requestTxExecution", "inputs": [ { "name": "dstChainId", @@ -229,11 +288,6 @@ "type": "bytes32", "internalType": "bytes32" }, - { - "name": "executionFee", - "type": "uint256", - "internalType": "uint256" - }, { "name": "options", "type": "bytes", @@ -241,7 +295,7 @@ } ], "outputs": [], - "stateMutability": "nonpayable" + "stateMutability": "payable" }, { "type": "function", @@ -261,6 +315,19 @@ "outputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "setClaimerFraction", + "inputs": [ + { + "name": "claimerFraction_", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "setExecutorEOA", @@ -319,6 +386,19 @@ ], "stateMutability": "view" }, + { + "type": "event", + "name": "ClaimerFractionSet", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "ExecutionRequested", @@ -334,6 +414,12 @@ "type": "address", "indexed": false, "internalType": "address" + }, + { + "name": "executionFee", + "type": "uint256", + "indexed": false, + "internalType": "uint256" } ], "anonymous": false @@ -351,6 +437,50 @@ ], "anonymous": false }, + { + "type": "event", + "name": "FeeRecipientSet", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "FeesClaimed", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimedFees", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "claimer", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimerReward", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "GasOracleSet", @@ -486,6 +616,48 @@ } ] }, + { + "type": "error", + "name": "AddressInsufficientBalance", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__ClaimerFractionAboveMax", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxAllowed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__FeeAmountZero", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimableFees__FeeRecipientZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "FailedInnerCall", + "inputs": [] + }, { "type": "error", "name": "InvalidInitialization", @@ -498,7 +670,7 @@ }, { "type": "error", - "name": "OptionsLib__IncorrectVersion", + "name": "OptionsLib__VersionInvalid", "inputs": [ { "name": "version", @@ -509,15 +681,20 @@ }, { "type": "error", - "name": "SynapseExecutionService__FeeAmountTooLow", + "name": "SynapseExecutionService__ExecutorZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "SynapseExecutionService__FeeAmountBelowMin", "inputs": [ { - "name": "actual", + "name": "feeAmount", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -525,7 +702,18 @@ }, { "type": "error", - "name": "SynapseExecutionService__GasOracleNotSet", + "name": "SynapseExecutionService__GasOracleNotContract", + "inputs": [ + { + "name": "gasOracle", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "SynapseExecutionService__GasOracleZeroAddress", "inputs": [] }, { @@ -541,17 +729,7 @@ }, { "type": "error", - "name": "SynapseExecutionService__ZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -559,6 +737,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.json b/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.json index e8f1ba36f4..d190477191 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.json +++ b/packages/contracts-communication/deployments/arb_sepolia/SynapseExecutionServiceV1.json @@ -1,9 +1,9 @@ { - "address": "0xEB8f63C97B3B1dF220e3f61534F12cEC68573924", + "address": "0x16006C628A3164B8D6C25E6Ad4Facf59cD205AB8", "constructorArgs": "0x", "receipt": { - "hash": "0xb1d77fb5b688a59dedcfd6b2b46322bdc1b8fc75092d1f95ffb1fc03bd3793f0", - "blockNumber": 34357743 + "hash": "0xe5bf1cf943d043fb36e72b542eb0570794b26580fc6114225cd7184d3c02a031", + "blockNumber": 41157184 }, "abi": [ { @@ -50,6 +50,13 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "claimFees", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "executorEOA", @@ -76,6 +83,45 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getClaimableAmount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerFraction", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerReward", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getExecutionFee", @@ -105,6 +151,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getFeeRecipient", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getRoleAdmin", @@ -212,7 +271,7 @@ }, { "type": "function", - "name": "requestExecution", + "name": "requestTxExecution", "inputs": [ { "name": "dstChainId", @@ -229,11 +288,6 @@ "type": "bytes32", "internalType": "bytes32" }, - { - "name": "executionFee", - "type": "uint256", - "internalType": "uint256" - }, { "name": "options", "type": "bytes", @@ -241,7 +295,7 @@ } ], "outputs": [], - "stateMutability": "nonpayable" + "stateMutability": "payable" }, { "type": "function", @@ -261,6 +315,19 @@ "outputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "setClaimerFraction", + "inputs": [ + { + "name": "claimerFraction_", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "setExecutorEOA", @@ -319,6 +386,19 @@ ], "stateMutability": "view" }, + { + "type": "event", + "name": "ClaimerFractionSet", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "ExecutionRequested", @@ -334,6 +414,12 @@ "type": "address", "indexed": false, "internalType": "address" + }, + { + "name": "executionFee", + "type": "uint256", + "indexed": false, + "internalType": "uint256" } ], "anonymous": false @@ -351,6 +437,50 @@ ], "anonymous": false }, + { + "type": "event", + "name": "FeeRecipientSet", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "FeesClaimed", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimedFees", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "claimer", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimerReward", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "GasOracleSet", @@ -486,6 +616,48 @@ } ] }, + { + "type": "error", + "name": "AddressInsufficientBalance", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__ClaimerFractionAboveMax", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxAllowed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__FeeAmountZero", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimableFees__FeeRecipientZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "FailedInnerCall", + "inputs": [] + }, { "type": "error", "name": "InvalidInitialization", @@ -498,7 +670,7 @@ }, { "type": "error", - "name": "OptionsLib__IncorrectVersion", + "name": "OptionsLib__VersionInvalid", "inputs": [ { "name": "version", @@ -509,15 +681,20 @@ }, { "type": "error", - "name": "SynapseExecutionService__FeeAmountTooLow", + "name": "SynapseExecutionService__ExecutorZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "SynapseExecutionService__FeeAmountBelowMin", "inputs": [ { - "name": "actual", + "name": "feeAmount", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -525,7 +702,18 @@ }, { "type": "error", - "name": "SynapseExecutionService__GasOracleNotSet", + "name": "SynapseExecutionService__GasOracleNotContract", + "inputs": [ + { + "name": "gasOracle", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "SynapseExecutionService__GasOracleZeroAddress", "inputs": [] }, { @@ -541,17 +729,7 @@ }, { "type": "error", - "name": "SynapseExecutionService__ZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -559,6 +737,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/arb_sepolia/SynapseGasOracleV1.json b/packages/contracts-communication/deployments/arb_sepolia/SynapseGasOracleV1.json index 88b8accd26..c8cbf548d8 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/SynapseGasOracleV1.json +++ b/packages/contracts-communication/deployments/arb_sepolia/SynapseGasOracleV1.json @@ -1,9 +1,9 @@ { - "address": "0x7a73234588e80aDccFEc41C8d3a6daEF6C4b56C3", + "address": "0x7e09589fB70C26Eaf06a4b4f6Ccbc57F932c1f58", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xed1d493409c8b7ddaf3b9812d4d4cee712e96ffdd76e9202a9bbc7ef3a683df1", - "blockNumber": 34358058 + "hash": "0xb0f6fa4e5961308a38226077cde7b87f6e476a63069511387950ece71224b70c", + "blockNumber": 41156962 }, "abi": [ { @@ -430,7 +430,7 @@ }, { "type": "error", - "name": "SynapseGasOracleV1__NativePriceNotSet", + "name": "SynapseGasOracleV1__ChainIdNotRemote", "inputs": [ { "name": "chainId", @@ -441,12 +441,7 @@ }, { "type": "error", - "name": "SynapseGasOracleV1__NativePriceZero", - "inputs": [] - }, - { - "type": "error", - "name": "SynapseGasOracleV1__NotRemoteChainId", + "name": "SynapseGasOracleV1__NativePriceNotSet", "inputs": [ { "name": "chainId", @@ -454,6 +449,11 @@ "internalType": "uint64" } ] + }, + { + "type": "error", + "name": "SynapseGasOracleV1__NativePriceZero", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/arb_sepolia/SynapseModule.json b/packages/contracts-communication/deployments/arb_sepolia/SynapseModule.json index a7c8dd2cc6..7f7d029796 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/SynapseModule.json +++ b/packages/contracts-communication/deployments/arb_sepolia/SynapseModule.json @@ -1,9 +1,9 @@ { - "address": "0xC13e2b478f6531Ef096FF05733Ed65E3bc7fC5AF", - "constructorArgs": "0x0000000000000000000000004361f461c5df0dcf109ba2cf0e46dfa26e73f54f000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", + "address": "0xE55659865F84B97eAEc00C1a8F4175F852523E25", + "constructorArgs": "0x000000000000000000000000943257ae5037f5997ab302c4e158efe48bbce89d000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xf175001a19ff7c0f377fffa3d6c5c178a8cc4beba5301dc73b849ba0b5920c10", - "blockNumber": 34357595 + "hash": "0x1e0cc9db61e5b1930e96e6c13cb3d4f6548c1d2faee7084c466c79f454602a40", + "blockNumber": 41157077 }, "abi": [ { @@ -83,7 +83,7 @@ }, { "type": "function", - "name": "feeCollector", + "name": "gasOracle", "inputs": [], "outputs": [ { @@ -96,20 +96,20 @@ }, { "type": "function", - "name": "gasOracle", + "name": "getClaimableAmount", "inputs": [], "outputs": [ { "name": "", - "type": "address", - "internalType": "address" + "type": "uint256", + "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", - "name": "getClaimFeeAmount", + "name": "getClaimerFraction", "inputs": [], "outputs": [ { @@ -122,7 +122,7 @@ }, { "type": "function", - "name": "getClaimFeeFraction", + "name": "getClaimerReward", "inputs": [], "outputs": [ { @@ -133,6 +133,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getFeeRecipient", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getModuleFee", @@ -276,6 +289,11 @@ "type": "uint64", "internalType": "uint64" }, + { + "name": "batchNonce", + "type": "uint64", + "internalType": "uint64" + }, { "name": "versionedBatch", "type": "bytes", @@ -287,10 +305,10 @@ }, { "type": "function", - "name": "setClaimFeeFraction", + "name": "setClaimerFraction", "inputs": [ { - "name": "claimFeeFraction", + "name": "claimerFraction", "type": "uint256", "internalType": "uint256" } @@ -300,10 +318,10 @@ }, { "type": "function", - "name": "setFeeCollector", + "name": "setFeeRecipient", "inputs": [ { - "name": "feeCollector_", + "name": "feeRecipient", "type": "address", "internalType": "address" } @@ -438,10 +456,10 @@ }, { "type": "event", - "name": "ClaimFeeFractionSet", + "name": "ClaimerFractionSet", "inputs": [ { - "name": "claimFeeFraction", + "name": "claimerFraction", "type": "uint256", "indexed": false, "internalType": "uint256" @@ -451,10 +469,10 @@ }, { "type": "event", - "name": "FeeCollectorSet", + "name": "FeeRecipientSet", "inputs": [ { - "name": "feeCollector", + "name": "feeRecipient", "type": "address", "indexed": false, "internalType": "address" @@ -467,13 +485,13 @@ "name": "FeesClaimed", "inputs": [ { - "name": "feeCollector", + "name": "feeRecipient", "type": "address", "indexed": false, "internalType": "address" }, { - "name": "collectedFees", + "name": "claimedFees", "type": "uint256", "indexed": false, "internalType": "uint256" @@ -485,7 +503,7 @@ "internalType": "address" }, { - "name": "claimerFee", + "name": "claimerReward", "type": "uint256", "indexed": false, "internalType": "uint256" @@ -634,31 +652,15 @@ }, { "type": "error", - "name": "FailedInnerCall", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainModule__IncorrectSourceChainId", + "name": "ClaimableFees__ClaimerFractionAboveMax", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - } - ] - }, - { - "type": "error", - "name": "InterchainModule__InsufficientFee", - "inputs": [ - { - "name": "actual", + "name": "claimerFraction", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "maxAllowed", "type": "uint256", "internalType": "uint256" } @@ -666,7 +668,22 @@ }, { "type": "error", - "name": "InterchainModule__NotInterchainDB", + "name": "ClaimableFees__FeeAmountZero", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimableFees__FeeRecipientZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "FailedInnerCall", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainModule__CallerNotInterchainDB", "inputs": [ { "name": "caller", @@ -677,7 +694,7 @@ }, { "type": "error", - "name": "InterchainModule__SameChainId", + "name": "InterchainModule__ChainIdNotRemote", "inputs": [ { "name": "chainId", @@ -688,21 +705,26 @@ }, { "type": "error", - "name": "OwnableInvalidOwner", + "name": "InterchainModule__FeeAmountBelowMin", "inputs": [ { - "name": "owner", - "type": "address", - "internalType": "address" + "name": "feeAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "OwnableUnauthorizedAccount", + "name": "OwnableInvalidOwner", "inputs": [ { - "name": "account", + "name": "owner", "type": "address", "internalType": "address" } @@ -710,18 +732,18 @@ }, { "type": "error", - "name": "SynapseModule__ClaimFeeFractionExceedsMax", + "name": "OwnableUnauthorizedAccount", "inputs": [ { - "name": "claimFeeFraction", - "type": "uint256", - "internalType": "uint256" + "name": "account", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "SynapseModule__FeeCollectorNotSet", + "name": "SynapseModule__FeeRecipientZeroAddress", "inputs": [] }, { @@ -737,28 +759,33 @@ }, { "type": "error", - "name": "SynapseModule__GasOracleNotSet", + "name": "SynapseModule__GasOracleZeroAddress", "inputs": [] }, { "type": "error", - "name": "SynapseModule__NoFeesToClaim", + "name": "ThresholdECDSA__RecoveredSignersNotSorted", "inputs": [] }, { "type": "error", - "name": "ThresholdECDSA__AlreadySigner", + "name": "ThresholdECDSA__SignaturesAmountBelowThreshold", "inputs": [ { - "name": "account", - "type": "address", - "internalType": "address" + "name": "signaturesAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "threshold", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "ThresholdECDSA__IncorrectSignaturesLength", + "name": "ThresholdECDSA__SignaturesPayloadLengthInvalid", "inputs": [ { "name": "length", @@ -769,65 +796,50 @@ }, { "type": "error", - "name": "ThresholdECDSA__InvalidSignature", + "name": "ThresholdECDSA__SignerAlreadyAdded", "inputs": [ { - "name": "signature", - "type": "bytes", - "internalType": "bytes" + "name": "account", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "ThresholdECDSA__NotEnoughSignatures", + "name": "ThresholdECDSA__SignerNotAdded", "inputs": [ { - "name": "provided", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "threshold", - "type": "uint256", - "internalType": "uint256" + "name": "account", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "ThresholdECDSA__NotSigner", + "name": "ThresholdECDSA__SignerRecoveryFailed", "inputs": [ { - "name": "account", - "type": "address", - "internalType": "address" + "name": "signature", + "type": "bytes", + "internalType": "bytes" } ] }, { "type": "error", - "name": "ThresholdECDSA__RecoveredSignersNotSorted", + "name": "ThresholdECDSA__SignerZeroAddress", "inputs": [] }, { "type": "error", - "name": "ThresholdECDSA__ZeroAddress", + "name": "ThresholdECDSA__ThresholdZero", "inputs": [] }, { "type": "error", - "name": "ThresholdECDSA__ZeroThreshold", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -835,6 +847,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/arb_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json b/packages/contracts-communication/deployments/arb_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json index 42612ffa2c..be62ba1643 100644 --- a/packages/contracts-communication/deployments/arb_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json +++ b/packages/contracts-communication/deployments/arb_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json @@ -1,9 +1,9 @@ { - "address": "0xEB8f63C97B3B1dF220e3f61534F12cEC68573924", - "constructorArgs": "0x000000000000000000000000ca30cefa3321fb5b0eb32006ebc9f26757c78c9c000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000", + "address": "0x16006C628A3164B8D6C25E6Ad4Facf59cD205AB8", + "constructorArgs": "0x000000000000000000000000af3b718677ae400cb321a2143966cbae762a9ef6000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000", "receipt": { - "hash": "0xb1d77fb5b688a59dedcfd6b2b46322bdc1b8fc75092d1f95ffb1fc03bd3793f0", - "blockNumber": 34357743 + "hash": "0xe5bf1cf943d043fb36e72b542eb0570794b26580fc6114225cd7184d3c02a031", + "blockNumber": 41157184 }, "abi": [ { diff --git a/packages/contracts-communication/deployments/eth_sepolia/ExecutionFees.json b/packages/contracts-communication/deployments/eth_sepolia/ExecutionFees.json deleted file mode 100644 index 5e8a4a4dea..0000000000 --- a/packages/contracts-communication/deployments/eth_sepolia/ExecutionFees.json +++ /dev/null @@ -1,534 +0,0 @@ -{ - "address": "0x0fD219B1FabBb32ab9d7FcA3A5bF91C74bBCD32B", - "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", - "receipt": { - "hash": "0xbdead5adc2bf95d810b99cfdef3d2129809c99a3e753321c60b98a4555f34be0", - "blockNumber": 5712792 - }, - "abi": [ - { - "type": "constructor", - "inputs": [ - { - "name": "admin", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "RECORDER_ROLE", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "accumulatedRewards", - "inputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "totalAccumulated", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "addExecutionFee", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [], - "stateMutability": "payable" - }, - { - "type": "function", - "name": "claimExecutionFees", - "inputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "executionFee", - "inputs": [ - { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "fee", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "getRoleAdmin", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "grantRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "hasRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "recordExecutor", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "recordedExecutor", - "inputs": [ - { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - } - ], - "outputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "renounceRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "callerConfirmation", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "revokeRole", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "internalType": "address" - } - ], - "outputs": [], - "stateMutability": "nonpayable" - }, - { - "type": "function", - "name": "supportsInterface", - "inputs": [ - { - "name": "interfaceId", - "type": "bytes4", - "internalType": "bytes4" - } - ], - "outputs": [ - { - "name": "", - "type": "bool", - "internalType": "bool" - } - ], - "stateMutability": "view" - }, - { - "type": "function", - "name": "unclaimedRewards", - "inputs": [ - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ], - "outputs": [ - { - "name": "totalClaimed", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, - { - "type": "event", - "name": "ExecutionFeeAdded", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "totalFee", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExecutionFeesAwarded", - "inputs": [ - { - "name": "executor", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExecutionFeesClaimed", - "inputs": [ - { - "name": "executor", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "amount", - "type": "uint256", - "indexed": false, - "internalType": "uint256" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "ExecutorRecorded", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "indexed": false, - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "executor", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleAdminChanged", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "previousAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "newAdminRole", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleGranted", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "event", - "name": "RoleRevoked", - "inputs": [ - { - "name": "role", - "type": "bytes32", - "indexed": true, - "internalType": "bytes32" - }, - { - "name": "account", - "type": "address", - "indexed": true, - "internalType": "address" - }, - { - "name": "sender", - "type": "address", - "indexed": true, - "internalType": "address" - } - ], - "anonymous": false - }, - { - "type": "error", - "name": "AccessControlBadConfirmation", - "inputs": [] - }, - { - "type": "error", - "name": "AccessControlUnauthorizedAccount", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - }, - { - "name": "neededRole", - "type": "bytes32", - "internalType": "bytes32" - } - ] - }, - { - "type": "error", - "name": "AddressInsufficientBalance", - "inputs": [ - { - "name": "account", - "type": "address", - "internalType": "address" - } - ] - }, - { - "type": "error", - "name": "ExecutionFees__AlreadyRecorded", - "inputs": [ - { - "name": "dstChainId", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "transactionId", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "executor", - "type": "address", - "internalType": "address" - } - ] - }, - { - "type": "error", - "name": "ExecutionFees__ZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "ExecutionFees__ZeroAmount", - "inputs": [] - }, - { - "type": "error", - "name": "FailedInnerCall", - "inputs": [] - } - ] -} \ No newline at end of file diff --git a/packages/contracts-communication/deployments/eth_sepolia/InterchainClientV1.json b/packages/contracts-communication/deployments/eth_sepolia/InterchainClientV1.json index 42239195d4..af4c42f9f9 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/InterchainClientV1.json +++ b/packages/contracts-communication/deployments/eth_sepolia/InterchainClientV1.json @@ -1,9 +1,9 @@ { - "address": "0xfcb988E117dbAa8c8b48047afd7c22d4a8321bCA", - "constructorArgs": "0x0000000000000000000000001ce3a9d87a26ae56a43a5bb1d5e9a8d14550d0a4000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", + "address": "0x6bAb7426099ba52ac37F309903169C4c0A5f7534", + "constructorArgs": "0x0000000000000000000000008d50e833331a0d01d6f286881ce2c3a5dad12e26000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xddb503be3046c579c38d71df13ac6eda25a43a54adbc7ae1796df99ef419a769", - "blockNumber": 5712788 + "hash": "0xed5ce09fc0316bff5d6f4046e6337b5ce510e75629b1073c61c9d1c7fc4763b0", + "blockNumber": 5847938 }, "abi": [ { @@ -79,6 +79,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "defaultGuard", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "encodeTransaction", @@ -140,19 +153,6 @@ ], "stateMutability": "pure" }, - { - "type": "function", - "name": "executionFees", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "address", - "internalType": "address" - } - ], - "stateMutability": "view" - }, { "type": "function", "name": "getAppReceivingConfigV1", @@ -178,6 +178,16 @@ "name": "optimisticPeriod", "type": "uint256", "internalType": "uint256" + }, + { + "name": "guardFlag", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "guard", + "type": "address", + "internalType": "address" } ] }, @@ -304,6 +314,82 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getTxReadinessV1", + "inputs": [ + { + "name": "icTx", + "type": "tuple", + "internalType": "struct InterchainTransaction", + "components": [ + { + "name": "srcChainId", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "dstChainId", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "srcSender", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "dstReceiver", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "options", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "message", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "proof", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "outputs": [ + { + "name": "status", + "type": "uint8", + "internalType": "enum IInterchainClientV1.TxReadiness" + }, + { + "name": "firstArg", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "secondArg", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "interchainExecute", @@ -495,10 +581,10 @@ }, { "type": "function", - "name": "setExecutionFees", + "name": "setDefaultGuard", "inputs": [ { - "name": "executionFees_", + "name": "guard", "type": "address", "internalType": "address" } @@ -563,10 +649,10 @@ }, { "type": "event", - "name": "ExecutionFeesSet", + "name": "DefaultGuardSet", "inputs": [ { - "name": "executionFees", + "name": "guard", "type": "address", "indexed": false, "internalType": "address" @@ -755,7 +841,7 @@ }, { "type": "error", - "name": "AppConfigLib__IncorrectVersion", + "name": "AppConfigLib__VersionInvalid", "inputs": [ { "name": "version", @@ -766,23 +852,34 @@ }, { "type": "error", - "name": "InterchainClientV1__FeeAmountTooLow", + "name": "BatchingV1__EntryIndexNotZero", "inputs": [ { - "name": "actual", - "type": "uint256", - "internalType": "uint256" - }, + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "BatchingV1__ProofNotEmpty", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainClientV1__BatchConflict", + "inputs": [ { - "name": "required", - "type": "uint256", - "internalType": "uint256" + "name": "module", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "InterchainClientV1__IncorrectDstChainId", + "name": "InterchainClientV1__ChainIdNotLinked", "inputs": [ { "name": "chainId", @@ -793,15 +890,42 @@ }, { "type": "error", - "name": "InterchainClientV1__IncorrectMsgValue", + "name": "InterchainClientV1__ChainIdNotRemote", "inputs": [ { - "name": "actual", + "name": "chainId", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__DstChainIdNotLocal", + "inputs": [ + { + "name": "chainId", + "type": "uint64", + "internalType": "uint64" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__ExecutionServiceZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainClientV1__FeeAmountBelowMin", + "inputs": [ + { + "name": "feeAmount", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -809,29 +933,28 @@ }, { "type": "error", - "name": "InterchainClientV1__InvalidTransactionVersion", + "name": "InterchainClientV1__GasLeftBelowMin", "inputs": [ { - "name": "version", - "type": "uint16", - "internalType": "uint16" + "name": "gasLeft", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "InterchainClientV1__NoLinkedClient", - "inputs": [ - { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - } - ] + "name": "InterchainClientV1__GuardZeroAddress", + "inputs": [] }, { "type": "error", - "name": "InterchainClientV1__NotEVMClient", + "name": "InterchainClientV1__LinkedClientNotEVM", "inputs": [ { "name": "client", @@ -842,15 +965,10 @@ }, { "type": "error", - "name": "InterchainClientV1__NotEnoughGasSupplied", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainClientV1__NotEnoughResponses", + "name": "InterchainClientV1__MsgValueMismatch", "inputs": [ { - "name": "actual", + "name": "msgValue", "type": "uint256", "internalType": "uint256" }, @@ -863,12 +981,44 @@ }, { "type": "error", - "name": "InterchainClientV1__NotRemoteChainId", + "name": "InterchainClientV1__ReceiverNotICApp", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "receiver", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__ReceiverZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainClientV1__ReceiverZeroRequiredResponses", + "inputs": [ + { + "name": "receiver", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "InterchainClientV1__ResponsesAmountBelowMin", + "inputs": [ + { + "name": "responsesAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, @@ -896,17 +1046,23 @@ }, { "type": "error", - "name": "InterchainClientV1__ZeroReceiver", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainClientV1__ZeroRequiredResponses", - "inputs": [] + "name": "InterchainClientV1__TxVersionMismatch", + "inputs": [ + { + "name": "txVersion", + "type": "uint16", + "internalType": "uint16" + }, + { + "name": "required", + "type": "uint16", + "internalType": "uint16" + } + ] }, { "type": "error", - "name": "OptionsLib__IncorrectVersion", + "name": "OptionsLib__VersionInvalid", "inputs": [ { "name": "version", @@ -955,12 +1111,7 @@ }, { "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -968,6 +1119,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/eth_sepolia/InterchainDB.json b/packages/contracts-communication/deployments/eth_sepolia/InterchainDB.json index 73c1e7a9a5..5f3dfa8a04 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/InterchainDB.json +++ b/packages/contracts-communication/deployments/eth_sepolia/InterchainDB.json @@ -1,9 +1,9 @@ { - "address": "0x1Ce3a9d87A26Ae56a43a5BB1D5e9A8D14550D0a4", + "address": "0x8d50e833331A0D01d6F286881ce2C3A5DAD12e26", "constructorArgs": "0x", "receipt": { - "hash": "0x2efd5f79af2d52c4e382c4b016a50323f1e2724d54375d4a31ffd26d2eef2115", - "blockNumber": 5712772 + "hash": "0xd3cc2a04b2f37aa61ac965af8264198031d925236d55825b124fd3da9358e491", + "blockNumber": 5847919 }, "abi": [ { @@ -21,7 +21,7 @@ }, { "type": "function", - "name": "checkVerification", + "name": "checkBatchVerification", "inputs": [ { "name": "dstModule", @@ -29,9 +29,9 @@ "internalType": "address" }, { - "name": "entry", + "name": "batch", "type": "tuple", - "internalType": "struct InterchainEntry", + "internalType": "struct InterchainBatch", "components": [ { "name": "srcChainId", @@ -44,26 +44,11 @@ "internalType": "uint64" }, { - "name": "entryIndex", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "srcWriter", - "type": "bytes32", - "internalType": "bytes32" - }, - { - "name": "dataHash", + "name": "batchRoot", "type": "bytes32", "internalType": "bytes32" } ] - }, - { - "name": "proof", - "type": "bytes32[]", - "internalType": "bytes32[]" } ], "outputs": [ @@ -159,6 +144,57 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getBatchRoot", + "inputs": [ + { + "name": "entry", + "type": "tuple", + "internalType": "struct InterchainEntry", + "components": [ + { + "name": "srcChainId", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "srcWriter", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "dataHash", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "name": "proof", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "pure" + }, { "type": "function", "name": "getBatchSize", @@ -281,6 +317,25 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getVersionedBatch", + "inputs": [ + { + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + } + ], + "outputs": [ + { + "name": "versionedBatch", + "type": "bytes", + "internalType": "bytes" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "requestBatchVerification", @@ -489,10 +544,10 @@ }, { "type": "error", - "name": "InterchainDB__BatchDoesNotExist", + "name": "BatchingV1__EntryIndexNotZero", "inputs": [ { - "name": "dbNonce", + "name": "entryIndex", "type": "uint64", "internalType": "uint64" } @@ -500,18 +555,12 @@ }, { "type": "error", - "name": "InterchainDB__BatchNotFinalized", - "inputs": [ - { - "name": "dbNonce", - "type": "uint64", - "internalType": "uint64" - } - ] + "name": "BatchingV1__ProofNotEmpty", + "inputs": [] }, { "type": "error", - "name": "InterchainDB__ConflictingBatches", + "name": "InterchainDB__BatchConflict", "inputs": [ { "name": "module", @@ -549,55 +598,55 @@ }, { "type": "error", - "name": "InterchainDB__EntryIndexOutOfRange", + "name": "InterchainDB__BatchVersionMismatch", "inputs": [ { - "name": "dbNonce", - "type": "uint64", - "internalType": "uint64" - }, - { - "name": "entryIndex", - "type": "uint64", - "internalType": "uint64" + "name": "version", + "type": "uint16", + "internalType": "uint16" }, { - "name": "batchSize", - "type": "uint64", - "internalType": "uint64" + "name": "required", + "type": "uint16", + "internalType": "uint16" } ] }, { "type": "error", - "name": "InterchainDB__IncorrectFeeAmount", + "name": "InterchainDB__ChainIdNotRemote", "inputs": [ { - "name": "actualFee", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "expectedFee", - "type": "uint256", - "internalType": "uint256" + "name": "chainId", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainDB__InvalidBatchVersion", + "name": "InterchainDB__EntryIndexOutOfRange", "inputs": [ { - "name": "version", - "type": "uint16", - "internalType": "uint16" + "name": "dbNonce", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "entryIndex", + "type": "uint64", + "internalType": "uint64" + }, + { + "name": "batchSize", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainDB__InvalidEntryRange", + "name": "InterchainDB__EntryRangeInvalid", "inputs": [ { "name": "dbNonce", @@ -618,20 +667,25 @@ }, { "type": "error", - "name": "InterchainDB__NoModulesSpecified", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainDB__SameChainId", + "name": "InterchainDB__FeeAmountBelowMin", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "feeAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, + { + "type": "error", + "name": "InterchainDB__ModulesNotProvided", + "inputs": [] + }, { "type": "error", "name": "SafeCastOverflowedUintDowncast", @@ -650,7 +704,7 @@ }, { "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", diff --git a/packages/contracts-communication/deployments/eth_sepolia/LegacyPingPong.json b/packages/contracts-communication/deployments/eth_sepolia/LegacyPingPong.json index e16b7643a2..8917416e09 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/LegacyPingPong.json +++ b/packages/contracts-communication/deployments/eth_sepolia/LegacyPingPong.json @@ -1,9 +1,9 @@ { - "address": "0x8CdBa6b4de7553E36ed9C755d726b0D02D1873EF", + "address": "0xda3b7cB145EE712b10a00a7A8da33580EB784f1B", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xbac2066b26a5464f307b155855ae7e401c3995d0beb13611fd9cf82b8e7b2428", - "blockNumber": 5712808 + "hash": "0x4a925d88a4d24e6fe2eb5e08c128d0af5790955f2ab65382dd3515a603b9746b", + "blockNumber": 5847953 }, "abi": [ { @@ -336,7 +336,7 @@ }, { "type": "error", - "name": "LegacyReceiver__BalanceTooLow", + "name": "LegacyReceiver__BalanceBelowMin", "inputs": [ { "name": "actual", @@ -352,7 +352,7 @@ }, { "type": "error", - "name": "LegacyReceiver__NotMessageBus", + "name": "LegacyReceiver__CallerNotMessageBus", "inputs": [ { "name": "caller", @@ -363,34 +363,34 @@ }, { "type": "error", - "name": "LegacyReceiver__NotTrustedRemote", + "name": "LegacyReceiver__ChainIdNotRemote", "inputs": [ { "name": "chainId", "type": "uint256", "internalType": "uint256" - }, - { - "name": "srcCaller", - "type": "bytes32", - "internalType": "bytes32" } ] }, { "type": "error", - "name": "LegacyReceiver__SameChainId", + "name": "LegacyReceiver__SrcCallerNotTrusted", "inputs": [ { "name": "chainId", "type": "uint256", "internalType": "uint256" + }, + { + "name": "srcCaller", + "type": "bytes32", + "internalType": "bytes32" } ] }, { "type": "error", - "name": "LegacyReceiver__TrustedRemoteNotSet", + "name": "LegacyReceiver__TrustedRemoteZeroAddress", "inputs": [ { "name": "chainId", diff --git a/packages/contracts-communication/deployments/eth_sepolia/MessageBus.json b/packages/contracts-communication/deployments/eth_sepolia/MessageBus.json index c3db59bdb7..3d09db3334 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/MessageBus.json +++ b/packages/contracts-communication/deployments/eth_sepolia/MessageBus.json @@ -1,9 +1,9 @@ { - "address": "0x8D2F5587f094D97cb6c5607601dDc6b97d486635", + "address": "0x6c10B9C27233E80C8b58EE875a0CaA27D50fd134", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0x78cf1502a921afcf6b158432b829cd40099efbb59cbc6c485bd72f43acbd55e8", - "blockNumber": 5719544 + "hash": "0x7afcd2576d4345567fb842dce302cf0f59d12e34d6ff43fa6ac14db559805f0a", + "blockNumber": 5847948 }, "abi": [ { @@ -192,6 +192,16 @@ "name": "optimisticPeriod", "type": "uint256", "internalType": "uint256" + }, + { + "name": "guardFlag", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "guard", + "type": "address", + "internalType": "address" } ] } @@ -567,21 +577,14 @@ "name": "setAppConfigV1", "inputs": [ { - "name": "appConfig", - "type": "tuple", - "internalType": "struct AppConfigV1", - "components": [ - { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" - } - ] + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ], "outputs": [], @@ -996,31 +999,31 @@ }, { "type": "error", - "name": "InterchainApp__AlreadyLatestClient", + "name": "InterchainApp__AppConfigInvalid", "inputs": [ { - "name": "client", - "type": "address", - "internalType": "address" + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "InterchainApp__AppZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__BalanceTooLow", + "name": "InterchainApp__BalanceBelowMin", "inputs": [ { - "name": "actual", + "name": "balance", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -1028,10 +1031,10 @@ }, { "type": "error", - "name": "InterchainApp__ClientAlreadyAdded", + "name": "InterchainApp__CallerNotInterchainClient", "inputs": [ { - "name": "client", + "name": "caller", "type": "address", "internalType": "address" } @@ -1039,31 +1042,21 @@ }, { "type": "error", - "name": "InterchainApp__InterchainClientZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__InvalidAppConfig", + "name": "InterchainApp__ChainIdNotRemote", "inputs": [ { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" + "name": "chainId", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainApp__ModuleAlreadyAdded", + "name": "InterchainApp__InterchainClientAlreadyAdded", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -1071,10 +1064,10 @@ }, { "type": "error", - "name": "InterchainApp__ModuleNotAdded", + "name": "InterchainApp__InterchainClientAlreadyLatest", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -1082,12 +1075,12 @@ }, { "type": "error", - "name": "InterchainApp__ModuleZeroAddress", + "name": "InterchainApp__InterchainClientZeroAddress", "inputs": [] }, { "type": "error", - "name": "InterchainApp__NotEVMLinkedApp", + "name": "InterchainApp__LinkedAppNotEVM", "inputs": [ { "name": "linkedApp", @@ -1098,10 +1091,10 @@ }, { "type": "error", - "name": "InterchainApp__NotInterchainClient", + "name": "InterchainApp__ModuleAlreadyAdded", "inputs": [ { - "name": "account", + "name": "module", "type": "address", "internalType": "address" } @@ -1109,18 +1102,23 @@ }, { "type": "error", - "name": "InterchainApp__ReceiverNotSet", + "name": "InterchainApp__ModuleNotAdded", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "module", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "InterchainApp__SameChainId", + "name": "InterchainApp__ModuleZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__ReceiverZeroAddress", "inputs": [ { "name": "chainId", @@ -1131,7 +1129,12 @@ }, { "type": "error", - "name": "InterchainApp__SenderNotAllowed", + "name": "InterchainApp__RemoteAppZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__SrcSenderNotAllowed", "inputs": [ { "name": "srcChainId", @@ -1147,7 +1150,7 @@ }, { "type": "error", - "name": "LegacyOptionsLib__InvalidOptions", + "name": "LegacyOptionsLib__PayloadInvalid", "inputs": [ { "name": "legacyOpts", @@ -1158,7 +1161,7 @@ }, { "type": "error", - "name": "MessageBus__NotEVMReceiver", + "name": "MessageBus__ReceiverNotEVM", "inputs": [ { "name": "receiver", diff --git a/packages/contracts-communication/deployments/eth_sepolia/PingPongApp.json b/packages/contracts-communication/deployments/eth_sepolia/PingPongApp.json index a5e2ce8f3f..32f73962b5 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/PingPongApp.json +++ b/packages/contracts-communication/deployments/eth_sepolia/PingPongApp.json @@ -1,9 +1,9 @@ { - "address": "0x8dA1BEd6ff65C7A8f0459822B52f8d40BbB549a0", + "address": "0xD6dCB592B06875214D0D58d777081202034c6756", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0xbd6ad3c6ac55bdc6c1a259cb2cc4d0c51a9aa5b0551eed4636c904ef16204928", - "blockNumber": 5719541 + "hash": "0xa4658be7494a11ff23c21508527a1f8774078709a95a6ca23d4fff0bf3e797f2", + "blockNumber": 5847943 }, "abi": [ { @@ -143,6 +143,16 @@ "name": "optimisticPeriod", "type": "uint256", "internalType": "uint256" + }, + { + "name": "guardFlag", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "guard", + "type": "address", + "internalType": "address" } ] } @@ -483,21 +493,14 @@ "name": "setAppConfigV1", "inputs": [ { - "name": "appConfig", - "type": "tuple", - "internalType": "struct AppConfigV1", - "components": [ - { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" - } - ] + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ], "outputs": [], @@ -892,31 +895,31 @@ }, { "type": "error", - "name": "InterchainApp__AlreadyLatestClient", + "name": "InterchainApp__AppConfigInvalid", "inputs": [ { - "name": "client", - "type": "address", - "internalType": "address" + "name": "requiredResponses", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "optimisticPeriod", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "InterchainApp__AppZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__BalanceTooLow", + "name": "InterchainApp__BalanceBelowMin", "inputs": [ { - "name": "actual", + "name": "balance", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -924,10 +927,10 @@ }, { "type": "error", - "name": "InterchainApp__ClientAlreadyAdded", + "name": "InterchainApp__CallerNotInterchainClient", "inputs": [ { - "name": "client", + "name": "caller", "type": "address", "internalType": "address" } @@ -935,31 +938,21 @@ }, { "type": "error", - "name": "InterchainApp__InterchainClientZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainApp__InvalidAppConfig", + "name": "InterchainApp__ChainIdNotRemote", "inputs": [ { - "name": "requiredResponses", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "optimisticPeriod", - "type": "uint256", - "internalType": "uint256" + "name": "chainId", + "type": "uint64", + "internalType": "uint64" } ] }, { "type": "error", - "name": "InterchainApp__ModuleAlreadyAdded", + "name": "InterchainApp__InterchainClientAlreadyAdded", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -967,10 +960,10 @@ }, { "type": "error", - "name": "InterchainApp__ModuleNotAdded", + "name": "InterchainApp__InterchainClientAlreadyLatest", "inputs": [ { - "name": "module", + "name": "client", "type": "address", "internalType": "address" } @@ -978,12 +971,12 @@ }, { "type": "error", - "name": "InterchainApp__ModuleZeroAddress", + "name": "InterchainApp__InterchainClientZeroAddress", "inputs": [] }, { "type": "error", - "name": "InterchainApp__NotEVMLinkedApp", + "name": "InterchainApp__LinkedAppNotEVM", "inputs": [ { "name": "linkedApp", @@ -994,10 +987,10 @@ }, { "type": "error", - "name": "InterchainApp__NotInterchainClient", + "name": "InterchainApp__ModuleAlreadyAdded", "inputs": [ { - "name": "account", + "name": "module", "type": "address", "internalType": "address" } @@ -1005,18 +998,23 @@ }, { "type": "error", - "name": "InterchainApp__ReceiverNotSet", + "name": "InterchainApp__ModuleNotAdded", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" + "name": "module", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "InterchainApp__SameChainId", + "name": "InterchainApp__ModuleZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__ReceiverZeroAddress", "inputs": [ { "name": "chainId", @@ -1027,7 +1025,12 @@ }, { "type": "error", - "name": "InterchainApp__SenderNotAllowed", + "name": "InterchainApp__RemoteAppZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainApp__SrcSenderNotAllowed", "inputs": [ { "name": "srcChainId", diff --git a/packages/contracts-communication/deployments/eth_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json b/packages/contracts-communication/deployments/eth_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json index 55407af0ce..60c93e2a4e 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json +++ b/packages/contracts-communication/deployments/eth_sepolia/ProxyAdmin.SynapseExecutionServiceV1.json @@ -1,9 +1,9 @@ { - "address": "0xa84ec5D5027E67c20937e1266f2b04F131DA5027", + "address": "0xfc5aa03c3985154eDf6fEF03cECa00214827ff9b", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0x4e22905b6cc1e9ec5436c123c539795cf614e8558ae3f05a74c503961bf9bcde", - "blockNumber": 5712784 + "hash": "0x73205ad465e106e58f9fbe107bddd4267829af811f614957e0c7cae7b549f26b", + "blockNumber": 5847930 }, "abi": [ { diff --git a/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.Implementation.json b/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.Implementation.json index 16b4399608..fb09d304b9 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.Implementation.json +++ b/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.Implementation.json @@ -1,9 +1,9 @@ { - "address": "0xE424490d88562F8123AC756f9A7ffa173630DB4E", + "address": "0xEaF2728Fa62C3acaEA43D796219fc83019C04B2b", "constructorArgs": "0x", "receipt": { - "hash": "0x221171644ba5b06767d060e6e1d69657b686346f97b3c49847c2dfa8b5a5ca67", - "blockNumber": 5712784 + "hash": "0x0bdd2845acd5f2f5734d41303e98f4d6019b680736274983713aa3b7d18925ac", + "blockNumber": 5847930 }, "abi": [ { @@ -50,6 +50,13 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "claimFees", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "executorEOA", @@ -76,6 +83,45 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getClaimableAmount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerFraction", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerReward", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getExecutionFee", @@ -105,6 +151,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getFeeRecipient", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getRoleAdmin", @@ -212,7 +271,7 @@ }, { "type": "function", - "name": "requestExecution", + "name": "requestTxExecution", "inputs": [ { "name": "dstChainId", @@ -229,11 +288,6 @@ "type": "bytes32", "internalType": "bytes32" }, - { - "name": "executionFee", - "type": "uint256", - "internalType": "uint256" - }, { "name": "options", "type": "bytes", @@ -241,7 +295,7 @@ } ], "outputs": [], - "stateMutability": "nonpayable" + "stateMutability": "payable" }, { "type": "function", @@ -261,6 +315,19 @@ "outputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "setClaimerFraction", + "inputs": [ + { + "name": "claimerFraction_", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "setExecutorEOA", @@ -319,6 +386,19 @@ ], "stateMutability": "view" }, + { + "type": "event", + "name": "ClaimerFractionSet", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "ExecutionRequested", @@ -334,6 +414,12 @@ "type": "address", "indexed": false, "internalType": "address" + }, + { + "name": "executionFee", + "type": "uint256", + "indexed": false, + "internalType": "uint256" } ], "anonymous": false @@ -351,6 +437,50 @@ ], "anonymous": false }, + { + "type": "event", + "name": "FeeRecipientSet", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "FeesClaimed", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimedFees", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "claimer", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimerReward", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "GasOracleSet", @@ -486,6 +616,48 @@ } ] }, + { + "type": "error", + "name": "AddressInsufficientBalance", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__ClaimerFractionAboveMax", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxAllowed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__FeeAmountZero", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimableFees__FeeRecipientZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "FailedInnerCall", + "inputs": [] + }, { "type": "error", "name": "InvalidInitialization", @@ -498,7 +670,7 @@ }, { "type": "error", - "name": "OptionsLib__IncorrectVersion", + "name": "OptionsLib__VersionInvalid", "inputs": [ { "name": "version", @@ -509,15 +681,20 @@ }, { "type": "error", - "name": "SynapseExecutionService__FeeAmountTooLow", + "name": "SynapseExecutionService__ExecutorZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "SynapseExecutionService__FeeAmountBelowMin", "inputs": [ { - "name": "actual", + "name": "feeAmount", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -525,7 +702,18 @@ }, { "type": "error", - "name": "SynapseExecutionService__GasOracleNotSet", + "name": "SynapseExecutionService__GasOracleNotContract", + "inputs": [ + { + "name": "gasOracle", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "SynapseExecutionService__GasOracleZeroAddress", "inputs": [] }, { @@ -541,17 +729,7 @@ }, { "type": "error", - "name": "SynapseExecutionService__ZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -559,6 +737,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.json b/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.json index b7fa353329..bc1ab10b80 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.json +++ b/packages/contracts-communication/deployments/eth_sepolia/SynapseExecutionServiceV1.json @@ -1,9 +1,9 @@ { - "address": "0x4fA6eDe8E33e801CADB05eD0675DC6cfcD72ebC8", + "address": "0x6d50A69c8B21C0f8b8d1631f7E4B615d39e2653C", "constructorArgs": "0x", "receipt": { - "hash": "0x4e22905b6cc1e9ec5436c123c539795cf614e8558ae3f05a74c503961bf9bcde", - "blockNumber": 5712784 + "hash": "0x73205ad465e106e58f9fbe107bddd4267829af811f614957e0c7cae7b549f26b", + "blockNumber": 5847930 }, "abi": [ { @@ -50,6 +50,13 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "claimFees", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "executorEOA", @@ -76,6 +83,45 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getClaimableAmount", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerFraction", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getClaimerReward", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getExecutionFee", @@ -105,6 +151,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getFeeRecipient", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getRoleAdmin", @@ -212,7 +271,7 @@ }, { "type": "function", - "name": "requestExecution", + "name": "requestTxExecution", "inputs": [ { "name": "dstChainId", @@ -229,11 +288,6 @@ "type": "bytes32", "internalType": "bytes32" }, - { - "name": "executionFee", - "type": "uint256", - "internalType": "uint256" - }, { "name": "options", "type": "bytes", @@ -241,7 +295,7 @@ } ], "outputs": [], - "stateMutability": "nonpayable" + "stateMutability": "payable" }, { "type": "function", @@ -261,6 +315,19 @@ "outputs": [], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "setClaimerFraction", + "inputs": [ + { + "name": "claimerFraction_", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, { "type": "function", "name": "setExecutorEOA", @@ -319,6 +386,19 @@ ], "stateMutability": "view" }, + { + "type": "event", + "name": "ClaimerFractionSet", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "ExecutionRequested", @@ -334,6 +414,12 @@ "type": "address", "indexed": false, "internalType": "address" + }, + { + "name": "executionFee", + "type": "uint256", + "indexed": false, + "internalType": "uint256" } ], "anonymous": false @@ -351,6 +437,50 @@ ], "anonymous": false }, + { + "type": "event", + "name": "FeeRecipientSet", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "FeesClaimed", + "inputs": [ + { + "name": "feeRecipient", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimedFees", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "claimer", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "claimerReward", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, { "type": "event", "name": "GasOracleSet", @@ -486,6 +616,48 @@ } ] }, + { + "type": "error", + "name": "AddressInsufficientBalance", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__ClaimerFractionAboveMax", + "inputs": [ + { + "name": "claimerFraction", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxAllowed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ClaimableFees__FeeAmountZero", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimableFees__FeeRecipientZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "FailedInnerCall", + "inputs": [] + }, { "type": "error", "name": "InvalidInitialization", @@ -498,7 +670,7 @@ }, { "type": "error", - "name": "OptionsLib__IncorrectVersion", + "name": "OptionsLib__VersionInvalid", "inputs": [ { "name": "version", @@ -509,15 +681,20 @@ }, { "type": "error", - "name": "SynapseExecutionService__FeeAmountTooLow", + "name": "SynapseExecutionService__ExecutorZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "SynapseExecutionService__FeeAmountBelowMin", "inputs": [ { - "name": "actual", + "name": "feeAmount", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "minRequired", "type": "uint256", "internalType": "uint256" } @@ -525,7 +702,18 @@ }, { "type": "error", - "name": "SynapseExecutionService__GasOracleNotSet", + "name": "SynapseExecutionService__GasOracleNotContract", + "inputs": [ + { + "name": "gasOracle", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "SynapseExecutionService__GasOracleZeroAddress", "inputs": [] }, { @@ -541,17 +729,7 @@ }, { "type": "error", - "name": "SynapseExecutionService__ZeroAddress", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -559,6 +737,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/eth_sepolia/SynapseGasOracleV1.json b/packages/contracts-communication/deployments/eth_sepolia/SynapseGasOracleV1.json index 59a2d15eaf..6f3ebe092a 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/SynapseGasOracleV1.json +++ b/packages/contracts-communication/deployments/eth_sepolia/SynapseGasOracleV1.json @@ -1,9 +1,9 @@ { - "address": "0x3BfcE077Cf306E1C7C3300E72aF6eE79AC997eCc", + "address": "0x9AaA36c80F6824c674419Bd0C5F6d76f865295ca", "constructorArgs": "0x000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0x4b36c6953f669d7dc4d5384fac566b25751cab81704318401e2e1ca830219a6c", - "blockNumber": 5712777 + "hash": "0xe0719b81a125e39e9e6b9ee0e0e46777d28752fbab4e03a81a1da3a8c0dbd0e0", + "blockNumber": 5847922 }, "abi": [ { @@ -430,7 +430,7 @@ }, { "type": "error", - "name": "SynapseGasOracleV1__NativePriceNotSet", + "name": "SynapseGasOracleV1__ChainIdNotRemote", "inputs": [ { "name": "chainId", @@ -441,12 +441,7 @@ }, { "type": "error", - "name": "SynapseGasOracleV1__NativePriceZero", - "inputs": [] - }, - { - "type": "error", - "name": "SynapseGasOracleV1__NotRemoteChainId", + "name": "SynapseGasOracleV1__NativePriceNotSet", "inputs": [ { "name": "chainId", @@ -454,6 +449,11 @@ "internalType": "uint64" } ] + }, + { + "type": "error", + "name": "SynapseGasOracleV1__NativePriceZero", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/eth_sepolia/SynapseModule.json b/packages/contracts-communication/deployments/eth_sepolia/SynapseModule.json index 16993bdbf1..e3d8139079 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/SynapseModule.json +++ b/packages/contracts-communication/deployments/eth_sepolia/SynapseModule.json @@ -1,9 +1,9 @@ { - "address": "0x95f2e2fAFE38f2aAdC9F9cBef98785809cc4bb6B", - "constructorArgs": "0x0000000000000000000000001ce3a9d87a26ae56a43a5bb1d5e9a8d14550d0a4000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", + "address": "0x93391bD1De68aFBAB10BB94BF3d36a4484B60eA2", + "constructorArgs": "0x0000000000000000000000008d50e833331a0d01d6f286881ce2c3a5dad12e26000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e4", "receipt": { - "hash": "0x5347793c4471a1d31ce1de3fe07a61ee2f5933e49353ada4673adb4f106e99f3", - "blockNumber": 5712781 + "hash": "0x0283d44cd3da1dbf1b8ceccf1afa57789ef55c57feb03dd9745d05dc437aea40", + "blockNumber": 5847925 }, "abi": [ { @@ -83,7 +83,7 @@ }, { "type": "function", - "name": "feeCollector", + "name": "gasOracle", "inputs": [], "outputs": [ { @@ -96,20 +96,20 @@ }, { "type": "function", - "name": "gasOracle", + "name": "getClaimableAmount", "inputs": [], "outputs": [ { "name": "", - "type": "address", - "internalType": "address" + "type": "uint256", + "internalType": "uint256" } ], "stateMutability": "view" }, { "type": "function", - "name": "getClaimFeeAmount", + "name": "getClaimerFraction", "inputs": [], "outputs": [ { @@ -122,7 +122,7 @@ }, { "type": "function", - "name": "getClaimFeeFraction", + "name": "getClaimerReward", "inputs": [], "outputs": [ { @@ -133,6 +133,19 @@ ], "stateMutability": "view" }, + { + "type": "function", + "name": "getFeeRecipient", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "getModuleFee", @@ -276,6 +289,11 @@ "type": "uint64", "internalType": "uint64" }, + { + "name": "batchNonce", + "type": "uint64", + "internalType": "uint64" + }, { "name": "versionedBatch", "type": "bytes", @@ -287,10 +305,10 @@ }, { "type": "function", - "name": "setClaimFeeFraction", + "name": "setClaimerFraction", "inputs": [ { - "name": "claimFeeFraction", + "name": "claimerFraction", "type": "uint256", "internalType": "uint256" } @@ -300,10 +318,10 @@ }, { "type": "function", - "name": "setFeeCollector", + "name": "setFeeRecipient", "inputs": [ { - "name": "feeCollector_", + "name": "feeRecipient", "type": "address", "internalType": "address" } @@ -438,10 +456,10 @@ }, { "type": "event", - "name": "ClaimFeeFractionSet", + "name": "ClaimerFractionSet", "inputs": [ { - "name": "claimFeeFraction", + "name": "claimerFraction", "type": "uint256", "indexed": false, "internalType": "uint256" @@ -451,10 +469,10 @@ }, { "type": "event", - "name": "FeeCollectorSet", + "name": "FeeRecipientSet", "inputs": [ { - "name": "feeCollector", + "name": "feeRecipient", "type": "address", "indexed": false, "internalType": "address" @@ -467,13 +485,13 @@ "name": "FeesClaimed", "inputs": [ { - "name": "feeCollector", + "name": "feeRecipient", "type": "address", "indexed": false, "internalType": "address" }, { - "name": "collectedFees", + "name": "claimedFees", "type": "uint256", "indexed": false, "internalType": "uint256" @@ -485,7 +503,7 @@ "internalType": "address" }, { - "name": "claimerFee", + "name": "claimerReward", "type": "uint256", "indexed": false, "internalType": "uint256" @@ -634,31 +652,15 @@ }, { "type": "error", - "name": "FailedInnerCall", - "inputs": [] - }, - { - "type": "error", - "name": "InterchainModule__IncorrectSourceChainId", + "name": "ClaimableFees__ClaimerFractionAboveMax", "inputs": [ { - "name": "chainId", - "type": "uint64", - "internalType": "uint64" - } - ] - }, - { - "type": "error", - "name": "InterchainModule__InsufficientFee", - "inputs": [ - { - "name": "actual", + "name": "claimerFraction", "type": "uint256", "internalType": "uint256" }, { - "name": "required", + "name": "maxAllowed", "type": "uint256", "internalType": "uint256" } @@ -666,7 +668,22 @@ }, { "type": "error", - "name": "InterchainModule__NotInterchainDB", + "name": "ClaimableFees__FeeAmountZero", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimableFees__FeeRecipientZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "FailedInnerCall", + "inputs": [] + }, + { + "type": "error", + "name": "InterchainModule__CallerNotInterchainDB", "inputs": [ { "name": "caller", @@ -677,7 +694,7 @@ }, { "type": "error", - "name": "InterchainModule__SameChainId", + "name": "InterchainModule__ChainIdNotRemote", "inputs": [ { "name": "chainId", @@ -688,21 +705,26 @@ }, { "type": "error", - "name": "OwnableInvalidOwner", + "name": "InterchainModule__FeeAmountBelowMin", "inputs": [ { - "name": "owner", - "type": "address", - "internalType": "address" + "name": "feeAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minRequired", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "OwnableUnauthorizedAccount", + "name": "OwnableInvalidOwner", "inputs": [ { - "name": "account", + "name": "owner", "type": "address", "internalType": "address" } @@ -710,18 +732,18 @@ }, { "type": "error", - "name": "SynapseModule__ClaimFeeFractionExceedsMax", + "name": "OwnableUnauthorizedAccount", "inputs": [ { - "name": "claimFeeFraction", - "type": "uint256", - "internalType": "uint256" + "name": "account", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "SynapseModule__FeeCollectorNotSet", + "name": "SynapseModule__FeeRecipientZeroAddress", "inputs": [] }, { @@ -737,28 +759,33 @@ }, { "type": "error", - "name": "SynapseModule__GasOracleNotSet", + "name": "SynapseModule__GasOracleZeroAddress", "inputs": [] }, { "type": "error", - "name": "SynapseModule__NoFeesToClaim", + "name": "ThresholdECDSA__RecoveredSignersNotSorted", "inputs": [] }, { "type": "error", - "name": "ThresholdECDSA__AlreadySigner", + "name": "ThresholdECDSA__SignaturesAmountBelowThreshold", "inputs": [ { - "name": "account", - "type": "address", - "internalType": "address" + "name": "signaturesAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "threshold", + "type": "uint256", + "internalType": "uint256" } ] }, { "type": "error", - "name": "ThresholdECDSA__IncorrectSignaturesLength", + "name": "ThresholdECDSA__SignaturesPayloadLengthInvalid", "inputs": [ { "name": "length", @@ -769,65 +796,50 @@ }, { "type": "error", - "name": "ThresholdECDSA__InvalidSignature", + "name": "ThresholdECDSA__SignerAlreadyAdded", "inputs": [ { - "name": "signature", - "type": "bytes", - "internalType": "bytes" + "name": "account", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "ThresholdECDSA__NotEnoughSignatures", + "name": "ThresholdECDSA__SignerNotAdded", "inputs": [ { - "name": "provided", - "type": "uint256", - "internalType": "uint256" - }, - { - "name": "threshold", - "type": "uint256", - "internalType": "uint256" + "name": "account", + "type": "address", + "internalType": "address" } ] }, { "type": "error", - "name": "ThresholdECDSA__NotSigner", + "name": "ThresholdECDSA__SignerRecoveryFailed", "inputs": [ { - "name": "account", - "type": "address", - "internalType": "address" + "name": "signature", + "type": "bytes", + "internalType": "bytes" } ] }, { "type": "error", - "name": "ThresholdECDSA__RecoveredSignersNotSorted", + "name": "ThresholdECDSA__SignerZeroAddress", "inputs": [] }, { "type": "error", - "name": "ThresholdECDSA__ZeroAddress", + "name": "ThresholdECDSA__ThresholdZero", "inputs": [] }, { "type": "error", - "name": "ThresholdECDSA__ZeroThreshold", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__PrecompileFailed", - "inputs": [] - }, - { - "type": "error", - "name": "VersionedPayload__TooShort", + "name": "VersionedPayload__PayloadTooShort", "inputs": [ { "name": "versionedPayload", @@ -835,6 +847,11 @@ "internalType": "bytes" } ] + }, + { + "type": "error", + "name": "VersionedPayload__PrecompileFailed", + "inputs": [] } ] } \ No newline at end of file diff --git a/packages/contracts-communication/deployments/eth_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json b/packages/contracts-communication/deployments/eth_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json index 1a4151703e..344b1837d4 100644 --- a/packages/contracts-communication/deployments/eth_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json +++ b/packages/contracts-communication/deployments/eth_sepolia/TransparentUpgradeableProxy.SynapseExecutionServiceV1.json @@ -1,9 +1,9 @@ { - "address": "0x4fA6eDe8E33e801CADB05eD0675DC6cfcD72ebC8", - "constructorArgs": "0x000000000000000000000000e424490d88562f8123ac756f9a7ffa173630db4e000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000", + "address": "0x6d50A69c8B21C0f8b8d1631f7E4B615d39e2653C", + "constructorArgs": "0x000000000000000000000000eaf2728fa62c3acaea43d796219fc83019c04b2b000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000e7353bedc72d29f99d6ca5cde69f807cce5d57e400000000000000000000000000000000000000000000000000000000", "receipt": { - "hash": "0x4e22905b6cc1e9ec5436c123c539795cf614e8558ae3f05a74c503961bf9bcde", - "blockNumber": 5712784 + "hash": "0x73205ad465e106e58f9fbe107bddd4267829af811f614957e0c7cae7b549f26b", + "blockNumber": 5847930 }, "abi": [ { diff --git a/packages/contracts-communication/package.json b/packages/contracts-communication/package.json index d32f04bcc7..143201cc37 100644 --- a/packages/contracts-communication/package.json +++ b/packages/contracts-communication/package.json @@ -1,6 +1,6 @@ { "name": "contracts-communication", - "version": "1.5.4", + "version": "1.6.1", "private": true, "files": [ "contracts/*.sol" diff --git a/packages/contracts-communication/script/testnet-config.sh b/packages/contracts-communication/script/testnet-config.sh index 2b754d8884..e00dcff127 100755 --- a/packages/contracts-communication/script/testnet-config.sh +++ b/packages/contracts-communication/script/testnet-config.sh @@ -18,7 +18,6 @@ yarn fsr-str script/config/ConfigureSynapseModule.s.sol "$chainName" "$walletNam yarn fsr-str script/config/ConfigureSynapseExecutionServiceV1.s.sol "$chainName" "$walletName" testnet "$@" # Client contracts yarn fsr-str script/config/ConfigureClientV1.s.sol "$chainName" "$walletName" testnet "$@" -yarn fsr script/config/ConfigureExecutionFees.s.sol "$chainName" "$walletName" "$@" # Ping-Pong App yarn fsr-str script/config/ConfigurePingPongApp.s.sol "$chainName" "$walletName" testnet "$@" # Legacy contracts diff --git a/packages/contracts-communication/script/testnet-deploy.sh b/packages/contracts-communication/script/testnet-deploy.sh index 5a10092a64..1f2cd5d66f 100755 --- a/packages/contracts-communication/script/testnet-deploy.sh +++ b/packages/contracts-communication/script/testnet-deploy.sh @@ -22,7 +22,6 @@ yarn fsr script/deploy/DeploySynapseExecutionServiceV1.s.sol "$chainName" "$wall yarn vp "$chainName" SynapseExecutionServiceV1 # Client contracts yarn fsr script/deploy/DeployInterchainClientV1.s.sol "$chainName" "$walletName" "$@" -yarn fsr-str script/deploy/DeployWithMsgSender.s.sol "$chainName" "$walletName" ExecutionFees "$@" # Ping-Pong App yarn fsr-str script/deploy/DeployWithMsgSender.s.sol "$chainName" "$walletName" PingPongApp "$@" # Legacy contracts diff --git a/packages/contracts-communication/test/InterchainClientV1.Base.t.sol b/packages/contracts-communication/test/InterchainClientV1.Base.t.sol index eac3911852..3ba8525657 100644 --- a/packages/contracts-communication/test/InterchainClientV1.Base.t.sol +++ b/packages/contracts-communication/test/InterchainClientV1.Base.t.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.20; import {InterchainClientV1, InterchainClientV1Events, IInterchainClientV1} from "../contracts/InterchainClientV1.sol"; import {IInterchainApp} from "../contracts/interfaces/IInterchainApp.sol"; import {AppConfigV1} from "../contracts/libs/AppConfig.sol"; -import {BatchingV1Lib} from "../contracts/libs/BatchingV1.sol"; import {InterchainTxDescriptor, InterchainTransaction} from "../contracts/libs/InterchainTransaction.sol"; import {OptionsLib} from "../contracts/libs/Options.sol"; @@ -76,8 +75,8 @@ abstract contract InterchainClientV1BaseTest is Test, InterchainClientV1Events { // ═════════════════════════════════════════════ EXPECT (REVERTS) ══════════════════════════════════════════════════ - function expectRevertBatchConflict(address module) internal { - vm.expectRevert(abi.encodeWithSelector(IInterchainClientV1.InterchainClientV1__BatchConflict.selector, module)); + function expectRevertEntryConflict(address module) internal { + vm.expectRevert(abi.encodeWithSelector(IInterchainClientV1.InterchainClientV1__EntryConflict.selector, module)); } function expectRevertFeeAmountBelowMin(uint256 feeAmount, uint256 minRequired) internal { @@ -94,20 +93,12 @@ abstract contract InterchainClientV1BaseTest is Test, InterchainClientV1Events { ); } - function expectRevertEntryIndexNotZero(uint64 entryIndex) internal { - vm.expectRevert(abi.encodeWithSelector(BatchingV1Lib.BatchingV1__EntryIndexNotZero.selector, entryIndex)); - } - function expectRevertMsgValueMismatch(uint256 actual, uint256 required) internal { vm.expectRevert( abi.encodeWithSelector(IInterchainClientV1.InterchainClientV1__MsgValueMismatch.selector, actual, required) ); } - function expectRevertProofNotEmpty() internal { - vm.expectRevert(BatchingV1Lib.BatchingV1__ProofNotEmpty.selector); - } - function expectRevertTxVersionMismatch(uint16 version, uint16 required) internal { vm.expectRevert( abi.encodeWithSelector( @@ -218,7 +209,6 @@ abstract contract InterchainClientV1BaseTest is Test, InterchainClientV1Events { emit InterchainTransactionSent({ transactionId: desc.transactionId, dbNonce: desc.dbNonce, - entryIndex: desc.entryIndex, dstChainId: icTx.dstChainId, srcSender: icTx.srcSender, dstReceiver: icTx.dstReceiver, @@ -241,28 +231,15 @@ abstract contract InterchainClientV1BaseTest is Test, InterchainClientV1Events { emit InterchainTransactionReceived({ transactionId: desc.transactionId, dbNonce: desc.dbNonce, - entryIndex: desc.entryIndex, srcChainId: icTx.srcChainId, srcSender: icTx.srcSender, dstReceiver: icTx.dstReceiver }); } - function expectEventExecutionProofWritten( - bytes32 transactionId, - uint64 localDbNonce, - uint64 localEntryIndex, - address executor - ) - internal - { + function expectEventExecutionProofWritten(bytes32 transactionId, uint64 localDbNonce, address executor) internal { vm.expectEmit(address(icClient)); - emit ExecutionProofWritten({ - transactionId: transactionId, - dbNonce: localDbNonce, - entryIndex: localEntryIndex, - executor: executor - }); + emit ExecutionProofWritten({transactionId: transactionId, dbNonce: localDbNonce, executor: executor}); } // ════════════════════════════════════════════════ ASSERTIONS ═════════════════════════════════════════════════════ @@ -275,7 +252,6 @@ abstract contract InterchainClientV1BaseTest is Test, InterchainClientV1Events { view { assertEq(desc.dbNonce, icTx.dbNonce, "!desc.dbNonce"); - assertEq(desc.entryIndex, icTx.entryIndex, "!desc.entryIndex"); assertEq(desc.transactionId, keccak256(getEncodedTx(icTx)), "!desc.transactionId"); } @@ -285,7 +261,6 @@ abstract contract InterchainClientV1BaseTest is Test, InterchainClientV1Events { assertEq(icTx.dstChainId, expected.dstChainId, "!dstChainId"); assertEq(icTx.dstReceiver, expected.dstReceiver, "!dstReceiver"); assertEq(icTx.dbNonce, expected.dbNonce, "!dbNonce"); - assertEq(icTx.entryIndex, expected.entryIndex, "!entryIndex"); assertEq(icTx.options, expected.options, "!options"); assertEq(icTx.message, expected.message, "!message"); } diff --git a/packages/contracts-communication/test/InterchainClientV1.Dst.t.sol b/packages/contracts-communication/test/InterchainClientV1.Dst.t.sol index 25572732b8..f62786ccb6 100644 --- a/packages/contracts-communication/test/InterchainClientV1.Dst.t.sol +++ b/packages/contracts-communication/test/InterchainClientV1.Dst.t.sol @@ -3,8 +3,7 @@ pragma solidity 0.8.20; import {IInterchainClientV1} from "../contracts/interfaces/IInterchainClientV1.sol"; import {AppConfigV1} from "../contracts/libs/AppConfig.sol"; -import {InterchainBatch} from "../contracts/libs/InterchainBatch.sol"; -import {InterchainEntryLib} from "../contracts/libs/InterchainEntry.sol"; +import {InterchainEntry, InterchainEntryLib} from "../contracts/libs/InterchainEntry.sol"; import {OptionsV1} from "../contracts/libs/Options.sol"; import {VersionedPayloadLib} from "../contracts/libs/VersionedPayload.sol"; @@ -33,10 +32,8 @@ import {InterchainDBMock} from "./mocks/InterchainDBMock.sol"; /// 5. Mark transaction as executed and emit an event. abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { uint64 public constant MOCK_DB_NONCE = 444; - uint64 public constant MOCK_ENTRY_INDEX = 0; uint64 public constant MOCK_LOCAL_DB_NONCE = 123; - uint64 public constant MOCK_LOCAL_ENTRY_INDEX = 0; uint256 public constant BIGGER_PERIOD = 7 days; @@ -57,8 +54,6 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { address public receiverEOA = makeAddr("Receiver EOA"); address public receiverNotICApp; - bytes32[] public emptyProof; - address[] public oneModuleA; address[] public twoModules; @@ -67,7 +62,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { // - Almost verified: verified exactly "optimistic period" ago // - Just verified: verified exactly "optimistic period + 1 second" ago // - Over verified: verified long ago - // - Conflict: module verified a conflicting batch + // - Conflict: module verified a conflicting entry // Only "just verified" and "over verified" should be considered as verified. uint256 public constant INITIAL_TS = 1_704_067_200; // 2024-01-01 00:00:00 UTC @@ -105,25 +100,16 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { ) internal { - InterchainBatch memory batch = InterchainBatch({ + InterchainEntry memory entry = InterchainEntry({ srcChainId: REMOTE_CHAIN_ID, dbNonce: desc.dbNonce, - batchRoot: InterchainEntryLib.getEntryValue({srcWriter: MOCK_REMOTE_CLIENT, dataHash: desc.transactionId}) + entryValue: InterchainEntryLib.getEntryValue({srcWriter: MOCK_REMOTE_CLIENT, digest: desc.transactionId}) }); vm.mockCall( - icDB, abi.encodeCall(InterchainDBMock.checkBatchVerification, (dstModule, batch)), abi.encode(verifiedAt) + icDB, abi.encodeCall(InterchainDBMock.checkEntryVerification, (dstModule, entry)), abi.encode(verifiedAt) ); } - /// @dev Override the local DB's returned next entry index (both for reads and writes) - function mockLocalNextEntryIndex(uint64 dbNonce, uint64 entryIndex) internal { - bytes memory returnData = abi.encode(dbNonce, entryIndex); - // Use partial calldata to override return values for calls to these functions with any arguments. - vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.getNextEntryIndex.selector), returnData); - vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.writeEntry.selector), returnData); - vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.writeEntryWithVerification.selector), returnData); - } - // ═════════════════════════════════════════════════ TEST DATA ═════════════════════════════════════════════════════ function getOptions() internal view virtual returns (OptionsV1 memory); @@ -181,7 +167,6 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { dstChainId: LOCAL_CHAIN_ID, dstReceiver: dstReceiverBytes32, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, options: encodedOptions, message: MOCK_MESSAGE }); @@ -197,19 +182,14 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { } function getTxDescriptor(InterchainTransaction memory icTx) internal view returns (InterchainTxDescriptor memory) { - return InterchainTxDescriptor({ - dbNonce: icTx.dbNonce, - entryIndex: icTx.entryIndex, - transactionId: keccak256(getEncodedTx(icTx)) - }); + return InterchainTxDescriptor({dbNonce: icTx.dbNonce, transactionId: keccak256(getEncodedTx(icTx))}); } // ══════════════════════════════════════════════ TEST ASSERTIONS ══════════════════════════════════════════════════ function expectAppReceiveCall(OptionsV1 memory options) internal { bytes memory expectedCalldata = abi.encodeCall( - InterchainAppMock.appReceive, - (REMOTE_CHAIN_ID, MOCK_SRC_SENDER, MOCK_DB_NONCE, MOCK_ENTRY_INDEX, MOCK_MESSAGE) + InterchainAppMock.appReceive, (REMOTE_CHAIN_ID, MOCK_SRC_SENDER, MOCK_DB_NONCE, MOCK_MESSAGE) ); vm.expectCall({ callee: dstReceiver, @@ -266,21 +246,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { internal view { - assertCorrectReadiness(icTx, emptyProof, expected, expectedFirstArg, expectedSecondArg); - } - - function assertCorrectReadiness( - InterchainTransaction memory icTx, - bytes32[] memory proof, - IInterchainClientV1.TxReadiness expected, - uint256 expectedFirstArg, - uint256 expectedSecondArg - ) - internal - view - { - (IInterchainClientV1.TxReadiness actual, bytes32 firstArg, bytes32 secondArg) = - icClient.getTxReadinessV1(icTx, proof); + (IInterchainClientV1.TxReadiness actual, bytes32 firstArg, bytes32 secondArg) = icClient.getTxReadinessV1(icTx); assertEq(uint256(actual), uint256(expected)); assertEq(firstArg, bytes32(expectedFirstArg)); assertEq(secondArg, bytes32(expectedSecondArg)); @@ -288,11 +254,11 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { // ═══════════════════════════════════════════════ TEST HELPERS ════════════════════════════════════════════════════ - function executeTransaction(bytes memory encodedTx, bytes32[] memory proof) internal { + function executeTransaction(bytes memory encodedTx) internal { OptionsV1 memory options = getOptions(); deal(executor, options.gasAirdrop); vm.prank(executor); - icClient.interchainExecute{value: options.gasAirdrop}(options.gasLimit, encodedTx, proof); + icClient.interchainExecute{value: options.gasAirdrop}(options.gasLimit, encodedTx); } function prepareExecuteTest( @@ -322,7 +288,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { verificationTimes: toArr(OVER_VERIFIED, OVER_VERIFIED) }); bytes memory encodedTx = getEncodedTx(icTx); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); skip(1 days); } @@ -342,9 +308,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { expectAppReceiveCall(options); expectEventInterchainTransactionReceived(icTx, desc); bytes memory encodedTx = getEncodedTx(icTx); - assertTrue(icClient.isExecutable(encodedTx, emptyProof)); + assertTrue(icClient.isExecutable(encodedTx)); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.Ready); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.AlreadyExecuted, uint256(desc.transactionId)); assertExecutorSaved(icTx, desc); assertEq(dstReceiver.balance, options.gasAirdrop); @@ -369,23 +335,23 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { { (InterchainTransaction memory icTx,) = prepareExecuteTest(required, guardFlag, times); bytes memory encodedTx = getEncodedTx(icTx); - assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.BatchAwaitingResponses, actual, required); + assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.EntryAwaitingResponses, actual, required); expectRevertResponsesAmountBelowMin({actual: actual, required: required}); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertResponsesAmountBelowMin({actual: actual, required: required}); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } - /// @dev Execute the scenario where a batch conflict has been detected. + /// @dev Execute the scenario where an entry conflict has been detected. /// Both `isExecutable` and `interchainExecute` should revert. - function checkBatchConflict(address module, uint256 required, uint256 guardFlag, uint256[] memory times) internal { + function checkEntryConflict(address module, uint256 required, uint256 guardFlag, uint256[] memory times) internal { (InterchainTransaction memory icTx,) = prepareExecuteTest(required, guardFlag, times); bytes memory encodedTx = getEncodedTx(icTx); - assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.BatchConflict, module); - expectRevertBatchConflict(module); - icClient.isExecutable(encodedTx, emptyProof); - expectRevertBatchConflict(module); - executeTransaction(encodedTx, emptyProof); + assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.EntryConflict, module); + expectRevertEntryConflict(module); + icClient.isExecutable(encodedTx); + expectRevertEntryConflict(module); + executeTransaction(encodedTx); } function checkScenario(uint256 required, uint256 guardFlag, uint256 indexA, uint256 indexB) internal { @@ -394,11 +360,11 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { uint256[] memory times = toArr(timeA, timeB); // Check for conflicts if (timeA == CONFLICT) { - checkBatchConflict({module: icModuleA, required: required, guardFlag: guardFlag, times: times}); + checkEntryConflict({module: icModuleA, required: required, guardFlag: guardFlag, times: times}); return; } if (timeB == CONFLICT) { - checkBatchConflict({module: icModuleB, required: required, guardFlag: guardFlag, times: times}); + checkEntryConflict({module: icModuleB, required: required, guardFlag: guardFlag, times: times}); return; } uint256 actual = 0; @@ -436,7 +402,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { addGuardConflict(defaultGuard); uint256 timeA = getTimestampFixture(indexA); uint256 timeB = getTimestampFixture(indexB); - checkBatchConflict({module: defaultGuard, required: 1, guardFlag: GUARD_DEFAULT, times: toArr(timeA, timeB)}); + checkEntryConflict({module: defaultGuard, required: 1, guardFlag: GUARD_DEFAULT, times: toArr(timeA, timeB)}); } function test_execute_1_2_customGuard(uint256 indexA, uint256 indexB) public { @@ -448,7 +414,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { addGuardConflict(customGuard); uint256 timeA = getTimestampFixture(indexA); uint256 timeB = getTimestampFixture(indexB); - checkBatchConflict({module: customGuard, required: 1, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); + checkEntryConflict({module: customGuard, required: 1, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); } /// @dev Default guard conflict should not affect the behavior if the app opted-in for a custom guard. @@ -464,7 +430,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { addGuardConflict(customGuard); uint256 timeA = getTimestampFixture(indexA); uint256 timeB = getTimestampFixture(indexB); - checkBatchConflict({module: customGuard, required: 1, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); + checkEntryConflict({module: customGuard, required: 1, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); } // ═════════════════════════════════════ APP CONFIG: 2 OUT OF 2 RESPONSES ══════════════════════════════════════════ @@ -488,7 +454,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { addGuardConflict(defaultGuard); uint256 timeA = getTimestampFixture(indexA); uint256 timeB = getTimestampFixture(indexB); - checkBatchConflict({module: defaultGuard, required: 2, guardFlag: GUARD_DEFAULT, times: toArr(timeA, timeB)}); + checkEntryConflict({module: defaultGuard, required: 2, guardFlag: GUARD_DEFAULT, times: toArr(timeA, timeB)}); } function test_execute_2_2_customGuard(uint256 indexA, uint256 indexB) public { @@ -500,7 +466,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { addGuardConflict(customGuard); uint256 timeA = getTimestampFixture(indexA); uint256 timeB = getTimestampFixture(indexB); - checkBatchConflict({module: customGuard, required: 2, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); + checkEntryConflict({module: customGuard, required: 2, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); } /// @dev Default guard conflict should not affect the behavior if the app opted-in for a custom guard. @@ -516,7 +482,7 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { addGuardConflict(customGuard); uint256 timeA = getTimestampFixture(indexA); uint256 timeB = getTimestampFixture(indexB); - checkBatchConflict({module: customGuard, required: 2, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); + checkEntryConflict({module: customGuard, required: 2, guardFlag: GUARD_CUSTOM, times: toArr(timeA, timeB)}); } // ═══════════════════════════════════════════ EXECUTE: MISC REVERTS ═══════════════════════════════════════════════ @@ -533,9 +499,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory invalidVersionTx = VersionedPayloadLib.encodeVersionedPayload(version, abi.encode(icTx)); makeTxDescriptorExecutable(getTxDescriptor(icTx)); expectRevertTxVersionMismatch(version, CLIENT_VERSION); - icClient.isExecutable(invalidVersionTx, emptyProof); + icClient.isExecutable(invalidVersionTx); expectRevertTxVersionMismatch(version, CLIENT_VERSION); - executeTransaction(invalidVersionTx, emptyProof); + executeTransaction(invalidVersionTx); } function test_execute_revert_srcChainNotRemote() public { @@ -544,9 +510,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = encodeAndMakeExecutable(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.UndeterminedRevert); expectRevertChainIdNotRemote(LOCAL_CHAIN_ID); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertChainIdNotRemote(LOCAL_CHAIN_ID); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_srcChainNotLinked() public { @@ -555,9 +521,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = encodeAndMakeExecutable(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.UndeterminedRevert); expectRevertChainIdNotLinked(UNKNOWN_CHAIN_ID); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertChainIdNotLinked(UNKNOWN_CHAIN_ID); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_dstChainIncorrect() public { @@ -566,31 +532,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = encodeAndMakeExecutable(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.TxWrongDstChainId, UNKNOWN_CHAIN_ID); expectRevertDstChainIdNotLocal(UNKNOWN_CHAIN_ID); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertDstChainIdNotLocal(UNKNOWN_CHAIN_ID); - executeTransaction(encodedTx, emptyProof); - } - - function test_execute_revert_revert_nonZeroEntryIndex() public { - (InterchainTransaction memory icTx,) = constructInterchainTx(); - icTx.entryIndex = 1; - bytes memory encodedTx = encodeAndMakeExecutable(icTx); - assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.UndeterminedRevert); - expectRevertEntryIndexNotZero(icTx.entryIndex); - icClient.isExecutable(encodedTx, emptyProof); - expectRevertEntryIndexNotZero(icTx.entryIndex); - executeTransaction(encodedTx, emptyProof); - } - - function test_execute_revert_revert_nonEmptyProof() public { - (InterchainTransaction memory icTx,) = constructInterchainTx(); - bytes memory encodedTx = encodeAndMakeExecutable(icTx); - bytes32[] memory proof = new bytes32[](1); - assertCorrectReadiness(icTx, proof, IInterchainClientV1.TxReadiness.UndeterminedRevert, 0, 0); - expectRevertProofNotEmpty(); - icClient.isExecutable(encodedTx, proof); - expectRevertProofNotEmpty(); - executeTransaction(encodedTx, proof); + executeTransaction(encodedTx); } function test_execute_revert_emptyOptions() public { @@ -599,9 +543,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.UndeterminedRevert); // OptionsLib doesn't have a specific error for this case, so we expect a generic revert during decoding. vm.expectRevert(); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); vm.expectRevert(); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_invalidOptionsV0() public { @@ -611,9 +555,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = encodeAndMakeExecutable(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.UndeterminedRevert); expectRevertVersionInvalid(0); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertVersionInvalid(0); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_invalidOptionsV1() public { @@ -625,9 +569,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.UndeterminedRevert); // OptionsLib doesn't have a specific error for this case, so we expect a generic revert during decoding. vm.expectRevert(); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); vm.expectRevert(); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_receiverEOA() public { @@ -636,9 +580,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = encodeAndMakeExecutable(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.ReceiverNotICApp, receiverEOA); expectRevertReceiverNotICApp(receiverEOA); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertReceiverNotICApp(receiverEOA); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_receiverNotICApp() public { @@ -647,9 +591,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = encodeAndMakeExecutable(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.ReceiverNotICApp, receiverNotICApp); expectRevertReceiverNotICApp(receiverNotICApp); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertReceiverNotICApp(receiverNotICApp); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_alreadyExecuted() public { @@ -657,9 +601,9 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { bytes memory encodedTx = getEncodedTx(icTx); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.AlreadyExecuted, uint256(desc.transactionId)); expectRevertTxAlreadyExecuted(desc.transactionId); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertTxAlreadyExecuted(desc.transactionId); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } function test_execute_revert_zeroRequiredResponses() public { @@ -669,8 +613,8 @@ abstract contract InterchainClientV1DstTest is InterchainClientV1BaseTest { mockCheckVerification(icModuleA, desc, justVerTS()); assertCorrectReadiness(icTx, IInterchainClientV1.TxReadiness.ReceiverZeroRequiredResponses, dstReceiver); expectRevertReceiverZeroRequiredResponses(dstReceiver); - icClient.isExecutable(encodedTx, emptyProof); + icClient.isExecutable(encodedTx); expectRevertReceiverZeroRequiredResponses(dstReceiver); - executeTransaction(encodedTx, emptyProof); + executeTransaction(encodedTx); } } diff --git a/packages/contracts-communication/test/InterchainClientV1.Src.t.sol b/packages/contracts-communication/test/InterchainClientV1.Src.t.sol index 895585e5e6..c8e1561fb0 100644 --- a/packages/contracts-communication/test/InterchainClientV1.Src.t.sol +++ b/packages/contracts-communication/test/InterchainClientV1.Src.t.sol @@ -37,7 +37,6 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { uint256 public constant MOCK_INTERCHAIN_FEE = 0.5 ether; uint64 public constant MOCK_DB_NONCE = 444; - uint64 public constant MOCK_ENTRY_INDEX = 4; OptionsV1 public options = OptionsV1({gasLimit: 100_000, gasAirdrop: 1 ether}); bytes public encodedOptions = options.encodeOptionsV1(); @@ -81,13 +80,13 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { ); } - /// @dev Override the DB's returned next entry index (both for reads and writes) - function mockNextEntryIndex(uint64 dbNonce, uint64 entryIndex) internal { - bytes memory returnData = abi.encode(dbNonce, entryIndex); + /// @dev Override the DB's returned next DB nonce (both for reads and writes) + function mockNextDbNonce(uint64 dbNonce) internal { + bytes memory returnData = abi.encode(dbNonce); // Use partial calldata to override return values for calls to these functions with any arguments. - vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.getNextEntryIndex.selector), returnData); + vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.getDBNonce.selector), returnData); vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.writeEntry.selector), returnData); - vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.writeEntryWithVerification.selector), returnData); + vm.mockCall(icDB, abi.encodeWithSelector(InterchainDBMock.writeEntryRequestVerification.selector), returnData); } /// @dev Constructs an interchain transaction and its descriptor for testing. @@ -102,20 +101,15 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { dstChainId: REMOTE_CHAIN_ID, dstReceiver: receiver, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, options: encodedOptions, message: message }); - desc = InterchainTxDescriptor({ - transactionId: keccak256(getEncodedTx(icTx)), - dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX - }); + desc = InterchainTxDescriptor({transactionId: keccak256(getEncodedTx(icTx)), dbNonce: MOCK_DB_NONCE}); } // ═══════════════════════════════════════════════ TEST HELPERS ════════════════════════════════════════════════════ - function expectWriteEntryWithVerificationCall( + function expectWriteEntryRequestVerificationCall( InterchainTransaction memory icTx, InterchainTxDescriptor memory desc, uint256 interchainFee, @@ -124,7 +118,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { internal { bytes memory expectedCalldata = abi.encodeCall( - InterchainDBMock.writeEntryWithVerification, (icTx.dstChainId, desc.transactionId, srcModules) + InterchainDBMock.writeEntryRequestVerification, (icTx.dstChainId, desc.transactionId, srcModules) ); vm.expectCall({callee: icDB, msgValue: interchainFee, data: expectedCalldata, count: 1}); } @@ -155,14 +149,14 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { { (icTx, desc) = constructInterchainTx(receiver); mockInterchainFee(icTx.dstChainId, srcModules, interchainFee); - mockNextEntryIndex(MOCK_DB_NONCE, MOCK_ENTRY_INDEX); + mockNextDbNonce(MOCK_DB_NONCE); } function test_interchainSend_withExecService_icFeeNonZero_execFeeNonZero() public { (InterchainTransaction memory icTx, InterchainTxDescriptor memory desc) = prepareSendTest({receiver: dstReceiver, interchainFee: MOCK_INTERCHAIN_FEE, srcModules: twoModules}); // Anything paid on top of the interchain fee is considered an execution fee. - expectWriteEntryWithVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); expectRequestTxExecutionCall(icTx, desc, MOCK_EXECUTION_FEE); expectEventInterchainTransactionSent(icTx, desc, MOCK_INTERCHAIN_FEE, MOCK_EXECUTION_FEE); vm.prank(srcSender); @@ -179,7 +173,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { function test_interchainSend_withExecService_icFeeNonZero_execFeeZero() public { (InterchainTransaction memory icTx, InterchainTxDescriptor memory desc) = prepareSendTest({receiver: dstReceiver, interchainFee: MOCK_INTERCHAIN_FEE, srcModules: twoModules}); - expectWriteEntryWithVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); expectRequestTxExecutionCall(icTx, desc, 0); expectEventInterchainTransactionSent(icTx, desc, MOCK_INTERCHAIN_FEE, 0); vm.prank(srcSender); @@ -197,7 +191,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { (InterchainTransaction memory icTx, InterchainTxDescriptor memory desc) = prepareSendTest({receiver: dstReceiver, interchainFee: 0, srcModules: twoModules}); // Anything paid on top of the interchain fee is considered an execution fee. - expectWriteEntryWithVerificationCall(icTx, desc, 0, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, 0, twoModules); expectRequestTxExecutionCall(icTx, desc, MOCK_EXECUTION_FEE); expectEventInterchainTransactionSent(icTx, desc, 0, MOCK_EXECUTION_FEE); vm.prank(srcSender); @@ -214,7 +208,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { function test_interchainSend_withExecService_icFeeZero_execFeeZero() public { (InterchainTransaction memory icTx, InterchainTxDescriptor memory desc) = prepareSendTest({receiver: dstReceiver, interchainFee: 0, srcModules: twoModules}); - expectWriteEntryWithVerificationCall(icTx, desc, 0, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, 0, twoModules); expectRequestTxExecutionCall(icTx, desc, 0); expectEventInterchainTransactionSent(icTx, desc, 0, 0); vm.prank(srcSender); @@ -355,7 +349,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { srcModules: twoModules }); // Anything paid on top of the interchain fee is considered an execution fee. - expectWriteEntryWithVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); expectRequestTxExecutionCall(icTx, desc, MOCK_EXECUTION_FEE); expectEventInterchainTransactionSent(icTx, desc, MOCK_INTERCHAIN_FEE, MOCK_EXECUTION_FEE); vm.prank(srcSender); @@ -375,7 +369,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { interchainFee: MOCK_INTERCHAIN_FEE, srcModules: twoModules }); - expectWriteEntryWithVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, MOCK_INTERCHAIN_FEE, twoModules); expectRequestTxExecutionCall(icTx, desc, 0); expectEventInterchainTransactionSent(icTx, desc, MOCK_INTERCHAIN_FEE, 0); vm.prank(srcSender); @@ -393,7 +387,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { (InterchainTransaction memory icTx, InterchainTxDescriptor memory desc) = prepareSendTest({receiver: dstReceiverEVMBytes32, interchainFee: 0, srcModules: twoModules}); // Anything paid on top of the interchain fee is considered an execution fee. - expectWriteEntryWithVerificationCall(icTx, desc, 0, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, 0, twoModules); expectRequestTxExecutionCall(icTx, desc, MOCK_EXECUTION_FEE); expectEventInterchainTransactionSent(icTx, desc, 0, MOCK_EXECUTION_FEE); vm.prank(srcSender); @@ -410,7 +404,7 @@ contract InterchainClientV1SourceTest is InterchainClientV1BaseTest { function test_interchainSendEVM_withExecService_icFeeZero_execFeeZero() public { (InterchainTransaction memory icTx, InterchainTxDescriptor memory desc) = prepareSendTest({receiver: dstReceiverEVMBytes32, interchainFee: 0, srcModules: twoModules}); - expectWriteEntryWithVerificationCall(icTx, desc, 0, twoModules); + expectWriteEntryRequestVerificationCall(icTx, desc, 0, twoModules); expectRequestTxExecutionCall(icTx, desc, 0); expectEventInterchainTransactionSent(icTx, desc, 0, 0); vm.prank(srcSender); diff --git a/packages/contracts-communication/test/InterchainDB.Dst.t.sol b/packages/contracts-communication/test/InterchainDB.Dst.t.sol index dc13e0c040..9290d896a4 100644 --- a/packages/contracts-communication/test/InterchainDB.Dst.t.sol +++ b/packages/contracts-communication/test/InterchainDB.Dst.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {InterchainDB, InterchainBatch, IInterchainDB, InterchainDBEvents} from "../contracts/InterchainDB.sol"; +import {InterchainDB, InterchainEntry, IInterchainDB, InterchainDBEvents} from "../contracts/InterchainDB.sol"; -import {InterchainBatchLibHarness} from "./harnesses/InterchainBatchLibHarness.sol"; +import {InterchainEntryLibHarness} from "./harnesses/InterchainEntryLibHarness.sol"; import {VersionedPayloadLibHarness} from "./harnesses/VersionedPayloadLibHarness.sol"; import {InterchainModuleMock} from "./mocks/InterchainModuleMock.sol"; @@ -20,9 +20,9 @@ contract InterchainDBDestinationTest is Test, InterchainDBEvents { uint16 public constant DB_VERSION = 1; - uint256 public constant BATCH_CONFLICT = type(uint256).max; + uint256 public constant ENTRY_CONFLICT = type(uint256).max; - InterchainBatchLibHarness public batchLibHarness; + InterchainEntryLibHarness public entryLibHarness; VersionedPayloadLibHarness public payloadLibHarness; InterchainDB public icDB; @@ -31,97 +31,93 @@ contract InterchainDBDestinationTest is Test, InterchainDBEvents { address public writerT = makeAddr("Test Writer"); - mapping(address module => mapping(bytes32 batchHash => uint256 timestamp)) public verifiedAt; + mapping(address module => mapping(bytes32 entryHash => uint256 timestamp)) public verifiedAt; function setUp() public { vm.chainId(DST_CHAIN_ID); icDB = new InterchainDB(); moduleA = new InterchainModuleMock(); moduleB = new InterchainModuleMock(); - batchLibHarness = new InterchainBatchLibHarness(); + entryLibHarness = new InterchainEntryLibHarness(); payloadLibHarness = new VersionedPayloadLibHarness(); // Format is {chainId: nonce} - // Verify some batches with module A + // Verify some entries with module A // A: {0: 0}, {0: 10}, {1: 10} - verifyBatch(moduleA, getVersionedBatch(getMockBatch(SRC_CHAIN_ID_0, 0))); - verifyBatch(moduleA, getVersionedBatch(getMockBatch(SRC_CHAIN_ID_0, 10))); - verifyBatch(moduleA, getVersionedBatch(getMockBatch(SRC_CHAIN_ID_1, 10))); - // Verify some batches with module B + verifyEntry(moduleA, getVersionedEntry(getMockEntry(SRC_CHAIN_ID_0, 0))); + verifyEntry(moduleA, getVersionedEntry(getMockEntry(SRC_CHAIN_ID_0, 10))); + verifyEntry(moduleA, getVersionedEntry(getMockEntry(SRC_CHAIN_ID_1, 10))); + // Verify some entries with module B // B: {1: 0}, {1: 10} - verifyBatch(moduleB, getVersionedBatch(getMockBatch(SRC_CHAIN_ID_1, 0))); - verifyBatch(moduleB, getVersionedBatch(getMockBatch(SRC_CHAIN_ID_1, 10))); + verifyEntry(moduleB, getVersionedEntry(getMockEntry(SRC_CHAIN_ID_1, 0))); + verifyEntry(moduleB, getVersionedEntry(getMockEntry(SRC_CHAIN_ID_1, 10))); } - function getVersionedBatch(InterchainBatch memory batch) internal view returns (bytes memory) { - return payloadLibHarness.encodeVersionedPayload(DB_VERSION, batchLibHarness.encodeBatch(batch)); + function getVersionedEntry(InterchainEntry memory entry) internal view returns (bytes memory) { + return payloadLibHarness.encodeVersionedPayload(DB_VERSION, entryLibHarness.encodeEntry(entry)); } - function verifyBatch(InterchainModuleMock module, bytes memory versionedBatch) internal { + function verifyEntry(InterchainModuleMock module, bytes memory versionedEntry) internal { skip(1 minutes); - verifiedAt[address(module)][keccak256(abi.encode(versionedBatch))] = block.timestamp; - module.mockVerifyRemoteBatch(address(icDB), versionedBatch); + verifiedAt[address(module)][keccak256(abi.encode(versionedEntry))] = block.timestamp; + module.mockVerifyRemoteEntry(address(icDB), versionedEntry); } function introduceConflicts() public { - // Have module A verify a different batch {1:0} (already verified by module B) - verifyBatch(moduleA, getVersionedBatch(getFakeBatch(SRC_CHAIN_ID_1, 0))); - // Have module B verify a different batch {0:10} (already verified by module A) - verifyBatch(moduleB, getVersionedBatch(getFakeBatch(SRC_CHAIN_ID_0, 10))); + // Have module A verify a different entry {1:0} (already verified by module B) + verifyEntry(moduleA, getVersionedEntry(getFakeEntry(SRC_CHAIN_ID_1, 0))); + // Have module B verify a different entry {0:10} (already verified by module A) + verifyEntry(moduleB, getVersionedEntry(getFakeEntry(SRC_CHAIN_ID_0, 10))); } - function introduceEmptyBatches() public { - // Have module A verify an empty batch for batches that module B has not verified + function introduceEmptyEntries() public { + // Have module A verify an empty entry for entries that module B has not verified // {0: 20} - verifyBatch(moduleA, getVersionedBatch(getEmptyBatch(SRC_CHAIN_ID_0, 20))); - // Have module A verify an empty batch for batches that module B has verified + verifyEntry(moduleA, getVersionedEntry(getEmptyEntry(SRC_CHAIN_ID_0, 20))); + // Have module A verify an empty entry for entries that module B has verified // {1: 0} - verifyBatch(moduleA, getVersionedBatch(getEmptyBatch(SRC_CHAIN_ID_1, 0))); - // Have module B verify an empty batch for batches that module A has not verified + verifyEntry(moduleA, getVersionedEntry(getEmptyEntry(SRC_CHAIN_ID_1, 0))); + // Have module B verify an empty entry for entries that module A has not verified // {0: 30} - verifyBatch(moduleB, getVersionedBatch(getEmptyBatch(SRC_CHAIN_ID_0, 30))); - // Have module B verify an empty batch for batches that module A has verified + verifyEntry(moduleB, getVersionedEntry(getEmptyEntry(SRC_CHAIN_ID_0, 30))); + // Have module B verify an empty entry for entries that module A has verified // {0: 10} - verifyBatch(moduleB, getVersionedBatch(getEmptyBatch(SRC_CHAIN_ID_0, 10))); + verifyEntry(moduleB, getVersionedEntry(getEmptyEntry(SRC_CHAIN_ID_0, 10))); } - function introduceEqualEmptyBatches() public { + function introduceEqualEmptyEntries() public { // {0: 20} - verifyBatch(moduleA, getVersionedBatch(getEmptyBatch(SRC_CHAIN_ID_0, 20))); - verifyBatch(moduleB, getVersionedBatch(getEmptyBatch(SRC_CHAIN_ID_0, 20))); + verifyEntry(moduleA, getVersionedEntry(getEmptyEntry(SRC_CHAIN_ID_0, 20))); + verifyEntry(moduleB, getVersionedEntry(getEmptyEntry(SRC_CHAIN_ID_0, 20))); } // ══════════════════════════════════════════════ DATA GENERATION ══════════════════════════════════════════════════ - function getMockBatchRoot(uint64 nonce) internal view returns (bytes32) { - return keccak256(abi.encode(writerT, getMockDataHash(nonce))); + function getMockEntryValue(uint64 nonce) internal view returns (bytes32) { + return entryLibHarness.getEntryValue(writerT, getMockDigest(nonce)); } - function getMockBatch(uint64 srcChainId, uint64 dbNonce) internal view returns (InterchainBatch memory batch) { - return InterchainBatch(srcChainId, dbNonce, getMockBatchRoot(dbNonce)); + function getMockEntry(uint64 srcChainId, uint64 dbNonce) internal view returns (InterchainEntry memory entry) { + return InterchainEntry(srcChainId, dbNonce, getMockEntryValue(dbNonce)); } - function getMockDataHash(uint64 nonce) internal pure returns (bytes32) { + function getMockDigest(uint64 nonce) internal pure returns (bytes32) { return keccak256(abi.encode(nonce)); } - function getFakeBatchRoot(uint64 nonce) internal view returns (bytes32) { - return keccak256(abi.encode(writerT, getFakeDataHash(nonce))); + function getFakeEntryValue(uint64 nonce) internal view returns (bytes32) { + return entryLibHarness.getEntryValue(writerT, getFakeDigest(nonce)); } - function getFakeBatch(uint64 srcChainId, uint64 dbNonce) internal view returns (InterchainBatch memory batch) { - return InterchainBatch(srcChainId, dbNonce, getFakeBatchRoot(dbNonce)); + function getFakeEntry(uint64 srcChainId, uint64 dbNonce) internal view returns (InterchainEntry memory entry) { + return InterchainEntry(srcChainId, dbNonce, getFakeEntryValue(dbNonce)); } - function getFakeDataHash(uint64 nonce) internal pure returns (bytes32) { + function getFakeDigest(uint64 nonce) internal pure returns (bytes32) { return keccak256(abi.encode(nonce, "Fake data")); } - function getEmptyBatchRoot() internal view returns (bytes32) { - return keccak256(abi.encode(writerT, 0)); - } - - function getEmptyBatch(uint64 srcChainId, uint64 dbNonce) internal pure returns (InterchainBatch memory batch) { - return InterchainBatch({srcChainId: srcChainId, dbNonce: dbNonce, batchRoot: 0}); + function getEmptyEntry(uint64 srcChainId, uint64 dbNonce) internal pure returns (InterchainEntry memory entry) { + return InterchainEntry({srcChainId: srcChainId, dbNonce: dbNonce, entryValue: 0}); } function addressToBytes32(address addr) internal pure returns (bytes32) { @@ -132,52 +128,44 @@ contract InterchainDBDestinationTest is Test, InterchainDBEvents { function assertCorrectInitialVerificationTime( InterchainModuleMock module, - InterchainBatch memory batch + InterchainEntry memory entry ) internal view { - bytes memory versionedBatch = getVersionedBatch(batch); - uint256 savedVerificationTime = verifiedAt[address(module)][keccak256(abi.encode(versionedBatch))]; + bytes memory versionedEntry = getVersionedEntry(entry); + uint256 savedVerificationTime = verifiedAt[address(module)][keccak256(abi.encode(versionedEntry))]; // We never save 0 as a verification time during initial setup assertGt(savedVerificationTime, 0); - checkVerification(module, batch, savedVerificationTime); + checkVerification(module, entry, savedVerificationTime); } function checkVerification( InterchainModuleMock module, - InterchainBatch memory batch, + InterchainEntry memory entry, uint256 expectedVerificationTime ) internal view { - uint256 timestamp = icDB.checkBatchVerification(address(module), batch); + uint256 timestamp = icDB.checkEntryVerification(address(module), entry); assertEq(timestamp, expectedVerificationTime); } - function expectEventBatchVerified(InterchainModuleMock module, InterchainBatch memory batch) internal { + function expectEventEntryVerified(InterchainModuleMock module, InterchainEntry memory entry) internal { vm.expectEmit(address(icDB)); - emit InterchainBatchVerified(address(module), batch.srcChainId, batch.dbNonce, batch.batchRoot); + emit InterchainEntryVerified(address(module), entry.srcChainId, entry.dbNonce, entry.entryValue); } - function expectRevertBatchConflict( - InterchainModuleMock module, - InterchainBatch memory existingBatch, - InterchainBatch memory newBatch - ) - internal - { + function expectRevertEntryConflict(InterchainModuleMock module, InterchainEntry memory newEntry) internal { vm.expectRevert( - abi.encodeWithSelector( - IInterchainDB.InterchainDB__BatchConflict.selector, address(module), existingBatch.batchRoot, newBatch - ) + abi.encodeWithSelector(IInterchainDB.InterchainDB__EntryConflict.selector, address(module), newEntry) ); } - function expectRevertBatchVersionMismatch(uint16 version, uint16 required) internal { + function expectRevertEntryVersionMismatch(uint16 version, uint16 required) internal { vm.expectRevert( - abi.encodeWithSelector(IInterchainDB.InterchainDB__BatchVersionMismatch.selector, version, required) + abi.encodeWithSelector(IInterchainDB.InterchainDB__EntryVersionMismatch.selector, version, required) ); } @@ -185,323 +173,321 @@ contract InterchainDBDestinationTest is Test, InterchainDBEvents { vm.expectRevert(abi.encodeWithSelector(IInterchainDB.InterchainDB__ChainIdNotRemote.selector, chainId)); } - // ═════════════════════════════════════════ TESTS: VERIFYING BATCHES ══════════════════════════════════════════════ + // ═════════════════════════════════════════ TESTS: VERIFYING ENTRIES ══════════════════════════════════════════════ - function test_verifyBatch_newKey_nonEmptyRoot() public { + function test_verifyEntry_newKey_nonEmptyRoot() public { skip(1 days); - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 20); - bytes memory versionedBatch = getVersionedBatch(batch); - expectEventBatchVerified(moduleA, batch); - verifyBatch(moduleA, versionedBatch); - checkVerification(moduleA, batch, block.timestamp); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 20); + bytes memory versionedEntry = getVersionedEntry(entry); + expectEventEntryVerified(moduleA, entry); + verifyEntry(moduleA, versionedEntry); + checkVerification(moduleA, entry, block.timestamp); } - function test_verifyBatch_newKey_emptyRoot() public { + function test_verifyEntry_newKey_emptyRoot() public { skip(1 days); - InterchainBatch memory batch = getEmptyBatch(SRC_CHAIN_ID_0, 20); - bytes memory versionedBatch = getVersionedBatch(batch); - expectEventBatchVerified(moduleA, batch); - verifyBatch(moduleA, versionedBatch); - checkVerification(moduleA, batch, block.timestamp); + InterchainEntry memory entry = getEmptyEntry(SRC_CHAIN_ID_0, 20); + bytes memory versionedEntry = getVersionedEntry(entry); + expectEventEntryVerified(moduleA, entry); + verifyEntry(moduleA, versionedEntry); + checkVerification(moduleA, entry, block.timestamp); } - function test_verifyBatch_sameKey_diffModule_prevEmptyRoot_emptyRoot() public { - introduceEmptyBatches(); + function test_verifyEntry_sameKey_diffModule_prevEmptyRoot_emptyRoot() public { + introduceEmptyEntries(); skip(1 days); // {0: 30} was verified as "empty" by module B, but not by module A - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 30); - bytes memory versionedEmptyBatch = getVersionedBatch(emptyBatch); - expectEventBatchVerified(moduleA, emptyBatch); - verifyBatch(moduleA, versionedEmptyBatch); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 30); + bytes memory versionedEmptyEntry = getVersionedEntry(emptyEntry); + expectEventEntryVerified(moduleA, emptyEntry); + verifyEntry(moduleA, versionedEmptyEntry); // Should save the verification time for A and not overwrite the existing verification time for B - checkVerification(moduleA, emptyBatch, block.timestamp); - assertCorrectInitialVerificationTime(moduleB, emptyBatch); + checkVerification(moduleA, emptyEntry, block.timestamp); + assertCorrectInitialVerificationTime(moduleB, emptyEntry); } - function test_verifyBatch_sameKey_diffModule_prevEmptyRoot_nonEmptyRoot() public { - introduceEmptyBatches(); + function test_verifyEntry_sameKey_diffModule_prevEmptyRoot_nonEmptyRoot() public { + introduceEmptyEntries(); skip(1 days); // {0: 30} was verified as "empty" by module B, but not by module A - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 30); - InterchainBatch memory mockBatch = getMockBatch(SRC_CHAIN_ID_0, 30); - bytes memory versionedBatch = getVersionedBatch(mockBatch); - expectEventBatchVerified(moduleA, mockBatch); - verifyBatch(moduleA, versionedBatch); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 30); + InterchainEntry memory mockEntry = getMockEntry(SRC_CHAIN_ID_0, 30); + bytes memory versionedEntry = getVersionedEntry(mockEntry); + expectEventEntryVerified(moduleA, mockEntry); + verifyEntry(moduleA, versionedEntry); // Should save the verification time for A and not overwrite the existing verification time for B - checkVerification(moduleA, mockBatch, block.timestamp); - assertCorrectInitialVerificationTime(moduleB, emptyBatch); + checkVerification(moduleA, mockEntry, block.timestamp); + assertCorrectInitialVerificationTime(moduleB, emptyEntry); } - function test_verifyBatch_sameKey_diffModule_prevNonEmptyRoot_emptyRoot() public { + function test_verifyEntry_sameKey_diffModule_prevNonEmptyRoot_emptyRoot() public { skip(1 days); // {1: 0} was verified by module B, but not by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_1, 0); - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_1, 0); - bytes memory versionedEmptyBatch = getVersionedBatch(emptyBatch); - expectEventBatchVerified(moduleA, emptyBatch); - verifyBatch(moduleA, versionedEmptyBatch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_1, 0); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_1, 0); + bytes memory versionedEmptyEntry = getVersionedEntry(emptyEntry); + expectEventEntryVerified(moduleA, emptyEntry); + verifyEntry(moduleA, versionedEmptyEntry); // Should save the verification time for A and not overwrite the existing verification time for B - checkVerification(moduleA, emptyBatch, block.timestamp); - assertCorrectInitialVerificationTime(moduleB, batch); + checkVerification(moduleA, emptyEntry, block.timestamp); + assertCorrectInitialVerificationTime(moduleB, entry); } - function test_verifyBatch_sameKey_diffModule_prevNonEmptyRoot_diffNonEmptyRoot() public { + function test_verifyEntry_sameKey_diffModule_prevNonEmptyRoot_diffNonEmptyRoot() public { skip(1 days); // {1: 0} was verified by module B, but not by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_1, 0); - InterchainBatch memory conflictingBatch = getFakeBatch(SRC_CHAIN_ID_1, 0); - bytes memory versionedConflictingBatch = getVersionedBatch(conflictingBatch); - expectEventBatchVerified(moduleA, conflictingBatch); - verifyBatch(moduleA, versionedConflictingBatch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_1, 0); + InterchainEntry memory conflictingEntry = getFakeEntry(SRC_CHAIN_ID_1, 0); + bytes memory versionedConflictingEntry = getVersionedEntry(conflictingEntry); + expectEventEntryVerified(moduleA, conflictingEntry); + verifyEntry(moduleA, versionedConflictingEntry); // Should save the verification time for A and not overwrite the existing verification time for B - checkVerification(moduleA, conflictingBatch, block.timestamp); - assertCorrectInitialVerificationTime(moduleB, batch); + checkVerification(moduleA, conflictingEntry, block.timestamp); + assertCorrectInitialVerificationTime(moduleB, entry); } - function test_verifyBatch_sameKey_diffModule_prevNonEmptyRoot_sameNonEmptyRoot() public { + function test_verifyEntry_sameKey_diffModule_prevNonEmptyRoot_sameNonEmptyRoot() public { skip(1 days); // {1: 0} was verified by module B, but not by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_1, 0); - bytes memory versionedBatch = getVersionedBatch(batch); - expectEventBatchVerified(moduleA, batch); - verifyBatch(moduleA, versionedBatch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_1, 0); + bytes memory versionedEntry = getVersionedEntry(entry); + expectEventEntryVerified(moduleA, entry); + verifyEntry(moduleA, versionedEntry); // Should save the verification time for A and not overwrite the existing verification time for B - checkVerification(moduleA, batch, block.timestamp); - assertCorrectInitialVerificationTime(moduleB, batch); + checkVerification(moduleA, entry, block.timestamp); + assertCorrectInitialVerificationTime(moduleB, entry); } - function test_verifyBatch_sameKey_sameModule_prevEmptyRoot_emptyRoot() public { - introduceEmptyBatches(); + function test_verifyEntry_sameKey_sameModule_prevEmptyRoot_emptyRoot() public { + introduceEmptyEntries(); skip(1 days); // {0: 20} was verified as "empty" by module A - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 20); - bytes memory versionedEmptyBatch = getVersionedBatch(emptyBatch); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 20); + bytes memory versionedEmptyEntry = getVersionedEntry(emptyEntry); // Should emit no event and not update the verification time - uint256 moduleAVerificationTime = verifiedAt[address(moduleA)][keccak256(abi.encode(versionedEmptyBatch))]; + uint256 moduleAVerificationTime = verifiedAt[address(moduleA)][keccak256(abi.encode(versionedEmptyEntry))]; vm.recordLogs(); - verifyBatch(moduleA, versionedEmptyBatch); + verifyEntry(moduleA, versionedEmptyEntry); assertEq(vm.getRecordedLogs().length, 0); - checkVerification(moduleA, emptyBatch, moduleAVerificationTime); + checkVerification(moduleA, emptyEntry, moduleAVerificationTime); } - function test_verifyBatch_sameKey_sameModule_prevEmptyRoot_nonEmptyRoot() public { - introduceEmptyBatches(); + function test_verifyEntry_sameKey_sameModule_prevEmptyRoot_nonEmptyRoot() public { + introduceEmptyEntries(); skip(1 days); // {0: 20} was verified as "empty" by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 20); - bytes memory versionedBatch = getVersionedBatch(batch); - // Overwriting an empty batch with a non-empty one is allowed - expectEventBatchVerified(moduleA, batch); - verifyBatch(moduleA, versionedBatch); - checkVerification(moduleA, batch, block.timestamp); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 20); + bytes memory versionedEntry = getVersionedEntry(entry); + // Overwriting an empty entry with a non-empty one is allowed + expectEventEntryVerified(moduleA, entry); + verifyEntry(moduleA, versionedEntry); + checkVerification(moduleA, entry, block.timestamp); } - function test_verifyBatch_sameKey_sameModule_prevNonEmptyRoot_sameNonEmptyRoot() public { + function test_verifyEntry_sameKey_sameModule_prevNonEmptyRoot_sameNonEmptyRoot() public { skip(1 days); // {0: 10} was verified by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 10); - bytes memory versionedBatch = getVersionedBatch(batch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 10); + bytes memory versionedEntry = getVersionedEntry(entry); // Should emit no event and not update the verification time - uint256 moduleAVerificationTime = verifiedAt[address(moduleA)][keccak256(abi.encode(versionedBatch))]; + uint256 moduleAVerificationTime = verifiedAt[address(moduleA)][keccak256(abi.encode(versionedEntry))]; vm.recordLogs(); - verifyBatch(moduleA, versionedBatch); + verifyEntry(moduleA, versionedEntry); assertEq(vm.getRecordedLogs().length, 0); - checkVerification(moduleA, batch, moduleAVerificationTime); + checkVerification(moduleA, entry, moduleAVerificationTime); } - // ════════════════════════════════════ TESTS: VERIFYING BATCHES (REVERTS) ═════════════════════════════════════════ + // ════════════════════════════════════ TESTS: VERIFYING ENTRIES (REVERTS) ═════════════════════════════════════════ - function test_verifyBatch_sameKey_sameModule_prevNonEmptyRoot_emptyRoot_revert() public { + function test_verifyEntry_sameKey_sameModule_prevNonEmptyRoot_emptyRoot_revert() public { // {0: 0} was verified by module A - InterchainBatch memory existingBatch = getMockBatch(SRC_CHAIN_ID_0, 0); - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 0); - bytes memory versionedEmptyBatch = getVersionedBatch(emptyBatch); - expectRevertBatchConflict(moduleA, existingBatch, emptyBatch); - verifyBatch(moduleA, versionedEmptyBatch); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 0); + bytes memory versionedEmptyEntry = getVersionedEntry(emptyEntry); + expectRevertEntryConflict(moduleA, emptyEntry); + verifyEntry(moduleA, versionedEmptyEntry); } - function test_verifyBatch_sameKey_sameModule_prevNonEmptyRoot_diffNonEmptyRoot_revert() public { + function test_verifyEntry_sameKey_sameModule_prevNonEmptyRoot_diffNonEmptyRoot_revert() public { // {0: 0} was verified by module A - InterchainBatch memory existingBatch = getMockBatch(SRC_CHAIN_ID_0, 0); - InterchainBatch memory conflictingBatch = getFakeBatch(SRC_CHAIN_ID_0, 0); - bytes memory versionedConflictingBatch = getVersionedBatch(conflictingBatch); - expectRevertBatchConflict(moduleA, existingBatch, conflictingBatch); - verifyBatch(moduleA, versionedConflictingBatch); + InterchainEntry memory conflictingEntry = getFakeEntry(SRC_CHAIN_ID_0, 0); + bytes memory versionedConflictingEntry = getVersionedEntry(conflictingEntry); + expectRevertEntryConflict(moduleA, conflictingEntry); + verifyEntry(moduleA, versionedConflictingEntry); } - function test_verifyBatch_revert_ChainIdNotRemote() public { - // Try to verify batch coming from the same chain - InterchainBatch memory batch = getMockBatch(DST_CHAIN_ID, 0); - bytes memory versionedBatch = getVersionedBatch(batch); + function test_verifyEntry_revert_ChainIdNotRemote() public { + // Try to verify entry coming from the same chain + InterchainEntry memory entry = getMockEntry(DST_CHAIN_ID, 0); + bytes memory versionedEntry = getVersionedEntry(entry); expectChainIdNotRemote(DST_CHAIN_ID); - verifyBatch(moduleA, versionedBatch); + verifyEntry(moduleA, versionedEntry); } - function test_verifyBatch_revert_wrongVersion(uint16 version) public { + function test_verifyEntry_revert_wrongVersion(uint16 version) public { vm.assume(version != DB_VERSION); - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 0); - bytes memory versionedBatch = - payloadLibHarness.encodeVersionedPayload(version, batchLibHarness.encodeBatch(batch)); - expectRevertBatchVersionMismatch(version, DB_VERSION); - moduleA.mockVerifyRemoteBatch(address(icDB), versionedBatch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 0); + bytes memory versionedEntry = + payloadLibHarness.encodeVersionedPayload(version, entryLibHarness.encodeEntry(entry)); + expectRevertEntryVersionMismatch(version, DB_VERSION); + moduleA.mockVerifyRemoteEntry(address(icDB), versionedEntry); } - // ══════════════════════════════════════════ TESTS: READING BATCHES ═══════════════════════════════════════════════ + // ══════════════════════════════════════════ TESTS: READING ENTRIES ═══════════════════════════════════════════════ function test_checkVerification_existingA_existingB() public view { // {1: 10} was verified by module A and module B - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_1, 10); - assertCorrectInitialVerificationTime(moduleA, batch); - assertCorrectInitialVerificationTime(moduleB, batch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_1, 10); + assertCorrectInitialVerificationTime(moduleA, entry); + assertCorrectInitialVerificationTime(moduleB, entry); } function test_checkVerification_existingA_unknownB() public view { // {0: 0} was verified by module A, but not by module B - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 0); - assertCorrectInitialVerificationTime(moduleA, batch); - checkVerification(moduleB, batch, 0); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 0); + assertCorrectInitialVerificationTime(moduleA, entry); + checkVerification(moduleB, entry, 0); } function test_checkVerification_existingA_differentB() public { introduceConflicts(); - // {0: 10} was verified by module A, but a "fake" batch was verified by module B - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 10); - assertCorrectInitialVerificationTime(moduleA, batch); - checkVerification(moduleB, batch, BATCH_CONFLICT); + // {0: 10} was verified by module A, but a "fake" entry was verified by module B + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 10); + assertCorrectInitialVerificationTime(moduleA, entry); + checkVerification(moduleB, entry, ENTRY_CONFLICT); } function test_checkVerification_existingA_emptyB() public { - introduceEmptyBatches(); - // {0: 10} was verified by module A, but an "empty" batch was verified by module B - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 10); - assertCorrectInitialVerificationTime(moduleA, batch); - checkVerification(moduleB, batch, BATCH_CONFLICT); + introduceEmptyEntries(); + // {0: 10} was verified by module A, but an "empty" entry was verified by module B + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 10); + assertCorrectInitialVerificationTime(moduleA, entry); + checkVerification(moduleB, entry, ENTRY_CONFLICT); } function test_checkVerification_unknownA_existingB() public view { // {1: 0} was verified by module B, but not by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_1, 0); - checkVerification(moduleA, batch, 0); - assertCorrectInitialVerificationTime(moduleB, batch); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_1, 0); + checkVerification(moduleA, entry, 0); + assertCorrectInitialVerificationTime(moduleB, entry); } function test_checkVerification_unknownA_unknownB() public view { // {0: 20} was not verified by any module - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 20); - checkVerification(moduleA, batch, 0); - checkVerification(moduleB, batch, 0); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 20); + checkVerification(moduleA, entry, 0); + checkVerification(moduleB, entry, 0); } function test_checkVerification_unknownA_differentB() public view { // {1: 0} was verified by module B, but not by module A - // Check the fake batch that neither module verified - InterchainBatch memory fakeBatch = getFakeBatch(SRC_CHAIN_ID_1, 0); - checkVerification(moduleA, fakeBatch, 0); - checkVerification(moduleB, fakeBatch, BATCH_CONFLICT); + // Check the fake entry that neither module verified + InterchainEntry memory fakeEntry = getFakeEntry(SRC_CHAIN_ID_1, 0); + checkVerification(moduleA, fakeEntry, 0); + checkVerification(moduleB, fakeEntry, ENTRY_CONFLICT); } function test_checkVerification_unknownA_emptyB() public { - introduceEmptyBatches(); - // {0: 30} was not verified by module A, but an "empty" batch was verified by module B - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 30); - checkVerification(moduleA, emptyBatch, 0); - assertCorrectInitialVerificationTime(moduleB, emptyBatch); + introduceEmptyEntries(); + // {0: 30} was not verified by module A, but an "empty" entry was verified by module B + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 30); + checkVerification(moduleA, emptyEntry, 0); + assertCorrectInitialVerificationTime(moduleB, emptyEntry); } function test_checkVerification_differentA_existingB() public { introduceConflicts(); - // {0: 10} was verified by module A, but a "fake" batch was verified by module B - // Check the fake batch that A never verified - InterchainBatch memory fakeBatch = getFakeBatch(SRC_CHAIN_ID_0, 10); - checkVerification(moduleA, fakeBatch, BATCH_CONFLICT); - assertCorrectInitialVerificationTime(moduleB, fakeBatch); + // {0: 10} was verified by module A, but a "fake" entry was verified by module B + // Check the fake entry that A never verified + InterchainEntry memory fakeEntry = getFakeEntry(SRC_CHAIN_ID_0, 10); + checkVerification(moduleA, fakeEntry, ENTRY_CONFLICT); + assertCorrectInitialVerificationTime(moduleB, fakeEntry); } function test_checkVerification_differentA_unknownB() public view { // {0: 10} was verified by module A, but not by module B - // Check the fake batch that neither module verified - InterchainBatch memory fakeBatch = getFakeBatch(SRC_CHAIN_ID_0, 10); - checkVerification(moduleA, fakeBatch, BATCH_CONFLICT); - checkVerification(moduleB, fakeBatch, 0); + // Check the fake entry that neither module verified + InterchainEntry memory fakeEntry = getFakeEntry(SRC_CHAIN_ID_0, 10); + checkVerification(moduleA, fakeEntry, ENTRY_CONFLICT); + checkVerification(moduleB, fakeEntry, 0); } function test_checkVerification_differentA_differentB() public view { // {1: 10} was verified by module A and module B - // Check the fake batch that neither module verified - InterchainBatch memory fakeBatch = getFakeBatch(SRC_CHAIN_ID_1, 10); - checkVerification(moduleA, fakeBatch, BATCH_CONFLICT); - checkVerification(moduleB, fakeBatch, BATCH_CONFLICT); + // Check the fake entry that neither module verified + InterchainEntry memory fakeEntry = getFakeEntry(SRC_CHAIN_ID_1, 10); + checkVerification(moduleA, fakeEntry, ENTRY_CONFLICT); + checkVerification(moduleB, fakeEntry, ENTRY_CONFLICT); } function test_checkVerification_differentA_emptyB() public { - introduceEmptyBatches(); - // {0: 10} was verified by module A, but an "empty" batch was verified by module B - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 10); - checkVerification(moduleA, emptyBatch, BATCH_CONFLICT); - assertCorrectInitialVerificationTime(moduleB, emptyBatch); + introduceEmptyEntries(); + // {0: 10} was verified by module A, but an "empty" entry was verified by module B + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 10); + checkVerification(moduleA, emptyEntry, ENTRY_CONFLICT); + assertCorrectInitialVerificationTime(moduleB, emptyEntry); } function test_checkVerification_emptyA_existingB() public { - introduceEmptyBatches(); - // {1: 0} was verified by module B, but an "empty" batch was verified by module A - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_1, 0); - checkVerification(moduleA, batch, BATCH_CONFLICT); - assertCorrectInitialVerificationTime(moduleB, batch); + introduceEmptyEntries(); + // {1: 0} was verified by module B, but an "empty" entry was verified by module A + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_1, 0); + checkVerification(moduleA, entry, ENTRY_CONFLICT); + assertCorrectInitialVerificationTime(moduleB, entry); } function test_checkVerification_emptyA_unknownB() public { - introduceEmptyBatches(); + introduceEmptyEntries(); // {0: 20} was verified as "empty" by module A, but not by module B - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 20); - assertCorrectInitialVerificationTime(moduleA, emptyBatch); - checkVerification(moduleB, emptyBatch, 0); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 20); + assertCorrectInitialVerificationTime(moduleA, emptyEntry); + checkVerification(moduleB, emptyEntry, 0); } function test_checkVerification_emptyA_differentB() public { - introduceEmptyBatches(); - // {1: 0} was verified by module B, but an "empty" batch was verified by module A - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_1, 0); - assertCorrectInitialVerificationTime(moduleA, emptyBatch); - checkVerification(moduleB, emptyBatch, BATCH_CONFLICT); + introduceEmptyEntries(); + // {1: 0} was verified by module B, but an "empty" entry was verified by module A + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_1, 0); + assertCorrectInitialVerificationTime(moduleA, emptyEntry); + checkVerification(moduleB, emptyEntry, ENTRY_CONFLICT); } function test_checkVerification_emptyA_emptyB() public { - introduceEqualEmptyBatches(); + introduceEqualEmptyEntries(); // {0: 20} was verified as "empty" by module A and module B - InterchainBatch memory emptyBatch = getEmptyBatch(SRC_CHAIN_ID_0, 20); - assertCorrectInitialVerificationTime(moduleA, emptyBatch); - assertCorrectInitialVerificationTime(moduleB, emptyBatch); + InterchainEntry memory emptyEntry = getEmptyEntry(SRC_CHAIN_ID_0, 20); + assertCorrectInitialVerificationTime(moduleA, emptyEntry); + assertCorrectInitialVerificationTime(moduleB, emptyEntry); } function test_checkVerification_modifySrcChainId() public view { - // Valid batch - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 0); - assertCorrectInitialVerificationTime(moduleA, batch); - batch.srcChainId ^= 1; - checkVerification(moduleA, batch, 0); + // Valid entry + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 0); + assertCorrectInitialVerificationTime(moduleA, entry); + entry.srcChainId ^= 1; + checkVerification(moduleA, entry, 0); } function test_checkVerification_modifyDbNonce() public view { - // Valid batch - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 0); - assertCorrectInitialVerificationTime(moduleA, batch); - batch.dbNonce ^= 1; - checkVerification(moduleA, batch, 0); + // Valid entry + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 0); + assertCorrectInitialVerificationTime(moduleA, entry); + entry.dbNonce ^= 1; + checkVerification(moduleA, entry, 0); } - function test_checkVerification_modifyBatchRoot() public view { + function test_checkVerification_modifyEntryValue() public view { // Valid entry - InterchainBatch memory batch = getMockBatch(SRC_CHAIN_ID_0, 0); - assertCorrectInitialVerificationTime(moduleA, batch); - batch.batchRoot ^= bytes32(uint256(1)); - checkVerification(moduleA, batch, BATCH_CONFLICT); + InterchainEntry memory entry = getMockEntry(SRC_CHAIN_ID_0, 0); + assertCorrectInitialVerificationTime(moduleA, entry); + entry.entryValue ^= bytes32(uint256(1)); + checkVerification(moduleA, entry, ENTRY_CONFLICT); } - // ═════════════════════════════════════ TESTS: READING BATCHES (REVERTS) ══════════════════════════════════════════ + // ═════════════════════════════════════ TESTS: READING ENTRIES (REVERTS) ══════════════════════════════════════════ function test_checkVerification_revert_ChainIdNotRemote() public { - InterchainBatch memory batch = getMockBatch(DST_CHAIN_ID, 0); + InterchainEntry memory entry = getMockEntry(DST_CHAIN_ID, 0); expectChainIdNotRemote(DST_CHAIN_ID); - icDB.checkBatchVerification(address(moduleA), batch); + icDB.checkEntryVerification(address(moduleA), entry); } } diff --git a/packages/contracts-communication/test/InterchainDB.Src.t.sol b/packages/contracts-communication/test/InterchainDB.Src.t.sol index 324c6e377b..e993ad559a 100644 --- a/packages/contracts-communication/test/InterchainDB.Src.t.sol +++ b/packages/contracts-communication/test/InterchainDB.Src.t.sol @@ -3,15 +3,13 @@ pragma solidity 0.8.20; import { InterchainDB, - InterchainBatch, InterchainEntry, InterchainEntryLib, IInterchainDB, - InterchainDBEvents, - BatchingV1Lib + InterchainDBEvents } from "../contracts/InterchainDB.sol"; -import {InterchainBatchLibHarness} from "./harnesses/InterchainBatchLibHarness.sol"; +import {InterchainEntryLibHarness} from "./harnesses/InterchainEntryLibHarness.sol"; import {VersionedPayloadLibHarness} from "./harnesses/VersionedPayloadLibHarness.sol"; import {InterchainModuleMock, IInterchainModule} from "./mocks/InterchainModuleMock.sol"; @@ -35,7 +33,7 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { uint256 public constant MODULE_A_FEE = 100; uint256 public constant MODULE_B_FEE = 200; - InterchainBatchLibHarness public batchLibHarness; + InterchainEntryLibHarness public entryLibHarness; VersionedPayloadLibHarness public payloadLibHarness; InterchainDB public icDB; @@ -57,7 +55,7 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { icDB = new InterchainDB(); moduleA = new InterchainModuleMock(); moduleB = new InterchainModuleMock(); - batchLibHarness = new InterchainBatchLibHarness(); + entryLibHarness = new InterchainEntryLibHarness(); payloadLibHarness = new VersionedPayloadLibHarness(); oneModule.push(address(moduleA)); twoModules.push(address(moduleA)); @@ -69,14 +67,12 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { function initialWrites() internal { for (uint64 i = 0; i < INITIAL_WRITER_F; ++i) { - InterchainEntry memory entry = getMockEntry(i, writerF); - writeEntry(writerF, entry.dataHash); - initialEntries.push(entry); + writeEntry(writerF, getMockDigest(i, writerF)); + initialEntries.push(getMockEntry(i, writerF)); } for (uint64 i = 0; i < INITIAL_WRITER_S; ++i) { - InterchainEntry memory entry = getMockEntry(INITIAL_WRITER_F + i, writerS); - writeEntry(writerS, entry.dataHash); - initialEntries.push(entry); + writeEntry(writerS, getMockDigest(INITIAL_WRITER_F + i, writerS)); + initialEntries.push(getMockEntry(INITIAL_WRITER_F + i, writerS)); } } @@ -85,36 +81,30 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { return initialEntries[dbNonce]; } - function getMockDataHash(address writer, uint64 nonce) internal pure returns (bytes32) { - return keccak256(abi.encode(writer, nonce)); + function getEmptyEntry(uint64 dbNonce) internal pure returns (InterchainEntry memory) { + return InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, entryValue: 0}); } - function getMockEntry(uint64 dbNonce, address writer) internal pure returns (InterchainEntry memory entry) { + function getMockDigest(uint64 nonce, address writer) internal pure returns (bytes32) { + return keccak256(abi.encode("Mock data", nonce, writer)); + } + + function getMockEntry(uint64 dbNonce, address writer) internal view returns (InterchainEntry memory entry) { + bytes32 digest = getMockDigest(dbNonce, writer); return InterchainEntry({ srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, - // TODO: entryIndex - entryIndex: 0, - srcWriter: addressToBytes32(writer), - dataHash: getMockDataHash(writer, dbNonce) - }); - } - - function getExpectedBatch(InterchainEntry memory entry) internal pure returns (InterchainBatch memory) { - return InterchainBatch({ - srcChainId: entry.srcChainId, - dbNonce: entry.dbNonce, - batchRoot: InterchainEntryLib.entryValue(entry) + entryValue: entryLibHarness.getEntryValue(writer, digest) }); } - function getVersionedBatch(InterchainBatch memory batch) internal view returns (bytes memory) { - return payloadLibHarness.encodeVersionedPayload(DB_VERSION, batchLibHarness.encodeBatch(batch)); + function getVersionedEntry(InterchainEntry memory entry) internal view returns (bytes memory) { + return payloadLibHarness.encodeVersionedPayload(DB_VERSION, entryLibHarness.encodeEntry(entry)); } - function getModuleCalldata(InterchainBatch memory batch) internal view returns (bytes memory) { - bytes memory vBatch = getVersionedBatch(batch); - return abi.encodeCall(IInterchainModule.requestBatchVerification, (DST_CHAIN_ID, batch.dbNonce, vBatch)); + function getModuleCalldata(InterchainEntry memory entry) internal view returns (bytes memory) { + bytes memory versionedEntry = getVersionedEntry(entry); + return abi.encodeCall(IInterchainModule.requestEntryVerification, (DST_CHAIN_ID, versionedEntry)); } function addressToBytes32(address addr) internal pure returns (bytes32) { @@ -129,21 +119,21 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { vm.mockCall(address(module), callData, returnData); } - function writeEntry(address writer, bytes32 dataHash) internal returns (uint64 dbNonce) { + function writeEntry(address writer, bytes32 digest) internal returns (uint64 dbNonce) { vm.prank(writer); - (dbNonce,) = icDB.writeEntry(dataHash); + return icDB.writeEntry(digest); } function requestVerification(address caller, uint256 msgValue, uint64 dbNonce, address[] memory modules) internal { deal(caller, msgValue); vm.prank(caller); - icDB.requestBatchVerification{value: msgValue}(DST_CHAIN_ID, dbNonce, modules); + icDB.requestEntryVerification{value: msgValue}(DST_CHAIN_ID, dbNonce, modules); } - function writeEntryWithVerification( + function writeEntryRequestVerification( uint256 msgValue, address writer, - bytes32 dataHash, + bytes32 digest, address[] memory modules ) internal @@ -151,55 +141,42 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { { deal(writer, msgValue); vm.prank(writer); - (dbNonce,) = icDB.writeEntryWithVerification{value: msgValue}(DST_CHAIN_ID, dataHash, modules); + return icDB.writeEntryRequestVerification{value: msgValue}(DST_CHAIN_ID, digest, modules); } // ═══════════════════════════════════════════════ TEST HELPERS ════════════════════════════════════════════════════ - function assertCorrectValue(bytes32 entryValue, InterchainEntry memory expected) internal pure { - bytes32 expectedValue = keccak256(abi.encode(expected.srcWriter, expected.dataHash)); - assertEq(entryValue, expectedValue, "!entryValue"); + function checkSavedEntry(uint64 dbNonce, InterchainEntry memory expected) internal view { + assertEq(icDB.getEntry(dbNonce), expected); + assertEq(icDB.getEntryValue(dbNonce), expected.entryValue); } - function assertEq(InterchainBatch memory actual, InterchainBatch memory expected) internal pure { + function assertEq(InterchainEntry memory actual, InterchainEntry memory expected) internal pure { assertEq(actual.srcChainId, expected.srcChainId, "!srcChainId"); assertEq(actual.dbNonce, expected.dbNonce, "!dbNonce"); - assertEq(actual.batchRoot, expected.batchRoot, "!batchRoot"); + assertEq(actual.entryValue, expected.entryValue, "!entryValue"); } - function expectEventInterchainEntryWritten(InterchainEntry memory entry) internal { - vm.expectEmit(address(icDB)); - emit InterchainEntryWritten({ - dbNonce: entry.dbNonce, - entryIndex: entry.entryIndex, - srcWriter: entry.srcWriter, - dataHash: entry.dataHash - }); - // In the V1 of InterchainDB, the batch is finalized immediately after writing an entry - vm.expectEmit(address(icDB)); - emit InterchainBatchFinalized({dbNonce: entry.dbNonce, batchRoot: entry.entryValue()}); - } - - function expectEventBatchVerificationRequested( - InterchainBatch memory batch, - address[] memory srcModules + function expectEventInterchainEntryWritten( + uint64 dbNonce, + address srcWriter, + bytes32 digest, + bytes32 entryValue ) internal { vm.expectEmit(address(icDB)); - emit InterchainBatchVerificationRequested(DST_CHAIN_ID, batch.dbNonce, batch.batchRoot, srcModules); - } - - function expectRevertEntryIndexOutOfRange(uint64 dbNonce, uint64 entryIndex, uint64 batchSize) internal { - vm.expectRevert( - abi.encodeWithSelector( - IInterchainDB.InterchainDB__EntryIndexOutOfRange.selector, dbNonce, entryIndex, batchSize - ) - ); + emit InterchainEntryWritten({ + dbNonce: dbNonce, + srcWriter: addressToBytes32(srcWriter), + digest: digest, + entryValue: entryValue + }); } - function expectRevertEntryIndexNotZero(uint64 entryIndex) internal { - vm.expectRevert(abi.encodeWithSelector(BatchingV1Lib.BatchingV1__EntryIndexNotZero.selector, entryIndex)); + function expectEventEntryVerificationRequested(uint64 dbNonce, address[] memory srcModules) internal { + vm.expectEmit(address(icDB)); + emit InterchainEntryVerificationRequested(DST_CHAIN_ID, dbNonce, srcModules); } function expectRevertFeeAmountBelowMin(uint256 feeAmount, uint256 minRequired) internal { @@ -208,16 +185,6 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { ); } - function expectRevertProofNotEmpty() internal { - vm.expectRevert(BatchingV1Lib.BatchingV1__ProofNotEmpty.selector); - } - - function expectRevertEntryRangeInvalid(uint64 dbNonce, uint64 start, uint64 end) internal { - vm.expectRevert( - abi.encodeWithSelector(IInterchainDB.InterchainDB__EntryRangeInvalid.selector, dbNonce, start, end) - ); - } - function expectRevertModulesNotProvided() internal { vm.expectRevert(IInterchainDB.InterchainDB__ModulesNotProvided.selector); } @@ -228,209 +195,174 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { // ═══════════════════════════════════════════════ TESTS: SET UP ═══════════════════════════════════════════════════ - function checkCorrectDBNonceEntryIndex(uint64 expectedDBNonce) internal view { - assertEq(icDB.getDBNonce(), expectedDBNonce); - (uint64 dbNonce, uint64 entryIndex) = icDB.getNextEntryIndex(); - assertEq(dbNonce, expectedDBNonce); - assertEq(entryIndex, 0); - } - function test_setup_getters() public view { for (uint64 i = 0; i < INITIAL_DB_NONCE; ++i) { - assertCorrectValue(icDB.getEntryValue(i, 0), getInitialEntry(i)); + checkSavedEntry(i, getInitialEntry(i)); } - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE); } // ══════════════════════════════════════════ TESTS: WRITING AN ENTRY ══════════════════════════════════════════════ - function test_writeEntry_writerF_emitsEvent() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - expectEventInterchainEntryWritten(entry); - writeEntry(writerF, entry.dataHash); - } - - function test_writeEntry_writerF_increasesDBNonce() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - writeEntry(writerF, dataHash); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - } - - function test_writeEntry_writerF_returnsCorrectNonce() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - uint64 nonce = writeEntry(writerF, dataHash); + function test_writeEntry_writerF() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); + bytes32 entryValue = getMockEntry(INITIAL_DB_NONCE, writerF).entryValue; + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerF, digest, entryValue); + uint64 nonce = writeEntry(writerF, digest); assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, getMockEntry(INITIAL_DB_NONCE, writerF)); } - function test_writeEntry_writerF_savesEntry() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - writeEntry(writerF, entry.dataHash); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); - } - - function test_writeEntry_writerS_emitsEvent() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - expectEventInterchainEntryWritten(entry); - writeEntry(writerS, entry.dataHash); - } - - function test_writeEntry_writerS_increasesDBNonce() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); - writeEntry(writerS, dataHash); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - } - - function test_writeEntry_writerS_returnsCorrectNonce() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); - uint64 nonce = writeEntry(writerS, dataHash); + function test_writeEntry_writerS() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerS); + bytes32 entryValue = getMockEntry(INITIAL_DB_NONCE, writerS).entryValue; + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerS, digest, entryValue); + uint64 nonce = writeEntry(writerS, digest); assertEq(nonce, INITIAL_DB_NONCE); - } - - function test_writeEntry_writerS_savesEntry() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - writeEntry(writerS, entry.dataHash); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, getMockEntry(INITIAL_DB_NONCE, writerS)); } // ═══════════════════════════════════════ TESTS: REQUESTING VALIDATION ════════════════════════════════════════════ function test_requestVerification_writerF_oneModule() public { uint64 dbNonce = 0; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE, dbNonce, oneModule); } function test_requestVerification_writerF_oneModule_higherFee() public { uint64 dbNonce = 0; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE * 2, dbNonce, oneModule); } function test_requestVerification_writerF_twoModules() public { uint64 dbNonce = 0; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_writerF_twoModules_higherFee() public { // Overpaid fees should be directed to the first module uint64 dbNonce = 0; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE * 2 + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_writerS_oneModule() public { uint64 dbNonce = 2; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE, dbNonce, oneModule); } function test_requestVerification_writerS_oneModule_higherFee() public { uint64 dbNonce = 2; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE * 2, dbNonce, oneModule); } function test_requestVerification_writerS_twoModules() public { uint64 dbNonce = 2; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_writerS_twoModules_higherFee() public { // Overpaid fees should be directed to the first module uint64 dbNonce = 2; - InterchainBatch memory batch = getExpectedBatch(getInitialEntry(dbNonce)); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getInitialEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE * 2 + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_nextNonce_oneModule() public { uint64 dbNonce = INITIAL_DB_NONCE; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE, dbNonce, oneModule); } function test_requestVerification_nextNonce_oneModule_higherFee() public { uint64 dbNonce = INITIAL_DB_NONCE; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE * 2, dbNonce, oneModule); } function test_requestVerification_nextNonce_twoModules() public { uint64 dbNonce = INITIAL_DB_NONCE; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_nextNonce_twoModules_higherFee() public { // Overpaid fees should be directed to the first module uint64 dbNonce = INITIAL_DB_NONCE; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE * 2 + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_hugeNonce_oneModule() public { uint64 dbNonce = 2 ** 32; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE, dbNonce, oneModule); } function test_requestVerification_hugeNonce_oneModule_higherFee() public { uint64 dbNonce = 2 ** 32; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, oneModule); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, oneModule); requestVerification(requestCaller, MODULE_A_FEE * 2, dbNonce, oneModule); } function test_requestVerification_hugeNonce_twoModules() public { uint64 dbNonce = 2 ** 32; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE + MODULE_B_FEE, dbNonce, twoModules); } function test_requestVerification_hugeNonce_twoModules_higherFee() public { // Overpaid fees should be directed to the first module uint64 dbNonce = 2 ** 32; - InterchainBatch memory batch = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: dbNonce, batchRoot: 0}); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventBatchVerificationRequested(batch, twoModules); + InterchainEntry memory entry = getEmptyEntry(dbNonce); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventEntryVerificationRequested(dbNonce, twoModules); requestVerification(requestCaller, MODULE_A_FEE * 2 + MODULE_B_FEE, dbNonce, twoModules); } @@ -456,214 +388,138 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { function test_requestVerification_revert_ChainIdNotRemote() public { expectRevertChainIdNotRemote(SRC_CHAIN_ID); vm.prank(requestCaller); - icDB.requestBatchVerification(SRC_CHAIN_ID, 0, oneModule); + icDB.requestEntryVerification(SRC_CHAIN_ID, 0, oneModule); } // ═════════════════════════════════════ TESTS: WRITE + REQUEST VALIDATION ═════════════════════════════════════════ - function test_writeEntryWithVerification_writerF_oneModule_callsModule() public { + function test_writeEntryRequestVerification_writerF_oneModule() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - writeEntryWithVerification(MODULE_A_FEE, writerF, entry.dataHash, oneModule); - } - - function test_writeEntryWithVerification_writerF_oneModule_emitsEvents() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - expectEventInterchainEntryWritten(entry); - expectEventBatchVerificationRequested(getExpectedBatch(entry), oneModule); - writeEntryWithVerification(MODULE_A_FEE, writerF, entry.dataHash, oneModule); - } - - function test_writeEntryWithVerification_writerF_oneModule_increasesDBNonce() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - writeEntryWithVerification(MODULE_A_FEE, writerF, dataHash, oneModule); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - } - - function test_writeEntryWithVerification_writerF_oneModule_returnsCorrectNonce() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - uint64 nonce = writeEntryWithVerification(MODULE_A_FEE, writerF, dataHash, oneModule); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerF, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, oneModule); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE, writerF, digest, oneModule); assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerF_oneModule_savesEntry() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - writeEntryWithVerification(MODULE_A_FEE, writerF, entry.dataHash, oneModule); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); - } - - function test_writeEntryWithVerification_writerF_oneModule_higherFee() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - expectEventInterchainEntryWritten(entry); - writeEntryWithVerification(MODULE_A_FEE * 2, writerF, dataHash, oneModule); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); - } - - function test_writeEntryWithVerification_writerF_twoModules_callsModules() public { + function test_writeEntryRequestVerification_writerF_oneModule_higherFee() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerF, entry.dataHash, twoModules); - } - - function test_writeEntryWithVerification_writerF_twoModules_emitsEvents() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - expectEventInterchainEntryWritten(entry); - expectEventBatchVerificationRequested(getExpectedBatch(entry), twoModules); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerF, entry.dataHash, twoModules); - } - - function test_writeEntryWithVerification_writerF_twoModules_increasesDBNonce() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerF, dataHash, twoModules); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - } - - function test_writeEntryWithVerification_writerF_twoModules_returnsCorrectNonce() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); - uint64 nonce = writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerF, dataHash, twoModules); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerF, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, oneModule); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE * 2, writerF, digest, oneModule); assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerF_twoModules_savesEntry() public { + function test_writeEntryRequestVerification_writerF_twoModules() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerF, entry.dataHash, twoModules); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerF, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, twoModules); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE + MODULE_B_FEE, writerF, digest, twoModules); + assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerF_twoModules_higherFee() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_writerF_twoModules_higherFee() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerF); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventInterchainEntryWritten(entry); - writeEntryWithVerification(MODULE_A_FEE * 2 + MODULE_B_FEE, writerF, dataHash, twoModules); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); - } - - function test_writeEntryWithVerification_writerS_oneModule_callsModule() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - writeEntryWithVerification(MODULE_A_FEE, writerS, entry.dataHash, oneModule); - } - - function test_writeEntryWithVerification_writerS_oneModule_emitsEvents() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - expectEventInterchainEntryWritten(entry); - expectEventBatchVerificationRequested(getExpectedBatch(entry), oneModule); - writeEntryWithVerification(MODULE_A_FEE, writerS, entry.dataHash, oneModule); - } - - function test_writeEntryWithVerification_writerS_oneModule_increasesDBNonce() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); - writeEntryWithVerification(MODULE_A_FEE, writerS, dataHash, oneModule); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - } - - function test_writeEntryWithVerification_writerS_oneModule_returnsCorrectNonce() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); - uint64 nonce = writeEntryWithVerification(MODULE_A_FEE, writerS, dataHash, oneModule); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerF, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, twoModules); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE * 2 + MODULE_B_FEE, writerF, digest, twoModules); assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerS_oneModule_savesEntry() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - writeEntryWithVerification(MODULE_A_FEE, writerS, entry.dataHash, oneModule); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); - } - - function test_writeEntryWithVerification_writerS_oneModule_higherFee() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_writerS_oneModule() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerS); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - expectEventInterchainEntryWritten(entry); - writeEntryWithVerification(MODULE_A_FEE * 2, writerS, dataHash, oneModule); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); - } - - function test_writeEntryWithVerification_writerS_twoModules_callsModules() public { - InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerS, entry.dataHash, twoModules); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerS, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, oneModule); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE, writerS, digest, oneModule); + assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerS_twoModules_emitsEvents() public { + function test_writeEntryRequestVerification_writerS_oneModule_higherFee() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerS); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - expectEventInterchainEntryWritten(entry); - expectEventBatchVerificationRequested(getExpectedBatch(entry), twoModules); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerS, entry.dataHash, twoModules); - } - - function test_writeEntryWithVerification_writerS_twoModules_increasesDBNonce() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerS, dataHash, twoModules); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - } - - function test_writeEntryWithVerification_writerS_twoModules_returnsCorrectNonce() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); - uint64 nonce = writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerS, dataHash, twoModules); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerS, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, oneModule); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE * 2, writerS, digest, oneModule); assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerS_twoModules_savesEntry() public { + function test_writeEntryRequestVerification_writerS_twoModules() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerS); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - writeEntryWithVerification(MODULE_A_FEE + MODULE_B_FEE, writerS, entry.dataHash, twoModules); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerS, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, twoModules); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE + MODULE_B_FEE, writerS, digest, twoModules); + assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } - function test_writeEntryWithVerification_writerS_twoModules_higherFee() public { - bytes32 dataHash = getMockDataHash(writerS, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_writerS_twoModules_higherFee() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerS); InterchainEntry memory entry = getMockEntry(INITIAL_DB_NONCE, writerS); - InterchainBatch memory batch = getExpectedBatch(entry); - vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(batch)}); - vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(batch)}); - expectEventInterchainEntryWritten(entry); - writeEntryWithVerification(MODULE_A_FEE * 2 + MODULE_B_FEE, writerS, dataHash, twoModules); - checkCorrectDBNonceEntryIndex(INITIAL_DB_NONCE + 1); - assertCorrectValue(icDB.getEntryValue(INITIAL_DB_NONCE, 0), entry); + vm.expectCall({callee: address(moduleA), msgValue: MODULE_A_FEE * 2, data: getModuleCalldata(entry)}); + vm.expectCall({callee: address(moduleB), msgValue: MODULE_B_FEE, data: getModuleCalldata(entry)}); + expectEventInterchainEntryWritten(INITIAL_DB_NONCE, writerS, digest, entry.entryValue); + expectEventEntryVerificationRequested(INITIAL_DB_NONCE, twoModules); + uint64 nonce = writeEntryRequestVerification(MODULE_A_FEE * 2 + MODULE_B_FEE, writerS, digest, twoModules); + assertEq(nonce, INITIAL_DB_NONCE); + assertEq(icDB.getDBNonce(), INITIAL_DB_NONCE + 1); + checkSavedEntry(INITIAL_DB_NONCE, entry); } // ════════════════════════════════ TESTS: WRITE + REQUEST VALIDATION (REVERTS) ════════════════════════════════════ - function test_writeEntryWithVerification_revert_FeeAmountBelowMin_oneModule_underpaid() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_revert_FeeAmountBelowMin_oneModule_underpaid() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); uint256 incorrectFee = MODULE_A_FEE - 1; expectRevertFeeAmountBelowMin(incorrectFee, MODULE_A_FEE); - writeEntryWithVerification(incorrectFee, writerF, dataHash, oneModule); + writeEntryRequestVerification(incorrectFee, writerF, digest, oneModule); } - function test_writeEntryWithVerification_revert_FeeAmountBelowMin_twoModules_underpaid() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_revert_FeeAmountBelowMin_twoModules_underpaid() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); uint256 incorrectFee = MODULE_A_FEE + MODULE_B_FEE - 1; expectRevertFeeAmountBelowMin(incorrectFee, MODULE_A_FEE + MODULE_B_FEE); - writeEntryWithVerification(incorrectFee, writerF, dataHash, twoModules); + writeEntryRequestVerification(incorrectFee, writerF, digest, twoModules); } - function test_writeEntryWithVerification_revert_ModulesNotProvided() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_revert_ModulesNotProvided() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); expectRevertModulesNotProvided(); - writeEntryWithVerification(0, writerF, dataHash, new address[](0)); + writeEntryRequestVerification(0, writerF, digest, new address[](0)); } - function test_writeEntryWithVerification_revert_ChainIdNotRemote() public { - bytes32 dataHash = getMockDataHash(writerF, INITIAL_DB_NONCE); + function test_writeEntryRequestVerification_revert_ChainIdNotRemote() public { + bytes32 digest = getMockDigest(INITIAL_DB_NONCE, writerF); expectRevertChainIdNotRemote(SRC_CHAIN_ID); vm.prank(writerF); - icDB.writeEntryWithVerification(SRC_CHAIN_ID, dataHash, oneModule); + icDB.writeEntryRequestVerification(SRC_CHAIN_ID, digest, oneModule); } // ═════════════════════════════════════════ TESTS: GET INTERCHAIN FEE ═════════════════════════════════════════════ @@ -685,189 +541,59 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents { // ════════════════════════════════════════ TESTS: RETRIEVING DB VALUES ════════════════════════════════════════════ - function test_getBatchLeafs_finalized() public view { - for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { - bytes32[] memory leafs = icDB.getBatchLeafs(nonce); - assertEq(leafs.length, 1, "!leafs.length"); - assertEq(leafs[0], getInitialEntry(nonce).entryValue()); - } - } - - function test_getBatchLeafs_nextNonce() public view { - bytes32[] memory leafs = icDB.getBatchLeafs(INITIAL_DB_NONCE); - assertEq(leafs.length, 0); - } - - function test_getBatchLeafs_hugeNonce() public view { - bytes32[] memory leafs = icDB.getBatchLeafs(2 ** 32); - assertEq(leafs.length, 0); - } - - function test_getBatchLeafsPaginated_finalized() public view { - for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { - bytes32[] memory leafs = icDB.getBatchLeafsPaginated(nonce, 0, 0); - assertEq(leafs.length, 0, "!leafs.length"); - leafs = icDB.getBatchLeafsPaginated(nonce, 1, 1); - assertEq(leafs.length, 0, "!leafs.length"); - leafs = icDB.getBatchLeafsPaginated(nonce, 0, 1); - assertEq(leafs.length, 1, "!leafs.length"); - assertEq(leafs[0], getInitialEntry(nonce).entryValue()); - } - } - - function test_getBatchLeafsPaginated_nextNonce() public view { - bytes32[] memory leafs = icDB.getBatchLeafsPaginated(INITIAL_DB_NONCE, 0, 0); - assertEq(leafs.length, 0); - } - - function test_getBatchLeafsPaginated_hugeNonce() public view { - bytes32[] memory leafs = icDB.getBatchLeafsPaginated(2 ** 32, 0, 0); - assertEq(leafs.length, 0); - } - - function test_getBatchLeafsPaginated_revert_invalidRange_finalized() public { - expectRevertEntryRangeInvalid(1, 0, 2); - icDB.getBatchLeafsPaginated(1, 0, 2); - expectRevertEntryRangeInvalid(3, 1, 0); - icDB.getBatchLeafsPaginated(3, 1, 0); - } - - function test_getBatchLeafsPaginated_revert_invalidRange_nextNonce() public { - expectRevertEntryRangeInvalid(INITIAL_DB_NONCE, 0, 1); - icDB.getBatchLeafsPaginated(INITIAL_DB_NONCE, 0, 1); - expectRevertEntryRangeInvalid(INITIAL_DB_NONCE, 1, 1); - icDB.getBatchLeafsPaginated(INITIAL_DB_NONCE, 1, 1); - expectRevertEntryRangeInvalid(INITIAL_DB_NONCE, 1, 0); - icDB.getBatchLeafsPaginated(INITIAL_DB_NONCE, 1, 0); - } - - function test_getBatchLeafsPaginated_revert_invalidRange_hugeNonce() public { - expectRevertEntryRangeInvalid(2 ** 32, 0, 1); - icDB.getBatchLeafsPaginated(2 ** 32, 0, 1); - expectRevertEntryRangeInvalid(2 ** 32, 1, 1); - icDB.getBatchLeafsPaginated(2 ** 32, 1, 1); - expectRevertEntryRangeInvalid(2 ** 32, 1, 0); - icDB.getBatchLeafsPaginated(2 ** 32, 1, 0); - } - - function test_getBatchSize_finalized() public view { - for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { - assertEq(icDB.getBatchSize(nonce), 1, "!batchSize"); - } - } - - function test_getBatchSize_nextNonce() public view { - assertEq(icDB.getBatchSize(INITIAL_DB_NONCE), 0); - } - - function test_getBatchSize_hugeNonce() public view { - assertEq(icDB.getBatchSize(2 ** 32), 0); - } - - function test_getBatch_finalized() public view { - for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { - InterchainBatch memory batch = icDB.getBatch(nonce); - assertEq(batch, getExpectedBatch(getInitialEntry(nonce))); - } - } - - function test_getBatch_nextNonce() public view { - InterchainBatch memory batch = icDB.getBatch(INITIAL_DB_NONCE); - InterchainBatch memory expected = - InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: INITIAL_DB_NONCE, batchRoot: 0}); - assertEq(batch, expected); - } - - function test_getBatch_hugeNonce() public view { - InterchainBatch memory batch = icDB.getBatch(2 ** 32); - InterchainBatch memory expected = InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: 2 ** 32, batchRoot: 0}); - assertEq(batch, expected); - } - - function test_getVersionedBatch_finalized() public view { + function test_getEntry_finalized() public view { for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { - bytes memory versionedBatch = icDB.getVersionedBatch(nonce); - InterchainBatch memory expectedBatch = getExpectedBatch(getInitialEntry(nonce)); - assertEq(versionedBatch, getVersionedBatch(expectedBatch)); + InterchainEntry memory entry = icDB.getEntry(nonce); + assertEq(entry, getInitialEntry(nonce)); } } - function test_getVersionedBatch_nextNonce() public view { - bytes memory versionedBatch = icDB.getVersionedBatch(INITIAL_DB_NONCE); - InterchainBatch memory expectedBatch = - InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: INITIAL_DB_NONCE, batchRoot: 0}); - assertEq(versionedBatch, getVersionedBatch(expectedBatch)); + function test_getEntry_nextNonce() public view { + InterchainEntry memory entry = icDB.getEntry(INITIAL_DB_NONCE); + InterchainEntry memory expected = + InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: INITIAL_DB_NONCE, entryValue: 0}); + assertEq(entry, expected); } - function test_getVersionedBatch_hugeNonce() public view { - bytes memory versionedBatch = icDB.getVersionedBatch(2 ** 32); - InterchainBatch memory expectedBatch = - InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: 2 ** 32, batchRoot: 0}); - assertEq(versionedBatch, getVersionedBatch(expectedBatch)); + function test_getEntry_hugeNonce() public view { + InterchainEntry memory entry = icDB.getEntry(2 ** 32); + InterchainEntry memory expected = InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: 2 ** 32, entryValue: 0}); + assertEq(entry, expected); } - function test_getEntryValue() public view { + function test_getEntryValue_finalized() public view { for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { InterchainEntry memory expectedEntry = getInitialEntry(nonce); - assertCorrectValue(icDB.getEntryValue(nonce, 0), expectedEntry); + assertEq(icDB.getEntryValue(nonce), expectedEntry.entryValue); } } - function test_getEntryValue_revert_finalizedOutOfRange() public { - expectRevertEntryIndexOutOfRange(INITIAL_DB_NONCE - 1, 1, 1); - icDB.getEntryValue(INITIAL_DB_NONCE - 1, 1); - } - - function test_getEntryValue_revert_nextNonceOutOfRange() public { - expectRevertEntryIndexOutOfRange(INITIAL_DB_NONCE, 0, 0); - icDB.getEntryValue(INITIAL_DB_NONCE, 0); + function test_getEntryValue_nextNonce() public view { + assertEq(icDB.getEntryValue(INITIAL_DB_NONCE), 0); } - function test_getEntryValue_revert_hugeNonceOutOfRange() public { - expectRevertEntryIndexOutOfRange(2 ** 32, 0, 0); - icDB.getEntryValue(2 ** 32, 0); + function test_getEntryValue_hugeNonce() public view { + assertEq(icDB.getEntryValue(2 ** 32), 0); } - function test_getEntryProof_finalized() public view { + function test_getEncodedEntry_finalized() public view { for (uint64 nonce = 0; nonce < INITIAL_DB_NONCE; ++nonce) { - bytes32[] memory proof = icDB.getEntryProof(nonce, 0); - assertEq(proof.length, 0, "!proof.length"); + InterchainEntry memory entry = getInitialEntry(nonce); + bytes memory encodedEntry = icDB.getEncodedEntry(nonce); + assertEq(encodedEntry, getVersionedEntry(entry)); } } - function test_getEntryProof_revert_finalizedOutOfRange() public { - expectRevertEntryIndexOutOfRange(INITIAL_DB_NONCE - 1, 1, 1); - icDB.getEntryProof(INITIAL_DB_NONCE - 1, 1); - } - - function test_getEntryProof_revert_nextNonceOutOfRange() public { - expectRevertEntryIndexOutOfRange(INITIAL_DB_NONCE, 0, 0); - icDB.getEntryProof(INITIAL_DB_NONCE, 0); - } - - function test_getEntryProof_revert_hugeNonceOutOfRange() public { - expectRevertEntryIndexOutOfRange(2 ** 32, 0, 0); - icDB.getEntryProof(2 ** 32, 0); - } - - // ═══════════════════════════════════════════ TESTS: GET BATCH ROOT ═══════════════════════════════════════════════ - - function test_getBatchRoot(InterchainEntry memory entry) public view { - entry.entryIndex = 0; - bytes32 batchRoot = icDB.getBatchRoot(entry, new bytes32[](0)); - assertEq(batchRoot, InterchainEntryLib.entryValue(entry)); - } - - function test_getBatchRoot_revert_nonZeroEntryIndex() public { - InterchainEntry memory entry = getInitialEntry(0); - entry.entryIndex = 1; - expectRevertEntryIndexNotZero(1); - icDB.getBatchRoot(entry, new bytes32[](0)); + function test_getEncodedEntry_nextNonce() public view { + InterchainEntry memory entry = + InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: INITIAL_DB_NONCE, entryValue: 0}); + bytes memory encodedEntry = icDB.getEncodedEntry(INITIAL_DB_NONCE); + assertEq(encodedEntry, getVersionedEntry(entry)); } - function test_getBatchRoot_revert_nonEmptyProof() public { - InterchainEntry memory entry = getInitialEntry(0); - expectRevertProofNotEmpty(); - icDB.getBatchRoot(entry, new bytes32[](1)); + function test_getEncodedEntry_hugeNonce() public view { + InterchainEntry memory entry = InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: 2 ** 32, entryValue: 0}); + bytes memory encodedEntry = icDB.getEncodedEntry(2 ** 32); + assertEq(encodedEntry, getVersionedEntry(entry)); } } diff --git a/packages/contracts-communication/test/apps/InterchainAppV1.Messaging.t.sol b/packages/contracts-communication/test/apps/InterchainAppV1.Messaging.t.sol index 51fd1197c9..cf2821ef65 100644 --- a/packages/contracts-communication/test/apps/InterchainAppV1.Messaging.t.sol +++ b/packages/contracts-communication/test/apps/InterchainAppV1.Messaging.t.sol @@ -12,7 +12,6 @@ import {InterchainClientV1Mock} from "../mocks/InterchainClientV1Mock.sol"; // solhint-disable ordering abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { uint64 public constant MOCK_DB_NONCE = 42; - uint64 public constant MOCK_ENTRY_INDEX = 4; uint256 public constant MOCK_IC_FEE = 4844; @@ -22,13 +21,10 @@ abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { address public extraClient = makeAddr("Extra Client"); - InterchainTxDescriptor public mockDesc = InterchainTxDescriptor({ - transactionId: keccak256("Mock Transaction ID"), - dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX - }); + InterchainTxDescriptor public mockDesc = + InterchainTxDescriptor({transactionId: keccak256("Mock Transaction ID"), dbNonce: MOCK_DB_NONCE}); - event MessageReceived(uint64 srcChainId, bytes32 sender, uint64 dbNonce, uint64 entryIndex, bytes message); + event MessageReceived(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes message); function configureICAppV1() internal override { appHarness.addInterchainClient({client: icClient, updateLatest: true}); @@ -66,20 +62,18 @@ abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { function assertEq(InterchainTxDescriptor memory desc, InterchainTxDescriptor memory expected) internal pure { assertEq(desc.transactionId, expected.transactionId); assertEq(desc.dbNonce, expected.dbNonce); - assertEq(desc.entryIndex, expected.entryIndex); } // ══════════════════════════════════════════ TESTS: RECEIVE MESSAGES ══════════════════════════════════════════════ function test_appReceive_noAirdrop() public { vm.expectEmit(address(appHarness)); - emit MessageReceived(REMOTE_CHAIN_ID, linkedAppMockBytes32, MOCK_DB_NONCE, MOCK_ENTRY_INDEX, message); + emit MessageReceived(REMOTE_CHAIN_ID, linkedAppMockBytes32, MOCK_DB_NONCE, message); vm.prank(icClient); appHarness.appReceive({ srcChainId: REMOTE_CHAIN_ID, sender: linkedAppMockBytes32, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, message: message }); } @@ -87,13 +81,12 @@ abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { function test_appReceive_withAirdrop() public { deal(icClient, 1 ether); vm.expectEmit(address(appHarness)); - emit MessageReceived(REMOTE_CHAIN_ID, linkedAppMockBytes32, MOCK_DB_NONCE, MOCK_ENTRY_INDEX, message); + emit MessageReceived(REMOTE_CHAIN_ID, linkedAppMockBytes32, MOCK_DB_NONCE, message); vm.prank(icClient); appHarness.appReceive{value: 1 ether}({ srcChainId: REMOTE_CHAIN_ID, sender: linkedAppMockBytes32, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, message: message }); } @@ -106,7 +99,6 @@ abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { srcChainId: REMOTE_CHAIN_ID, sender: linkedAppMockBytes32, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, message: message }); } @@ -118,7 +110,6 @@ abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { srcChainId: LOCAL_CHAIN_ID, sender: linkedAppMockBytes32, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, message: message }); } @@ -127,13 +118,7 @@ abstract contract InterchainAppV1MessagingTest is InterchainAppV1Test { vm.assume(sender != linkedAppMockBytes32); expectRevertSrcSenderNotAllowed(REMOTE_CHAIN_ID, sender); vm.prank(icClient); - appHarness.appReceive({ - srcChainId: REMOTE_CHAIN_ID, - sender: sender, - dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, - message: message - }); + appHarness.appReceive({srcChainId: REMOTE_CHAIN_ID, sender: sender, dbNonce: MOCK_DB_NONCE, message: message}); } function test_getReceivingConfig() public view { diff --git a/packages/contracts-communication/test/harnesses/ICAppV1Harness.sol b/packages/contracts-communication/test/harnesses/ICAppV1Harness.sol index 8a1321e612..32d54d4641 100644 --- a/packages/contracts-communication/test/harnesses/ICAppV1Harness.sol +++ b/packages/contracts-communication/test/harnesses/ICAppV1Harness.sol @@ -77,12 +77,11 @@ contract ICAppV1Harness is ICAppV1, IInterchainAppV1Harness { uint64 srcChainId, bytes32 sender, uint64 dbNonce, - uint64 entryIndex, bytes calldata message ) internal override { - emit MessageReceived(srcChainId, sender, dbNonce, entryIndex, message); + emit MessageReceived(srcChainId, sender, dbNonce, message); } } diff --git a/packages/contracts-communication/test/harnesses/InterchainBatchLibHarness.sol b/packages/contracts-communication/test/harnesses/InterchainBatchLibHarness.sol deleted file mode 100644 index 754fe67cc6..0000000000 --- a/packages/contracts-communication/test/harnesses/InterchainBatchLibHarness.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import {InterchainBatch, InterchainBatchLib, BatchKey} from "../../contracts/libs/InterchainBatch.sol"; - -contract InterchainBatchLibHarness { - function constructLocalBatch(uint64 dbNonce, bytes32 batchRoot) external view returns (InterchainBatch memory) { - return InterchainBatchLib.constructLocalBatch(dbNonce, batchRoot); - } - - function encodeBatch(InterchainBatch memory batch) external pure returns (bytes memory) { - return InterchainBatchLib.encodeBatch(batch); - } - - function decodeBatch(bytes calldata batch) external pure returns (InterchainBatch memory) { - return InterchainBatchLib.decodeBatch(batch); - } - - function decodeBatchFromMemory(bytes memory batch) external pure returns (InterchainBatch memory) { - return InterchainBatchLib.decodeBatchFromMemory(batch); - } - - function encodeBatchKey(uint64 srcChainId, uint64 dbNonce) external pure returns (BatchKey) { - return InterchainBatchLib.encodeBatchKey(srcChainId, dbNonce); - } - - function decodeBatchKey(BatchKey key) external pure returns (uint64 srcChainId, uint64 dbNonce) { - return InterchainBatchLib.decodeBatchKey(key); - } -} diff --git a/packages/contracts-communication/test/harnesses/InterchainEntryLibHarness.sol b/packages/contracts-communication/test/harnesses/InterchainEntryLibHarness.sol index 034e8e3a9f..cb80b94836 100644 --- a/packages/contracts-communication/test/harnesses/InterchainEntryLibHarness.sol +++ b/packages/contracts-communication/test/harnesses/InterchainEntryLibHarness.sol @@ -1,27 +1,38 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {InterchainEntry, InterchainEntryLib} from "../../contracts/libs/InterchainEntry.sol"; +import {InterchainEntry, InterchainEntryLib, EntryKey} from "../../contracts/libs/InterchainEntry.sol"; contract InterchainEntryLibHarness { - function constructLocalEntry( - uint64 dbNonce, - uint64 entryIndex, - address srcWriter, - bytes32 dataHash - ) - external - view - returns (InterchainEntry memory) - { - return InterchainEntryLib.constructLocalEntry(dbNonce, entryIndex, srcWriter, dataHash); + function constructLocalEntry(uint64 dbNonce, bytes32 entryValue) external view returns (InterchainEntry memory) { + return InterchainEntryLib.constructLocalEntry(dbNonce, entryValue); } - function entryValue(InterchainEntry memory entry) external pure returns (bytes32) { - return InterchainEntryLib.entryValue(entry); + function getEntryValue(bytes32 srcWriter, bytes32 digest) external pure returns (bytes32) { + return InterchainEntryLib.getEntryValue(srcWriter, digest); } - function getEntryValue(bytes32 srcWriter, bytes32 dataHash) external pure returns (bytes32) { - return InterchainEntryLib.getEntryValue(srcWriter, dataHash); + function getEntryValue(address srcWriter, bytes32 digest) external pure returns (bytes32) { + return InterchainEntryLib.getEntryValue(srcWriter, digest); + } + + function encodeEntry(InterchainEntry memory entry) external pure returns (bytes memory) { + return InterchainEntryLib.encodeEntry(entry); + } + + function decodeEntry(bytes calldata entry) external pure returns (InterchainEntry memory) { + return InterchainEntryLib.decodeEntry(entry); + } + + function decodeEntryFromMemory(bytes memory entry) external pure returns (InterchainEntry memory) { + return InterchainEntryLib.decodeEntryFromMemory(entry); + } + + function encodeEntryKey(uint64 srcChainId, uint64 dbNonce) external pure returns (EntryKey) { + return InterchainEntryLib.encodeEntryKey(srcChainId, dbNonce); + } + + function decodeEntryKey(EntryKey key) external pure returns (uint64 srcChainId, uint64 dbNonce) { + return InterchainEntryLib.decodeEntryKey(key); } } diff --git a/packages/contracts-communication/test/harnesses/InterchainTransactionLibHarness.sol b/packages/contracts-communication/test/harnesses/InterchainTransactionLibHarness.sol index 9849a86f72..8a19a67243 100644 --- a/packages/contracts-communication/test/harnesses/InterchainTransactionLibHarness.sol +++ b/packages/contracts-communication/test/harnesses/InterchainTransactionLibHarness.sol @@ -11,7 +11,6 @@ contract InterchainTransactionLibHarness { uint64 dstChainId, bytes32 dstReceiver, uint64 dbNonce, - uint64 entryIndex, bytes memory options, bytes memory message ) @@ -20,7 +19,7 @@ contract InterchainTransactionLibHarness { returns (InterchainTransaction memory transaction) { return InterchainTransactionLib.constructLocalTransaction( - srcSender, dstChainId, dstReceiver, dbNonce, entryIndex, options, message + srcSender, dstChainId, dstReceiver, dbNonce, options, message ); } @@ -36,23 +35,14 @@ contract InterchainTransactionLibHarness { return InterchainTransactionLib.payloadSize(optionsLen, messageLen); } - function encodeTxHeader( - uint64 srcChainId, - uint64 dstChainId, - uint64 dbNonce, - uint64 entryIndex - ) - external - pure - returns (ICTxHeader) - { - return InterchainTransactionLib.encodeTxHeader(srcChainId, dstChainId, dbNonce, entryIndex); + function encodeTxHeader(uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) external pure returns (ICTxHeader) { + return InterchainTransactionLib.encodeTxHeader(srcChainId, dstChainId, dbNonce); } function decodeTxHeader(ICTxHeader header) external pure - returns (uint64 srcChainId, uint64 dstChainId, uint64 dbNonce, uint64 entryIndex) + returns (uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) { return InterchainTransactionLib.decodeTxHeader(header); } diff --git a/packages/contracts-communication/test/harnesses/ModuleBatchLibHarness.sol b/packages/contracts-communication/test/harnesses/ModuleBatchLibHarness.sol deleted file mode 100644 index 319e074267..0000000000 --- a/packages/contracts-communication/test/harnesses/ModuleBatchLibHarness.sol +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import {ModuleBatchLib} from "../../contracts/libs/ModuleBatch.sol"; - -contract ModuleBatchLibHarness { - function encodeVersionedModuleBatch( - bytes memory versionedBatch, - bytes memory moduleData - ) - external - pure - returns (bytes memory) - { - return ModuleBatchLib.encodeVersionedModuleBatch(versionedBatch, moduleData); - } - - function decodeVersionedModuleBatch(bytes memory encodedModuleBatch) - external - pure - returns (bytes memory, bytes memory) - { - return ModuleBatchLib.decodeVersionedModuleBatch(encodedModuleBatch); - } -} diff --git a/packages/contracts-communication/test/harnesses/ModuleEntryLibHarness.sol b/packages/contracts-communication/test/harnesses/ModuleEntryLibHarness.sol new file mode 100644 index 0000000000..067d22eb74 --- /dev/null +++ b/packages/contracts-communication/test/harnesses/ModuleEntryLibHarness.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {ModuleEntryLib} from "../../contracts/libs/ModuleEntry.sol"; + +contract ModuleEntryLibHarness { + function encodeVersionedModuleEntry( + bytes memory versionedEntry, + bytes memory moduleData + ) + external + pure + returns (bytes memory) + { + return ModuleEntryLib.encodeVersionedModuleEntry(versionedEntry, moduleData); + } + + function decodeVersionedModuleEntry(bytes memory encodedModuleEntry) + external + pure + returns (bytes memory, bytes memory) + { + return ModuleEntryLib.decodeVersionedModuleEntry(encodedModuleEntry); + } +} diff --git a/packages/contracts-communication/test/integration/ICIntegration.t.sol b/packages/contracts-communication/test/integration/ICIntegration.t.sol index 4055fd57e0..97b2e370ab 100644 --- a/packages/contracts-communication/test/integration/ICIntegration.t.sol +++ b/packages/contracts-communication/test/integration/ICIntegration.t.sol @@ -8,10 +8,9 @@ import {InterchainModuleEvents} from "../../contracts/events/InterchainModuleEve import {IInterchainApp} from "../../contracts/interfaces/IInterchainApp.sol"; import {IInterchainClientV1} from "../../contracts/interfaces/IInterchainClientV1.sol"; -import {InterchainBatch} from "../../contracts/libs/InterchainBatch.sol"; import {InterchainEntry} from "../../contracts/libs/InterchainEntry.sol"; import {InterchainTransaction, InterchainTxDescriptor} from "../../contracts/libs/InterchainTransaction.sol"; -import {ModuleBatchLib} from "../../contracts/libs/ModuleBatch.sol"; +import {ModuleEntryLib} from "../../contracts/libs/ModuleEntry.sol"; import {OptionsV1} from "../../contracts/libs/Options.sol"; import {ICSetup, TypeCasts} from "./ICSetup.t.sol"; @@ -25,20 +24,20 @@ abstract contract ICIntegrationTest is InterchainDBEvents, InterchainModuleEvents { - using TypeCasts for address; - - function assertEq(InterchainBatch memory batch, InterchainBatch memory expected) internal pure { - assertEq(batch.srcChainId, expected.srcChainId); - assertEq(batch.dbNonce, expected.dbNonce); - assertEq(batch.batchRoot, expected.batchRoot); + struct FullEntry { + uint64 srcChainId; + uint64 dbNonce; + bytes32 entryValue; + bytes32 srcWriter; + bytes32 digest; } + using TypeCasts for address; + function assertEq(InterchainEntry memory entry, InterchainEntry memory expected) internal pure { assertEq(entry.srcChainId, expected.srcChainId); assertEq(entry.dbNonce, expected.dbNonce); - assertEq(entry.entryIndex, expected.entryIndex); - assertEq(entry.srcWriter, expected.srcWriter); - assertEq(entry.dataHash, expected.dataHash); + assertEq(entry.entryValue, expected.entryValue); } function expectServiceEventExecutionRequested(bytes32 transactionId, uint256 executionFee) internal { @@ -57,7 +56,6 @@ abstract contract ICIntegrationTest is emit InterchainTransactionSent({ transactionId: getTxId(icTx), dbNonce: icTx.dbNonce, - entryIndex: icTx.entryIndex, dstChainId: icTx.dstChainId, srcSender: icTx.srcSender, dstReceiver: icTx.dstReceiver, @@ -73,66 +71,58 @@ abstract contract ICIntegrationTest is emit InterchainTransactionReceived({ transactionId: getTxId(icTx), dbNonce: icTx.dbNonce, - entryIndex: icTx.entryIndex, srcChainId: icTx.srcChainId, srcSender: icTx.srcSender, dstReceiver: icTx.dstReceiver }); } - function expectDatabaseEventInterchainEntryWritten(InterchainEntry memory entry) internal { + function expectDatabaseEventInterchainEntryWritten(FullEntry memory fullEntry) internal { vm.expectEmit(address(icDB)); emit InterchainEntryWritten({ - dbNonce: entry.dbNonce, - entryIndex: entry.entryIndex, - srcWriter: entry.srcWriter, - dataHash: entry.dataHash + dbNonce: fullEntry.dbNonce, + srcWriter: fullEntry.srcWriter, + digest: fullEntry.digest, + entryValue: fullEntry.entryValue }); } - function expectDatabaseEventInterchainBatchFinalized(InterchainBatch memory batch) internal { + function expectDatabaseEventInterchainEntryVerified(FullEntry memory fullEntry) internal { vm.expectEmit(address(icDB)); - emit InterchainBatchFinalized({dbNonce: batch.dbNonce, batchRoot: batch.batchRoot}); - } - - function expectDatabaseEventInterchainBatchVerified(InterchainBatch memory batch) internal { - vm.expectEmit(address(icDB)); - emit InterchainBatchVerified({ + emit InterchainEntryVerified({ module: address(module), - srcChainId: batch.srcChainId, - dbNonce: batch.dbNonce, - batchRoot: batch.batchRoot + srcChainId: fullEntry.srcChainId, + dbNonce: fullEntry.dbNonce, + entryValue: fullEntry.entryValue }); } - function expectDatabaseEventInterchainBatchVerificationRequested(InterchainBatch memory batch) internal { + function expectDatabaseEventInterchainEntryVerificationRequested(FullEntry memory fullEntry) internal { vm.expectEmit(address(icDB)); - emit InterchainBatchVerificationRequested({ + emit InterchainEntryVerificationRequested({ dstChainId: remoteChainId(), - dbNonce: batch.dbNonce, - batchRoot: batch.batchRoot, + dbNonce: fullEntry.dbNonce, srcModules: toArray(address(module)) }); } - function expectModuleEventBatchVerificationRequested(InterchainBatch memory batch) internal { - bytes memory encodedBatch = getModuleBatch(batch); - bytes32 digest = getEthSignedBatchHash(batch); + function expectModuleEventEntryVerificationRequested(FullEntry memory fullEntry) internal { + bytes memory encodedEntry = getModuleEntry(fullEntry); + bytes32 digest = getEthSignedEntryHash(fullEntry); vm.expectEmit(address(module)); - emit BatchVerificationRequested({dstChainId: remoteChainId(), batch: encodedBatch, ethSignedBatchHash: digest}); + emit EntryVerificationRequested({dstChainId: remoteChainId(), entry: encodedEntry, ethSignedEntryHash: digest}); } - function expectModuleEventBatchVerified(InterchainBatch memory batch) internal { - bytes memory encodedBatch = getModuleBatch(batch); - bytes32 digest = getEthSignedBatchHash(batch); + function expectModuleEventEntryVerified(FullEntry memory fullEntry) internal { + bytes memory encodedEntry = getModuleEntry(fullEntry); + bytes32 digest = getEthSignedEntryHash(fullEntry); vm.expectEmit(address(module)); - emit BatchVerified({srcChainId: batch.srcChainId, batch: encodedBatch, ethSignedBatchHash: digest}); + emit EntryVerified({srcChainId: fullEntry.srcChainId, entry: encodedEntry, ethSignedEntryHash: digest}); } function expectAppCall(InterchainTransaction memory icTx, OptionsV1 memory options) internal { - bytes memory expectedCalldata = abi.encodeCall( - IInterchainApp.appReceive, (icTx.srcChainId, icTx.srcSender, icTx.dbNonce, icTx.entryIndex, icTx.message) - ); + bytes memory expectedCalldata = + abi.encodeCall(IInterchainApp.appReceive, (icTx.srcChainId, icTx.srcSender, icTx.dbNonce, icTx.message)); vm.expectCall({ callee: localApp(), msgValue: options.gasAirdrop, @@ -146,26 +136,24 @@ abstract contract ICIntegrationTest is function expectEventsMessageSent( InterchainTransaction memory icTx, - InterchainEntry memory entry, + FullEntry memory fullEntry, uint256 verificationFee, uint256 executionFee ) internal { - InterchainBatch memory batch = getInterchainBatch(entry); - InterchainTxDescriptor memory desc = getInterchainTxDescriptor(entry); - expectDatabaseEventInterchainEntryWritten(entry); - expectDatabaseEventInterchainBatchFinalized(batch); - expectModuleEventBatchVerificationRequested(batch); - expectDatabaseEventInterchainBatchVerificationRequested(batch); + InterchainTxDescriptor memory desc = getInterchainTxDescriptor(fullEntry); + expectDatabaseEventInterchainEntryWritten(fullEntry); + expectModuleEventEntryVerificationRequested(fullEntry); + expectDatabaseEventInterchainEntryVerificationRequested(fullEntry); expectServiceEventExecutionRequested(desc.transactionId, executionFee); expectClientEventInterchainTransactionSent(icTx, verificationFee, executionFee); } // ══════════════════════════════════════════════ EXPECT REVERTS ═══════════════════════════════════════════════════ - function expectClientRevertBatchConflict(address module) internal { - vm.expectRevert(abi.encodeWithSelector(IInterchainClientV1.InterchainClientV1__BatchConflict.selector, module)); + function expectClientRevertEntryConflict(address module) internal { + vm.expectRevert(abi.encodeWithSelector(IInterchainClientV1.InterchainClientV1__EntryConflict.selector, module)); } function expectClientRevertResponsesAmountBelowMin(uint256 actual, uint256 required) internal { @@ -184,45 +172,33 @@ abstract contract ICIntegrationTest is ); } - function checkBatchLeafs(InterchainBatch memory batch, bytes32[] memory leafs) internal pure { - assertEq(leafs.length, 1); - assertEq(leafs[0], batch.batchRoot); - } - - function checkDatabaseStateMsgSent(InterchainEntry memory entry, uint64 initialDBNonce) internal view { - InterchainBatch memory batch = getInterchainBatch(entry); - InterchainTxDescriptor memory desc = getInterchainTxDescriptor(entry); + function checkDatabaseStateMsgSent(FullEntry memory fullEntry, uint64 initialDBNonce) internal view { + InterchainEntry memory entry = getInterchainEntry(fullEntry); + InterchainTxDescriptor memory desc = getInterchainTxDescriptor(fullEntry); assertEq(desc.dbNonce, initialDBNonce); // Check getters related to the txs' dbNonce - checkBatchLeafs(batch, icDB.getBatchLeafs(desc.dbNonce)); - checkBatchLeafs(batch, icDB.getBatchLeafsPaginated(desc.dbNonce, 0, 1)); - assertEq(icDB.getBatchSize(desc.dbNonce), 1); - assertEq(icDB.getBatch(desc.dbNonce), batch); - assertEq(icDB.getEntryValue(desc.dbNonce, 0), batch.batchRoot); - assertEq(icDB.getEntryProof(desc.dbNonce, 0).length, 0); + assertEq(icDB.getEntry(desc.dbNonce), entry); + assertEq(icDB.getEntryValue(desc.dbNonce), entry.entryValue); // Check getters related to the next dbNonce assertEq(icDB.getDBNonce(), desc.dbNonce + 1); - (uint64 dbNonce, uint64 entryIndex) = icDB.getNextEntryIndex(); - assertEq(dbNonce, desc.dbNonce + 1); - assertEq(entryIndex, 0); } - function markInvalidByGuard(InterchainBatch memory batch) internal { - InterchainBatch memory conflictingBatch = InterchainBatch({ - srcChainId: batch.srcChainId, - dbNonce: batch.dbNonce, - batchRoot: keccak256("Some other data") + function markInvalidByGuard(FullEntry memory fullEntry) internal { + InterchainEntry memory conflictingEntry = InterchainEntry({ + srcChainId: fullEntry.srcChainId, + dbNonce: fullEntry.dbNonce, + entryValue: keccak256("Some other data") }); - bytes memory encodedBatch = - payloadLibHarness.encodeVersionedPayload(DB_VERSION, batchLibHarness.encodeBatch(conflictingBatch)); + bytes memory encodedEntry = + payloadLibHarness.encodeVersionedPayload(DB_VERSION, entryLibHarness.encodeEntry(conflictingEntry)); vm.prank(guard); - icDB.verifyRemoteBatch(encodedBatch); + icDB.verifyRemoteEntry(encodedEntry); } // ═══════════════════════════════════════════════ DATA HELPERS ════════════════════════════════════════════════════ - function getModuleSignatures(InterchainBatch memory batch) internal view returns (bytes memory signatures) { - bytes32 digest = getEthSignedBatchHash(batch); + function getModuleSignatures(FullEntry memory fullEntry) internal view returns (bytes memory signatures) { + bytes32 digest = getEthSignedEntryHash(fullEntry); signatures = ""; for (uint256 i = 0; i < signerPKs.length; i++) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(signerPKs[i], digest); @@ -230,54 +206,55 @@ abstract contract ICIntegrationTest is } } - function getEthSignedBatchHash(InterchainBatch memory batch) internal view returns (bytes32) { - bytes memory moduleBatch = getModuleBatch(batch); - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(moduleBatch))); + function getEthSignedEntryHash(FullEntry memory fullEntry) internal view returns (bytes32) { + bytes memory moduleEntry = getModuleEntry(fullEntry); + return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(moduleEntry))); } - function getModuleBatch(InterchainBatch memory batch) internal view returns (bytes memory) { - bytes memory versionedBatch = - payloadLibHarness.encodeVersionedPayload(DB_VERSION, batchLibHarness.encodeBatch(batch)); - return ModuleBatchLib.encodeVersionedModuleBatch(versionedBatch, new bytes(0)); + function getModuleEntry(FullEntry memory fullEntry) internal view returns (bytes memory) { + bytes memory versionedEntry = payloadLibHarness.encodeVersionedPayload( + DB_VERSION, entryLibHarness.encodeEntry(getInterchainEntry(fullEntry)) + ); + return ModuleEntryLib.encodeVersionedModuleEntry(versionedEntry, new bytes(0)); } - function getInterchainBatch(InterchainEntry memory entry) internal pure returns (InterchainBatch memory) { - return InterchainBatch({ - srcChainId: entry.srcChainId, - dbNonce: entry.dbNonce, - batchRoot: keccak256(abi.encode(entry.srcWriter, entry.dataHash)) + function getInterchainEntry(FullEntry memory fullEntry) internal pure returns (InterchainEntry memory) { + return InterchainEntry({ + srcChainId: fullEntry.srcChainId, + dbNonce: fullEntry.dbNonce, + entryValue: fullEntry.entryValue }); } - function getInterchainTxDescriptor(InterchainEntry memory entry) + function getInterchainTxDescriptor(FullEntry memory fullEntry) internal pure returns (InterchainTxDescriptor memory) { - return InterchainTxDescriptor({ - dbNonce: entry.dbNonce, - entryIndex: entry.entryIndex, - transactionId: entry.dataHash - }); + return InterchainTxDescriptor({dbNonce: fullEntry.dbNonce, transactionId: fullEntry.digest}); } - function getSrcInterchainEntry() internal view returns (InterchainEntry memory) { - return InterchainEntry({ + function getSrcFullEntry() internal view returns (FullEntry memory) { + bytes32 srcWriter = address(icClient).addressToBytes32(); + bytes32 digest = getTxId(getSrcTransaction()); + return FullEntry({ srcChainId: SRC_CHAIN_ID, dbNonce: SRC_INITIAL_DB_NONCE, - entryIndex: 0, - srcWriter: address(icClient).addressToBytes32(), - dataHash: getTxId(getSrcTransaction()) + entryValue: entryLibHarness.getEntryValue(srcWriter, digest), + srcWriter: srcWriter, + digest: digest }); } - function getDstInterchainEntry() internal view returns (InterchainEntry memory) { - return InterchainEntry({ + function getDstFullEntry() internal view returns (FullEntry memory) { + bytes32 srcWriter = address(icClient).addressToBytes32(); + bytes32 digest = getTxId(getDstTransaction()); + return FullEntry({ srcChainId: DST_CHAIN_ID, dbNonce: DST_INITIAL_DB_NONCE, - entryIndex: 0, - srcWriter: address(icClient).addressToBytes32(), - dataHash: getTxId(getDstTransaction()) + entryValue: entryLibHarness.getEntryValue(srcWriter, digest), + srcWriter: srcWriter, + digest: digest }); } @@ -296,7 +273,6 @@ abstract contract ICIntegrationTest is dstChainId: DST_CHAIN_ID, dstReceiver: address(dstApp).addressToBytes32(), dbNonce: SRC_INITIAL_DB_NONCE, - entryIndex: 0, options: getSrcOptions().encodeOptionsV1(), message: getSrcMessage() }); @@ -309,7 +285,6 @@ abstract contract ICIntegrationTest is dstChainId: SRC_CHAIN_ID, dstReceiver: address(srcApp).addressToBytes32(), dbNonce: DST_INITIAL_DB_NONCE, - entryIndex: 0, options: getDstOptions().encodeOptionsV1(), message: getDstMessage() }); diff --git a/packages/contracts-communication/test/integration/ICSetup.t.sol b/packages/contracts-communication/test/integration/ICSetup.t.sol index 7fc0c24695..1ecd4ff7f9 100644 --- a/packages/contracts-communication/test/integration/ICSetup.t.sol +++ b/packages/contracts-communication/test/integration/ICSetup.t.sol @@ -10,7 +10,7 @@ import {SynapseGasOracleV1, ISynapseGasOracleV1} from "../../contracts/oracles/S import {TypeCasts} from "../../contracts/libs/TypeCasts.sol"; -import {InterchainBatchLibHarness} from "../harnesses/InterchainBatchLibHarness.sol"; +import {InterchainEntryLibHarness} from "../harnesses/InterchainEntryLibHarness.sol"; import {InterchainTransactionLibHarness} from "../harnesses/InterchainTransactionLibHarness.sol"; import {VersionedPayloadLibHarness} from "../harnesses/VersionedPayloadLibHarness.sol"; import {ProxyTest} from "../proxy/ProxyTest.t.sol"; @@ -33,7 +33,7 @@ abstract contract ICSetup is ProxyTest { uint256 public constant INITIAL_TS = 1_704_067_200; // 2024-01-01 00:00:00 UTC - InterchainBatchLibHarness public batchLibHarness; + InterchainEntryLibHarness public entryLibHarness; InterchainTransactionLibHarness public txLibHarness; VersionedPayloadLibHarness public payloadLibHarness; @@ -72,7 +72,7 @@ abstract contract ICSetup is ProxyTest { } function deployLibraryHarnesses() internal virtual { - batchLibHarness = new InterchainBatchLibHarness(); + entryLibHarness = new InterchainEntryLibHarness(); txLibHarness = new InterchainTransactionLibHarness(); payloadLibHarness = new VersionedPayloadLibHarness(); } diff --git a/packages/contracts-communication/test/integration/PingPong.Dst.t.sol b/packages/contracts-communication/test/integration/PingPong.Dst.t.sol index e656dfefa7..c92bda0113 100644 --- a/packages/contracts-communication/test/integration/PingPong.Dst.t.sol +++ b/packages/contracts-communication/test/integration/PingPong.Dst.t.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.20; import {IInterchainClientV1} from "../../contracts/interfaces/IInterchainClientV1.sol"; -import {InterchainBatch} from "../../contracts/libs/InterchainBatch.sol"; import {InterchainEntry} from "../../contracts/libs/InterchainEntry.sol"; import {InterchainTransaction, InterchainTxDescriptor} from "../../contracts/libs/InterchainTransaction.sol"; import {OptionsV1} from "../../contracts/libs/Options.sol"; @@ -14,14 +13,12 @@ import {PingPongIntegrationTest} from "./PingPong.t.sol"; contract PingPongDstIntegrationTest is PingPongIntegrationTest { uint256 public constant LONG_PERIOD = 1 weeks; - InterchainBatch public srcBatch; - InterchainEntry public srcEntry; + FullEntry public srcFullEntry; InterchainTransaction public srcTx; InterchainTxDescriptor public srcDesc; bytes public encodedSrcTx; - InterchainBatch public dstBatch; - InterchainEntry public dstEntry; + FullEntry public dstFullEntry; InterchainTransaction public dstTx; InterchainTxDescriptor public dstDesc; @@ -29,24 +26,22 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { uint256 public dstVerificationFee; uint256 public dstExecutionFee; - bytes public moduleBatch; + bytes public moduleEntry; bytes public moduleSignatures; function setUp() public override { super.setUp(); srcTx = getSrcTransaction(); - srcEntry = getSrcInterchainEntry(); - srcDesc = getInterchainTxDescriptor(srcEntry); - srcBatch = getInterchainBatch(srcEntry); + srcFullEntry = getSrcFullEntry(); + srcDesc = getInterchainTxDescriptor(srcFullEntry); encodedSrcTx = getEncodedTx(srcTx); - moduleBatch = getModuleBatch(srcBatch); - moduleSignatures = getModuleSignatures(srcBatch); + moduleEntry = getModuleEntry(srcFullEntry); + moduleSignatures = getModuleSignatures(srcFullEntry); dstTx = getDstTransaction(); - dstEntry = getDstInterchainEntry(); - dstDesc = getInterchainTxDescriptor(dstEntry); - dstBatch = getInterchainBatch(dstEntry); + dstFullEntry = getDstFullEntry(); + dstDesc = getInterchainTxDescriptor(dstFullEntry); dstPingFee = dstPingPongApp().getPingFee(SRC_CHAIN_ID); dstVerificationFee = icDB.getInterchainFee(SRC_CHAIN_ID, toArray(address(module))); @@ -59,35 +54,32 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { function executeTx(OptionsV1 memory options) internal { vm.prank(executor); - icClient.interchainExecute{value: options.gasAirdrop}({ - gasLimit: options.gasLimit, - transaction: encodedSrcTx, - proof: new bytes32[](0) - }); + icClient.interchainExecute{value: options.gasAirdrop}({gasLimit: options.gasLimit, transaction: encodedSrcTx}); } - function test_verifyRemoteBatch_events() public { - expectDatabaseEventInterchainBatchVerified(srcBatch); - expectModuleEventBatchVerified(srcBatch); - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + function test_verifyRemoteEntry_events() public { + expectDatabaseEventInterchainEntryVerified(srcFullEntry); + expectModuleEventEntryVerified(srcFullEntry); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); } - function test_verifyRemoteBatch_state_client() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + function test_verifyRemoteEntry_state_client() public { + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); assertEq(icClient.getExecutor(encodedSrcTx), address(0)); assertEq(icClient.getExecutorById(srcDesc.transactionId), address(0)); - assertTrue(icClient.isExecutable(encodedSrcTx, new bytes32[](0))); + assertTrue(icClient.isExecutable(encodedSrcTx)); } - function test_verifyRemoteBatch_state_db() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + function test_verifyRemoteEntry_state_db() public { + InterchainEntry memory srcEntry = getInterchainEntry(srcFullEntry); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(LONG_PERIOD); - assertEq(icDB.checkBatchVerification(address(module), srcBatch), INITIAL_TS); + assertEq(icDB.checkEntryVerification(address(module), srcEntry), INITIAL_TS); } function test_interchainExecute_callPingPongApp() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); expectAppCall(srcTx, ppOptions); executeTx(ppOptions); @@ -95,7 +87,7 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { function test_interchainExecute_callPingPongApp_lowerGas() public { OptionsV1 memory options = OptionsV1({gasLimit: ppOptions.gasLimit / 2, gasAirdrop: ppOptions.gasAirdrop}); - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); // Should use the requested gas limit expectAppCall(srcTx, ppOptions); @@ -104,7 +96,7 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { function test_interchainExecute_callPingPongApp_higherGas() public { OptionsV1 memory options = OptionsV1({gasLimit: 2 * ppOptions.gasLimit, gasAirdrop: ppOptions.gasAirdrop}); - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); // Should allow to use higher gas limit expectAppCall(srcTx, options); @@ -112,16 +104,16 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { } function test_interchainExecute_events() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); - expectPingPongEventPingReceived(COUNTER, srcEntry); - expectEventsPingSent(COUNTER - 1, dstTx, dstEntry, dstVerificationFee, dstExecutionFee); + expectPingPongEventPingReceived(COUNTER, srcFullEntry); + expectEventsPingSent(COUNTER - 1, dstTx, dstFullEntry, dstVerificationFee, dstExecutionFee); expectClientEventInterchainTransactionReceived(srcTx); executeTx(ppOptions); } function test_interchainExecute_state_client() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); assertEq(icClient.getExecutor(encodedSrcTx), executor); @@ -131,32 +123,32 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { IInterchainClientV1.InterchainClientV1__TxAlreadyExecuted.selector, srcDesc.transactionId ) ); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_interchainExecute_state_db() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); - checkDatabaseStateMsgSent(dstEntry, DST_INITIAL_DB_NONCE); + checkDatabaseStateMsgSent(dstFullEntry, DST_INITIAL_DB_NONCE); } function test_interchainExecute_state_execService() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); assertEq(address(executionService).balance, dstExecutionFee); } function test_interchainExecute_state_pingPongApp() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); assertEq(dstApp.balance, PING_PONG_BALANCE - dstPingFee); } function test_interchainExecute_state_synapseModule() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); assertEq(address(module).balance, dstVerificationFee); @@ -169,41 +161,41 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { } function test_interchainExecute_revert_notConfirmed_guardMarked() public { - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); executeTx(ppOptions); } function test_interchainExecute_revert_confirmed_sameBlock() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); executeTx(ppOptions); } function test_interchainExecute_revert_confirmed_sameBlock_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); executeTx(ppOptions); } function test_interchainExecute_revert_confirmed_periodMinusOneSecond() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); executeTx(ppOptions); } function test_interchainExecute_revert_confirmed_periodMinusOneSecond_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); - markInvalidByGuard(srcBatch); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); + markInvalidByGuard(srcFullEntry); skip(APP_OPTIMISTIC_PERIOD); - expectClientRevertBatchConflict(guard); + expectClientRevertEntryConflict(guard); executeTx(ppOptions); } function test_interchainExecute_revert_alreadyExecuted() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); expectClientRevertTxAlreadyExecuted(srcDesc); @@ -211,56 +203,56 @@ contract PingPongDstIntegrationTest is PingPongIntegrationTest { } function test_isExecutable() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); - assertTrue(icClient.isExecutable(encodedSrcTx, new bytes32[](0))); + assertTrue(icClient.isExecutable(encodedSrcTx)); } function test_isExecutable_revert_notConfirmed() public { expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_notConfirmed_guardMarked() public { - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_sameBlock() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_sameBlock_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_periodMinusOneSecond() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_periodMinusOneSecond_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); - markInvalidByGuard(srcBatch); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); + markInvalidByGuard(srcFullEntry); skip(APP_OPTIMISTIC_PERIOD); - expectClientRevertBatchConflict(guard); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + expectClientRevertEntryConflict(guard); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_alreadyExecuted() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(ppOptions); expectClientRevertTxAlreadyExecuted(srcDesc); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function localChainId() internal pure override returns (uint64) { diff --git a/packages/contracts-communication/test/integration/PingPong.Src.t.sol b/packages/contracts-communication/test/integration/PingPong.Src.t.sol index 73f1464d0a..42474212c6 100644 --- a/packages/contracts-communication/test/integration/PingPong.Src.t.sol +++ b/packages/contracts-communication/test/integration/PingPong.Src.t.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {InterchainBatch} from "../../contracts/libs/InterchainBatch.sol"; -import {InterchainEntry} from "../../contracts/libs/InterchainEntry.sol"; import {InterchainTransaction, InterchainTxDescriptor} from "../../contracts/libs/InterchainTransaction.sol"; import {PingPongIntegrationTest} from "./PingPong.t.sol"; @@ -10,8 +8,7 @@ import {PingPongIntegrationTest} from "./PingPong.t.sol"; // solhint-disable func-name-mixedcase // solhint-disable ordering contract PingPongSrcIntegrationTest is PingPongIntegrationTest { - InterchainBatch public batch; - InterchainEntry public entry; + FullEntry public fullEntry; InterchainTransaction public icTx; InterchainTxDescriptor public desc; @@ -22,9 +19,8 @@ contract PingPongSrcIntegrationTest is PingPongIntegrationTest { function setUp() public override { super.setUp(); icTx = getSrcTransaction(); - entry = getSrcInterchainEntry(); - desc = getInterchainTxDescriptor(entry); - batch = getInterchainBatch(entry); + fullEntry = getSrcFullEntry(); + desc = getInterchainTxDescriptor(fullEntry); pingFee = srcPingPongApp().getPingFee(DST_CHAIN_ID); verificationFee = icDB.getInterchainFee(DST_CHAIN_ID, toArray(address(module))); executionFee = executionService.getExecutionFee({ @@ -35,13 +31,13 @@ contract PingPongSrcIntegrationTest is PingPongIntegrationTest { } function test_startPingPong_events() public { - expectEventsPingSent(COUNTER, icTx, entry, verificationFee, executionFee); + expectEventsPingSent(COUNTER, icTx, fullEntry, verificationFee, executionFee); srcPingPongApp().startPingPong(DST_CHAIN_ID, COUNTER); } function test_startPingPong_state_db() public { srcPingPongApp().startPingPong(DST_CHAIN_ID, COUNTER); - checkDatabaseStateMsgSent(entry, SRC_INITIAL_DB_NONCE); + checkDatabaseStateMsgSent(fullEntry, SRC_INITIAL_DB_NONCE); } function test_startPingPong_state_execService() public { diff --git a/packages/contracts-communication/test/integration/PingPong.t.sol b/packages/contracts-communication/test/integration/PingPong.t.sol index 415b58ab66..366368c17d 100644 --- a/packages/contracts-communication/test/integration/PingPong.t.sol +++ b/packages/contracts-communication/test/integration/PingPong.t.sol @@ -15,8 +15,8 @@ abstract contract PingPongIntegrationTest is ICIntegrationTest { OptionsV1 public ppOptions = OptionsV1({gasLimit: 500_000, gasAirdrop: 0}); - event PingReceived(uint256 counter, uint64 dbNonce, uint64 entryIndex); - event PingSent(uint256 counter, uint64 dbNonce, uint64 entryIndex); + event PingReceived(uint256 counter, uint64 dbNonce); + event PingSent(uint256 counter, uint64 dbNonce); /// @dev Should deploy the tested app and return its address. function deployApp() internal override returns (address app) { @@ -24,14 +24,14 @@ abstract contract PingPongIntegrationTest is ICIntegrationTest { deal(app, PING_PONG_BALANCE); } - function expectPingPongEventPingReceived(uint256 counter, InterchainEntry memory entry) internal { + function expectPingPongEventPingReceived(uint256 counter, FullEntry memory fullEntry) internal { vm.expectEmit(localApp()); - emit PingReceived(counter, entry.dbNonce, entry.entryIndex); + emit PingReceived(counter, fullEntry.dbNonce); } - function expectPingPongEventPingSent(uint256 counter, InterchainEntry memory entry) internal { + function expectPingPongEventPingSent(uint256 counter, FullEntry memory fullEntry) internal { vm.expectEmit(localApp()); - emit PingSent(counter, entry.dbNonce, entry.entryIndex); + emit PingSent(counter, fullEntry.dbNonce); } // ═══════════════════════════════════════════ COMPLEX SERIES CHECKS ═══════════════════════════════════════════════ @@ -39,14 +39,14 @@ abstract contract PingPongIntegrationTest is ICIntegrationTest { function expectEventsPingSent( uint256 counter, InterchainTransaction memory icTx, - InterchainEntry memory entry, + FullEntry memory fullEntry, uint256 verificationFee, uint256 executionFee ) internal { - expectEventsMessageSent(icTx, entry, verificationFee, executionFee); - expectPingPongEventPingSent(counter, entry); + expectEventsMessageSent(icTx, fullEntry, verificationFee, executionFee); + expectPingPongEventPingSent(counter, fullEntry); } // ═══════════════════════════════════════════════ DATA HELPERS ════════════════════════════════════════════════════ diff --git a/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Dst.t.sol b/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Dst.t.sol index 6b3bf92545..a1861a4696 100644 --- a/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Dst.t.sol +++ b/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Dst.t.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.20; import {IInterchainClientV1} from "../../../contracts/interfaces/IInterchainClientV1.sol"; -import {InterchainBatch} from "../../../contracts/libs/InterchainBatch.sol"; import {InterchainEntry} from "../../../contracts/libs/InterchainEntry.sol"; import {InterchainTransaction, InterchainTxDescriptor} from "../../../contracts/libs/InterchainTransaction.sol"; import {OptionsV1} from "../../../contracts/libs/Options.sol"; @@ -14,14 +13,12 @@ import {LegacyPingPongIntegrationTest} from "./LegacyPingPong.t.sol"; contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { uint256 public constant LONG_PERIOD = 1 weeks; - InterchainBatch public srcBatch; - InterchainEntry public srcEntry; + FullEntry public srcFullEntry; InterchainTransaction public srcTx; InterchainTxDescriptor public srcDesc; bytes public encodedSrcTx; - InterchainBatch public dstBatch; - InterchainEntry public dstEntry; + FullEntry public dstFullEntry; InterchainTransaction public dstTx; InterchainTxDescriptor public dstDesc; @@ -29,24 +26,22 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { uint256 public dstVerificationFee; uint256 public dstExecutionFee; - bytes public moduleBatch; + bytes public moduleEntry; bytes public moduleSignatures; function setUp() public override { super.setUp(); srcTx = getSrcTransaction(); - srcEntry = getSrcInterchainEntry(); - srcDesc = getInterchainTxDescriptor(srcEntry); - srcBatch = getInterchainBatch(srcEntry); + srcFullEntry = getSrcFullEntry(); + srcDesc = getInterchainTxDescriptor(srcFullEntry); encodedSrcTx = getEncodedTx(srcTx); - moduleBatch = getModuleBatch(srcBatch); - moduleSignatures = getModuleSignatures(srcBatch); + moduleEntry = getModuleEntry(srcFullEntry); + moduleSignatures = getModuleSignatures(srcFullEntry); dstTx = getDstTransaction(); - dstEntry = getDstInterchainEntry(); - dstDesc = getInterchainTxDescriptor(dstEntry); - dstBatch = getInterchainBatch(dstEntry); + dstFullEntry = getDstFullEntry(); + dstDesc = getInterchainTxDescriptor(dstFullEntry); dstPingFee = dstLegacyPingPong().getPingFee(SRC_CHAIN_ID); dstVerificationFee = icDB.getInterchainFee(SRC_CHAIN_ID, toArray(address(module))); @@ -59,35 +54,32 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { function executeTx(OptionsV1 memory options) internal { vm.prank(executor); - icClient.interchainExecute{value: options.gasAirdrop}({ - gasLimit: options.gasLimit, - transaction: encodedSrcTx, - proof: new bytes32[](0) - }); + icClient.interchainExecute{value: options.gasAirdrop}({gasLimit: options.gasLimit, transaction: encodedSrcTx}); } - function test_verifyRemoteBatch_events() public { - expectDatabaseEventInterchainBatchVerified(srcBatch); - expectModuleEventBatchVerified(srcBatch); - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + function test_verifyRemoteEntry_events() public { + expectDatabaseEventInterchainEntryVerified(srcFullEntry); + expectModuleEventEntryVerified(srcFullEntry); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); } - function test_verifyRemoteBatch_state_client() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + function test_verifyRemoteEntry_state_client() public { + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); assertEq(icClient.getExecutor(encodedSrcTx), address(0)); assertEq(icClient.getExecutorById(srcDesc.transactionId), address(0)); - assertTrue(icClient.isExecutable(encodedSrcTx, new bytes32[](0))); + assertTrue(icClient.isExecutable(encodedSrcTx)); } - function test_verifyRemoteBatch_state_db() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + function test_verifyRemoteEntry_state_db() public { + InterchainEntry memory entry = getInterchainEntry(srcFullEntry); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(LONG_PERIOD); - assertEq(icDB.checkBatchVerification(address(module), srcBatch), INITIAL_TS); + assertEq(icDB.checkEntryVerification(address(module), entry), INITIAL_TS); } function test_interchainExecute_callMessageBusAndLegacyPP() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); expectAppCall(srcTx, icOptions); expectPingPongCall(); @@ -96,7 +88,7 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { function test_interchainExecute_callMessageBusAndLegacyPP_lowerGas() public { OptionsV1 memory options = OptionsV1({gasLimit: icOptions.gasLimit / 2, gasAirdrop: 0}); - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); // Should use the requested gas limit expectAppCall(srcTx, icOptions); @@ -106,7 +98,7 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { function test_interchainExecute_callMessageBusAndLegacyPP_higherGas() public { OptionsV1 memory options = OptionsV1({gasLimit: 2 * icOptions.gasLimit, gasAirdrop: 0}); - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); // Should allow to use higher gas limit expectAppCall(srcTx, options); @@ -115,16 +107,16 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { } function test_interchainExecute_events() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); expectPingPongEventPingReceived(COUNTER); - expectEventsPingSent(COUNTER - 1, dstTx, dstEntry, dstVerificationFee, dstExecutionFee); + expectEventsPingSent(COUNTER - 1, dstTx, dstFullEntry, dstVerificationFee, dstExecutionFee); expectClientEventInterchainTransactionReceived(srcTx); executeTx(icOptions); } function test_interchainExecute_state_client() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); assertEq(icClient.getExecutor(encodedSrcTx), executor); @@ -134,32 +126,32 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { IInterchainClientV1.InterchainClientV1__TxAlreadyExecuted.selector, srcDesc.transactionId ) ); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_interchainExecute_state_db() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); - checkDatabaseStateMsgSent(dstEntry, DST_INITIAL_DB_NONCE); + checkDatabaseStateMsgSent(dstFullEntry, DST_INITIAL_DB_NONCE); } function test_interchainExecute_state_execService() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); assertEq(address(executionService).balance, dstExecutionFee); } function test_interchainExecute_state_legacyPingPong() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); assertEq(address(dstLegacyPingPong()).balance, PING_PONG_BALANCE - dstPingFee); } function test_interchainExecute_state_synapseModule() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); assertEq(address(module).balance, dstVerificationFee); @@ -172,41 +164,41 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { } function test_interchainExecute_revert_notConfirmed_guardMarked() public { - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); executeTx(icOptions); } function test_interchainExecute_revert_confirmed_sameBlock() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); executeTx(icOptions); } function test_interchainExecute_revert_confirmed_sameBlock_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); executeTx(icOptions); } function test_interchainExecute_revert_confirmed_periodMinusOneSecond() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); executeTx(icOptions); } function test_interchainExecute_revert_confirmed_periodMinusOneSecond_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD); - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); executeTx(icOptions); } function test_interchainExecute_revert_alreadyExecuted() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); expectClientRevertTxAlreadyExecuted(srcDesc); @@ -214,56 +206,56 @@ contract LegacyPingPongDstIntegrationTest is LegacyPingPongIntegrationTest { } function test_isExecutable() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); - assertTrue(icClient.isExecutable(encodedSrcTx, new bytes32[](0))); + assertTrue(icClient.isExecutable(encodedSrcTx)); } function test_isExecutable_revert_notConfirmed() public { expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_notConfirmed_guardMarked() public { - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_sameBlock() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_sameBlock_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_periodMinusOneSecond() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD); expectClientRevertResponsesAmountBelowMin({actual: 0, required: 1}); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_confirmed_periodMinusOneSecond_guardMarked() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD); - markInvalidByGuard(srcBatch); - expectClientRevertBatchConflict(guard); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + markInvalidByGuard(srcFullEntry); + expectClientRevertEntryConflict(guard); + icClient.isExecutable(encodedSrcTx); } function test_isExecutable_revert_alreadyExecuted() public { - module.verifyRemoteBatch(moduleBatch, moduleSignatures); + module.verifyRemoteEntry(moduleEntry, moduleSignatures); skip(APP_OPTIMISTIC_PERIOD + 1); executeTx(icOptions); expectClientRevertTxAlreadyExecuted(srcDesc); - icClient.isExecutable(encodedSrcTx, new bytes32[](0)); + icClient.isExecutable(encodedSrcTx); } function localChainId() internal pure override returns (uint64) { diff --git a/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Src.t.sol b/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Src.t.sol index 8e7fff8190..d26a5b8525 100644 --- a/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Src.t.sol +++ b/packages/contracts-communication/test/integration/legacy/LegacyPingPong.Src.t.sol @@ -1,16 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {InterchainBatch} from "../../../contracts/libs/InterchainBatch.sol"; -import {InterchainEntry} from "../../../contracts/libs/InterchainEntry.sol"; import {InterchainTransaction, InterchainTxDescriptor} from "../../../contracts/libs/InterchainTransaction.sol"; import {LegacyPingPongIntegrationTest} from "./LegacyPingPong.t.sol"; // solhint-disable func-name-mixedcase contract LegacyPingPongSrcIntegrationTest is LegacyPingPongIntegrationTest { - InterchainBatch public batch; - InterchainEntry public entry; + FullEntry public fullEntry; InterchainTransaction public icTx; InterchainTxDescriptor public desc; @@ -21,9 +18,8 @@ contract LegacyPingPongSrcIntegrationTest is LegacyPingPongIntegrationTest { function setUp() public override { super.setUp(); icTx = getSrcTransaction(); - entry = getSrcInterchainEntry(); - desc = getInterchainTxDescriptor(entry); - batch = getInterchainBatch(entry); + fullEntry = getSrcFullEntry(); + desc = getInterchainTxDescriptor(fullEntry); pingFee = srcLegacyPingPong().getPingFee(DST_CHAIN_ID); verificationFee = icDB.getInterchainFee(DST_CHAIN_ID, toArray(address(module))); executionFee = executionService.getExecutionFee({ @@ -34,13 +30,13 @@ contract LegacyPingPongSrcIntegrationTest is LegacyPingPongIntegrationTest { } function test_startPingPong_events() public { - expectEventsPingSent(COUNTER, icTx, entry, verificationFee, executionFee); + expectEventsPingSent(COUNTER, icTx, fullEntry, verificationFee, executionFee); srcLegacyPingPong().startPingPong(DST_CHAIN_ID, COUNTER); } function test_startPingPong_state_db() public { srcLegacyPingPong().startPingPong(DST_CHAIN_ID, COUNTER); - checkDatabaseStateMsgSent(entry, SRC_INITIAL_DB_NONCE); + checkDatabaseStateMsgSent(fullEntry, SRC_INITIAL_DB_NONCE); } function test_startPingPong_state_execService() public { diff --git a/packages/contracts-communication/test/integration/legacy/LegacyPingPong.t.sol b/packages/contracts-communication/test/integration/legacy/LegacyPingPong.t.sol index 1e890887c9..183d81e904 100644 --- a/packages/contracts-communication/test/integration/legacy/LegacyPingPong.t.sol +++ b/packages/contracts-communication/test/integration/legacy/LegacyPingPong.t.sol @@ -97,13 +97,13 @@ abstract contract LegacyPingPongIntegrationTest is ICIntegrationTest { function expectEventsPingSent( uint256 counter, InterchainTransaction memory icTx, - InterchainEntry memory entry, + FullEntry memory fullEntry, uint256 verificationFee, uint256 executionFee ) internal { - expectEventsMessageSent(icTx, entry, verificationFee, executionFee); + expectEventsMessageSent(icTx, fullEntry, verificationFee, executionFee); expectPingPongEventPingSent(counter); } diff --git a/packages/contracts-communication/test/interfaces/IInterchainAppV1Harness.sol b/packages/contracts-communication/test/interfaces/IInterchainAppV1Harness.sol index 6ca15f144e..d94db4f9ca 100644 --- a/packages/contracts-communication/test/interfaces/IInterchainAppV1Harness.sol +++ b/packages/contracts-communication/test/interfaces/IInterchainAppV1Harness.sol @@ -7,7 +7,7 @@ import {OptionsV1} from "../../contracts/libs/Options.sol"; // solhint-disable func-name-mixedcase interface IInterchainAppV1Harness is IInterchainAppV1 { - event MessageReceived(uint64 srcChainId, bytes32 sender, uint64 dbNonce, uint64 entryIndex, bytes message); + event MessageReceived(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes message); function exposed__sendInterchainMessageEVM( uint64 dstChainId, diff --git a/packages/contracts-communication/test/legacy/MessageBus.Dst.t.sol b/packages/contracts-communication/test/legacy/MessageBus.Dst.t.sol index 56c9ba56cd..8b3783882f 100644 --- a/packages/contracts-communication/test/legacy/MessageBus.Dst.t.sol +++ b/packages/contracts-communication/test/legacy/MessageBus.Dst.t.sol @@ -7,7 +7,6 @@ import {MessageBusBaseTest, LegacyMessage, LegacyReceiverMock} from "./MessageBu // solhint-disable ordering contract MessageBusDstTest is MessageBusBaseTest { uint64 public constant MOCK_DB_NONCE = 1_234_567; - uint64 public constant MOCK_ENTRY_INDEX = 4321; LegacyMessage public legacyMsg; bytes public encodedLegacyMsg; @@ -25,7 +24,6 @@ contract MessageBusDstTest is MessageBusBaseTest { srcChainId: REMOTE_CHAIN_ID, sender: remoteMessageBusBytes32, dbNonce: MOCK_DB_NONCE, - entryIndex: MOCK_ENTRY_INDEX, message: encodedLegacyMsg }); } diff --git a/packages/contracts-communication/test/libs/InterchainBatchLib.t.sol b/packages/contracts-communication/test/libs/InterchainBatchLib.t.sol deleted file mode 100644 index 2652768cbd..0000000000 --- a/packages/contracts-communication/test/libs/InterchainBatchLib.t.sol +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import {InterchainBatch, InterchainBatchLibHarness, BatchKey} from "../harnesses/InterchainBatchLibHarness.sol"; - -import {Test} from "forge-std/Test.sol"; - -// solhint-disable func-name-mixedcase -// solhint-disable ordering -contract InterchainBatchLibTest is Test { - InterchainBatchLibHarness public libHarness; - - InterchainBatch public mockBatch = InterchainBatch({srcChainId: 1, dbNonce: 2, batchRoot: bytes32(uint256(3))}); - - function setUp() public { - libHarness = new InterchainBatchLibHarness(); - } - - function assertEq(InterchainBatch memory actual, InterchainBatch memory expected) public pure { - assertEq(actual.srcChainId, expected.srcChainId, "!srcChainId"); - assertEq(actual.dbNonce, expected.dbNonce, "!dbNonce"); - assertEq(actual.batchRoot, expected.batchRoot, "!batchRoot"); - } - - function test_constructLocalBatch() public { - vm.chainId(1); - uint64 dbNonce = 2; - bytes32 batchRoot = bytes32(uint256(3)); - InterchainBatch memory actual = libHarness.constructLocalBatch(dbNonce, batchRoot); - assertEq(actual, mockBatch); - } - - function test_constructLocalBatch(uint64 chainId, uint64 dbNonce, bytes32 batchRoot) public { - vm.chainId(chainId); - InterchainBatch memory expected = InterchainBatch(chainId, dbNonce, batchRoot); - InterchainBatch memory actual = libHarness.constructLocalBatch(dbNonce, batchRoot); - assertEq(actual, expected); - } - - function test_encodeBatch_roundTrip(InterchainBatch memory batch) public view { - bytes memory encoded = libHarness.encodeBatch(batch); - InterchainBatch memory decoded = libHarness.decodeBatch(encoded); - assertEq(decoded, batch); - } - - function test_encodeBatchFromMemory_roundTrip(InterchainBatch memory batch) public view { - bytes memory encoded = libHarness.encodeBatch(batch); - InterchainBatch memory decoded = libHarness.decodeBatchFromMemory(encoded); - assertEq(decoded, batch); - } - - function test_encodeBatchKey_roundTrip(uint64 srcChainId, uint64 dbNonce) public view { - BatchKey key = libHarness.encodeBatchKey(srcChainId, dbNonce); - (uint64 decodedSrcChainId, uint64 decodedDbNonce) = libHarness.decodeBatchKey(key); - assertEq(decodedSrcChainId, srcChainId); - assertEq(decodedDbNonce, dbNonce); - } -} diff --git a/packages/contracts-communication/test/libs/InterchainEntryLib.t.sol b/packages/contracts-communication/test/libs/InterchainEntryLib.t.sol index e30b5ae86a..3b5c714306 100644 --- a/packages/contracts-communication/test/libs/InterchainEntryLib.t.sol +++ b/packages/contracts-communication/test/libs/InterchainEntryLib.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {InterchainEntry, InterchainEntryLibHarness} from "../harnesses/InterchainEntryLibHarness.sol"; +import {InterchainEntry, InterchainEntryLibHarness, EntryKey} from "../harnesses/InterchainEntryLibHarness.sol"; import {Test} from "forge-std/Test.sol"; @@ -10,14 +10,6 @@ import {Test} from "forge-std/Test.sol"; contract InterchainEntryLibTest is Test { InterchainEntryLibHarness public libHarness; - InterchainEntry public mockEntry = InterchainEntry({ - srcChainId: 1, - dbNonce: 2, - entryIndex: 3, - srcWriter: bytes32(uint256(4)), - dataHash: bytes32(uint256(5)) - }); - function setUp() public { libHarness = new InterchainEntryLibHarness(); } @@ -25,61 +17,66 @@ contract InterchainEntryLibTest is Test { function assertEq(InterchainEntry memory actual, InterchainEntry memory expected) public pure { assertEq(actual.srcChainId, expected.srcChainId, "!srcChainId"); assertEq(actual.dbNonce, expected.dbNonce, "!dbNonce"); - assertEq(actual.entryIndex, expected.entryIndex, "!entryIndex"); - assertEq(actual.srcWriter, expected.srcWriter, "!srcWriter"); - assertEq(actual.dataHash, expected.dataHash, "!dataHash"); + assertEq(actual.entryValue, expected.entryValue, "!entryValue"); } function test_constructLocalEntry() public { vm.chainId(1); uint64 dbNonce = 2; - uint64 entryIndex = 3; - address srcWriter = address(4); - bytes32 dataHash = bytes32(uint256(5)); - InterchainEntry memory actual = libHarness.constructLocalEntry(dbNonce, entryIndex, srcWriter, dataHash); - assertEq(actual, mockEntry); + bytes32 entryValue = bytes32(uint256(3)); + InterchainEntry memory actual = libHarness.constructLocalEntry(dbNonce, entryValue); + InterchainEntry memory expected = InterchainEntry({srcChainId: 1, dbNonce: dbNonce, entryValue: entryValue}); + assertEq(actual, expected); } - function test_constructLocalEntry( - uint64 chainId, - uint64 dbNonce, - uint64 entryIndex, - address srcWriter, - bytes32 dataHash - ) - public - { + function test_constructLocalEntry(uint64 chainId, uint64 dbNonce, bytes32 entryValue) public { vm.chainId(chainId); - InterchainEntry memory expected = InterchainEntry({ - srcChainId: chainId, - dbNonce: dbNonce, - entryIndex: entryIndex, - srcWriter: bytes32(uint256(uint160(srcWriter))), - dataHash: dataHash - }); - InterchainEntry memory actual = libHarness.constructLocalEntry(dbNonce, entryIndex, srcWriter, dataHash); + InterchainEntry memory expected = + InterchainEntry({srcChainId: chainId, dbNonce: dbNonce, entryValue: entryValue}); + InterchainEntry memory actual = libHarness.constructLocalEntry(dbNonce, entryValue); assertEq(actual, expected); } - function test_entryValue() public view { - bytes32 expected = keccak256(abi.encode(4, 5)); - assertEq(libHarness.entryValue(mockEntry), expected); + function test_getEntryValue_address() public view { + address srcWriter = address(3); + bytes32 digest = bytes32(uint256(4)); + bytes32 expected = keccak256(abi.encode(srcWriter, digest)); + assertEq(libHarness.getEntryValue(srcWriter, digest), expected); + } + + function test_getEntryValue_address(address srcWriter, bytes32 digest) public view { + bytes32 expected = keccak256(abi.encode(srcWriter, digest)); + assertEq(libHarness.getEntryValue(srcWriter, digest), expected); + } + + function test_getEntryValue_bytes32() public view { + bytes32 srcWriter = bytes32(uint256(3)); + bytes32 digest = bytes32(uint256(4)); + bytes32 expected = keccak256(abi.encode(srcWriter, digest)); + assertEq(libHarness.getEntryValue(srcWriter, digest), expected); + } + + function test_getEntryValue_bytes32(bytes32 srcWriter, bytes32 digest) public view { + bytes32 expected = keccak256(abi.encode(srcWriter, digest)); + assertEq(libHarness.getEntryValue(srcWriter, digest), expected); } - function test_entryValue(InterchainEntry memory entry) public view { - bytes32 expected = keccak256(abi.encode(entry.srcWriter, entry.dataHash)); - assertEq(libHarness.entryValue(entry), expected); + function test_encodeEntry_roundTrip(InterchainEntry memory entry) public view { + bytes memory encoded = libHarness.encodeEntry(entry); + InterchainEntry memory decoded = libHarness.decodeEntry(encoded); + assertEq(decoded, entry); } - function test_getEntryValue() public view { - bytes32 srcWriter = bytes32(uint256(4)); - bytes32 dataHash = bytes32(uint256(5)); - bytes32 expected = keccak256(abi.encode(srcWriter, dataHash)); - assertEq(libHarness.getEntryValue(srcWriter, dataHash), expected); + function test_encodeEntryFromMemory_roundTrip(InterchainEntry memory entry) public view { + bytes memory encoded = libHarness.encodeEntry(entry); + InterchainEntry memory decoded = libHarness.decodeEntryFromMemory(encoded); + assertEq(decoded, entry); } - function test_getEntryValue(bytes32 srcWriter, bytes32 dataHash) public view { - bytes32 expected = keccak256(abi.encode(srcWriter, dataHash)); - assertEq(libHarness.getEntryValue(srcWriter, dataHash), expected); + function test_encodeEntryKey_roundTrip(uint64 srcChainId, uint64 dbNonce) public view { + EntryKey key = libHarness.encodeEntryKey(srcChainId, dbNonce); + (uint64 decodedSrcChainId, uint64 decodedDbNonce) = libHarness.decodeEntryKey(key); + assertEq(decodedSrcChainId, srcChainId); + assertEq(decodedDbNonce, dbNonce); } } diff --git a/packages/contracts-communication/test/libs/InterchainTransaction.t.sol b/packages/contracts-communication/test/libs/InterchainTransaction.t.sol index a619abc15d..3cce120b62 100644 --- a/packages/contracts-communication/test/libs/InterchainTransaction.t.sol +++ b/packages/contracts-communication/test/libs/InterchainTransaction.t.sol @@ -27,22 +27,19 @@ contract InterchainTransactionLibTest is Test { uint64 dstChainId, bytes32 dstReceiver, uint64 dbNonce, - uint64 entryIndex, bytes memory options, bytes memory message ) public { vm.chainId(srcChainId); - InterchainTransaction memory icTx = libHarness.constructLocalTransaction( - srcSender, dstChainId, dstReceiver, dbNonce, entryIndex, options, message - ); + InterchainTransaction memory icTx = + libHarness.constructLocalTransaction(srcSender, dstChainId, dstReceiver, dbNonce, options, message); assertEq(icTx.srcChainId, srcChainId, "!srcChainId"); assertEq(icTx.srcSender, bytes32(uint256(uint160(srcSender))), "!srcSender"); assertEq(icTx.dstChainId, dstChainId, "!dstChainId"); assertEq(icTx.dstReceiver, dstReceiver, "!dstReceiver"); assertEq(icTx.dbNonce, dbNonce, "!dbNonce"); - assertEq(icTx.entryIndex, entryIndex, "!entryIndex"); assertEq(icTx.options, options, "!options"); assertEq(icTx.message, message, "!message"); } @@ -55,7 +52,6 @@ contract InterchainTransactionLibTest is Test { assertEq(decoded.dstChainId, icTx.dstChainId, "!dstChainId"); assertEq(decoded.dstReceiver, icTx.dstReceiver, "!dstReceiver"); assertEq(decoded.dbNonce, icTx.dbNonce, "!dbNonce"); - assertEq(decoded.entryIndex, icTx.entryIndex, "!entryIndex"); assertEq(decoded.options, icTx.options, "!options"); assertEq(decoded.message, icTx.message, "!message"); } @@ -73,21 +69,11 @@ contract InterchainTransactionLibTest is Test { test_payloadSize(icTx); } - function test_encodeTxHeader_roundTrip( - uint64 srcChainId, - uint64 dstChainId, - uint64 dbNonce, - uint64 entryIndex - ) - public - view - { - ICTxHeader header = libHarness.encodeTxHeader(srcChainId, dstChainId, dbNonce, entryIndex); - (uint64 decodedSrcChainId, uint64 decodedDstChainId, uint64 decodedDbNonce, uint64 decodedEntryIndex) = - libHarness.decodeTxHeader(header); + function test_encodeTxHeader_roundTrip(uint64 srcChainId, uint64 dstChainId, uint64 dbNonce) public view { + ICTxHeader header = libHarness.encodeTxHeader(srcChainId, dstChainId, dbNonce); + (uint64 decodedSrcChainId, uint64 decodedDstChainId, uint64 decodedDbNonce) = libHarness.decodeTxHeader(header); assertEq(decodedSrcChainId, srcChainId, "!srcChainId"); assertEq(decodedDstChainId, dstChainId, "!dstChainId"); assertEq(decodedDbNonce, dbNonce, "!dbNonce"); - assertEq(decodedEntryIndex, entryIndex, "!entryIndex"); } } diff --git a/packages/contracts-communication/test/libs/ModuleBatchLib.t.sol b/packages/contracts-communication/test/libs/ModuleBatchLib.t.sol deleted file mode 100644 index 376760fa24..0000000000 --- a/packages/contracts-communication/test/libs/ModuleBatchLib.t.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.20; - -import {InterchainBatch} from "../../contracts/libs/InterchainBatch.sol"; - -import {ModuleBatchLibHarness} from "../harnesses/ModuleBatchLibHarness.sol"; - -import {Test} from "forge-std/Test.sol"; - -// solhint-disable func-name-mixedcase -// solhint-disable ordering -contract ModuleBatchLibTest is Test { - ModuleBatchLibHarness public libHarness; - - function setUp() public { - libHarness = new ModuleBatchLibHarness(); - } - - function assertEq(InterchainBatch memory actual, InterchainBatch memory expected) public pure { - assertEq(actual.srcChainId, expected.srcChainId, "!srcChainId"); - assertEq(actual.dbNonce, expected.dbNonce, "!dbNonce"); - assertEq(actual.batchRoot, expected.batchRoot, "!batchRoot"); - } - - function test_encodeVersionedModuleBatch_roundTrip( - bytes memory versionedBatch, - bytes memory moduleData - ) - public - view - { - bytes memory encoded = libHarness.encodeVersionedModuleBatch(versionedBatch, moduleData); - (bytes memory decodedVersionedBatch, bytes memory decodedModuleData) = - libHarness.decodeVersionedModuleBatch(encoded); - assertEq(decodedVersionedBatch, versionedBatch); - assertEq(decodedModuleData, moduleData); - } -} diff --git a/packages/contracts-communication/test/libs/ModuleEntryLib.t.sol b/packages/contracts-communication/test/libs/ModuleEntryLib.t.sol new file mode 100644 index 0000000000..ca626c5665 --- /dev/null +++ b/packages/contracts-communication/test/libs/ModuleEntryLib.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {InterchainEntry} from "../../contracts/libs/InterchainEntry.sol"; + +import {ModuleEntryLibHarness} from "../harnesses/ModuleEntryLibHarness.sol"; + +import {Test} from "forge-std/Test.sol"; + +// solhint-disable func-name-mixedcase +// solhint-disable ordering +contract ModuleEntryLibTest is Test { + ModuleEntryLibHarness public libHarness; + + function setUp() public { + libHarness = new ModuleEntryLibHarness(); + } + + function assertEq(InterchainEntry memory actual, InterchainEntry memory expected) public pure { + assertEq(actual.srcChainId, expected.srcChainId, "!srcChainId"); + assertEq(actual.dbNonce, expected.dbNonce, "!dbNonce"); + assertEq(actual.entryValue, expected.entryValue, "!entryValue"); + } + + function test_encodeVersionedModuleEntry_roundTrip( + bytes memory versionedEntry, + bytes memory moduleData + ) + public + view + { + bytes memory encoded = libHarness.encodeVersionedModuleEntry(versionedEntry, moduleData); + (bytes memory decodedVersionedEntry, bytes memory decodedModuleData) = + libHarness.decodeVersionedModuleEntry(encoded); + assertEq(decodedVersionedEntry, versionedEntry); + assertEq(decodedModuleData, moduleData); + } +} diff --git a/packages/contracts-communication/test/mocks/InterchainAppMock.sol b/packages/contracts-communication/test/mocks/InterchainAppMock.sol index 1bd696a03b..c0fd16d1c9 100644 --- a/packages/contracts-communication/test/mocks/InterchainAppMock.sol +++ b/packages/contracts-communication/test/mocks/InterchainAppMock.sol @@ -5,16 +5,7 @@ import {IInterchainApp} from "../../contracts/interfaces/IInterchainApp.sol"; // solhint-disable no-empty-blocks contract InterchainAppMock is IInterchainApp { - function appReceive( - uint64 srcChainId, - bytes32 sender, - uint64 dbNonce, - uint64 entryIndex, - bytes calldata message - ) - external - payable - {} + function appReceive(uint64 srcChainId, bytes32 sender, uint64 dbNonce, bytes calldata message) external payable {} function getReceivingConfig() external view returns (bytes memory appConfig, address[] memory modules) {} } diff --git a/packages/contracts-communication/test/mocks/InterchainClientV1Mock.sol b/packages/contracts-communication/test/mocks/InterchainClientV1Mock.sol index 7a1c1d64eb..4fff09850c 100644 --- a/packages/contracts-communication/test/mocks/InterchainClientV1Mock.sol +++ b/packages/contracts-communication/test/mocks/InterchainClientV1Mock.sol @@ -39,23 +39,13 @@ contract InterchainClientV1Mock is IInterchainClientV1 { returns (InterchainTxDescriptor memory desc) {} - function interchainExecute( - uint256 gasLimit, - bytes calldata transaction, - bytes32[] calldata proof - ) - external - payable - {} + function interchainExecute(uint256 gasLimit, bytes calldata transaction) external payable {} - function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce, uint64 entryIndex) {} + function writeExecutionProof(bytes32 transactionId) external returns (uint64 dbNonce) {} - function isExecutable(bytes calldata transaction, bytes32[] calldata proof) external view returns (bool) {} + function isExecutable(bytes calldata transaction) external view returns (bool) {} - function getTxReadinessV1( - InterchainTransaction memory icTx, - bytes32[] calldata proof - ) + function getTxReadinessV1(InterchainTransaction memory icTx) external view returns (TxReadiness status, bytes32 firstArg, bytes32 secondArg) diff --git a/packages/contracts-communication/test/mocks/InterchainDBMock.sol b/packages/contracts-communication/test/mocks/InterchainDBMock.sol index 36bcfa4814..dc22641f0d 100644 --- a/packages/contracts-communication/test/mocks/InterchainDBMock.sol +++ b/packages/contracts-communication/test/mocks/InterchainDBMock.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {IInterchainDB, InterchainBatch, InterchainEntry} from "../../contracts/interfaces/IInterchainDB.sol"; +import {IInterchainDB, InterchainEntry} from "../../contracts/interfaces/IInterchainDB.sol"; // solhint-disable no-empty-blocks contract InterchainDBMock is IInterchainDB { uint16 public constant DB_VERSION = 1; - function writeEntry(bytes32 dataHash) external returns (uint64 writerNonce, uint64 entryIndex) {} + function writeEntry(bytes32 dataHash) external returns (uint64 writerNonce) {} - function requestBatchVerification( + function requestEntryVerification( uint64 dstChainId, uint64 dbNonce, address[] memory srcModules @@ -18,54 +18,34 @@ contract InterchainDBMock is IInterchainDB { payable {} - function writeEntryWithVerification( + function writeEntryRequestVerification( uint64 dstChainId, - bytes32 dataHash, + bytes32 digest, address[] memory srcModules ) external payable - returns (uint64 writerNonce, uint64 entryIndex) + returns (uint64 dbNonce) {} - function verifyRemoteBatch(bytes calldata versionedBatch) external {} + function verifyRemoteEntry(bytes calldata encodedEntry) external {} function getInterchainFee(uint64 dstChainId, address[] memory srcModules) external view returns (uint256) {} - function getBatchLeafs(uint64 dbNonce) external view returns (bytes32[] memory) {} + function getEncodedEntry(uint64 dbNonce) external view returns (bytes memory) {} - function getBatchLeafsPaginated( - uint64 dbNonce, - uint64 start, - uint64 end - ) - external - view - returns (bytes32[] memory) - {} - - function getBatchSize(uint64 dbNonce) external view returns (uint64) {} + function getEntry(uint64 dbNonce) external view returns (InterchainEntry memory) {} - function getBatch(uint64 dbNonce) external view returns (InterchainBatch memory) {} - - function getVersionedBatch(uint64 dbNonce) external view returns (bytes memory versionedBatch) {} - - function getEntryValue(uint64 dbNonce, uint64 entryIndex) external view returns (bytes32) {} - - function getEntryProof(uint64 dbNonce, uint64 entryIndex) external view returns (bytes32[] memory proof) {} + function getEntryValue(uint64 dbNonce) external view returns (bytes32) {} function getDBNonce() external view returns (uint64) {} - function getNextEntryIndex() external view returns (uint64 dbNonce, uint64 entryIndex) {} - - function checkBatchVerification( + function checkEntryVerification( address dstModule, - InterchainBatch memory batch + InterchainEntry memory entry ) external view returns (uint256 moduleVerifiedAt) {} - - function getBatchRoot(InterchainEntry memory entry, bytes32[] memory proof) external pure returns (bytes32) {} } diff --git a/packages/contracts-communication/test/mocks/InterchainModuleMock.sol b/packages/contracts-communication/test/mocks/InterchainModuleMock.sol index 13985589a0..15cba2667e 100644 --- a/packages/contracts-communication/test/mocks/InterchainModuleMock.sol +++ b/packages/contracts-communication/test/mocks/InterchainModuleMock.sol @@ -3,34 +3,27 @@ pragma solidity 0.8.20; import {IInterchainModule} from "../../contracts/interfaces/IInterchainModule.sol"; import {IInterchainDB} from "../../contracts/interfaces/IInterchainDB.sol"; -import {InterchainBatch, InterchainBatchLib} from "../../contracts/libs/InterchainBatch.sol"; +import {InterchainEntry, InterchainEntryLib} from "../../contracts/libs/InterchainEntry.sol"; import {VersionedPayloadLib} from "../../contracts/libs/VersionedPayload.sol"; // solhint-disable ordering // solhint-disable no-empty-blocks contract InterchainModuleMock is IInterchainModule { - function requestBatchVerification( - uint64 dstChainId, - uint64 batchNonce, - bytes calldata versionedBatch - ) - external - payable - {} + function requestEntryVerification(uint64 dstChainId, bytes calldata versionedEntry) external payable {} - function getModuleFee(uint64 dstChainId, uint64 dbNonce) external view returns (uint256) {} + function getModuleFee(uint64 dstChainId) external view returns (uint256) {} - function mockVerifyRemoteBatch(address interchainDB, bytes calldata versionedBatch) external { - IInterchainDB(interchainDB).verifyRemoteBatch(versionedBatch); + function mockVerifyRemoteEntry(address interchainDB, bytes calldata versionedEntry) external { + IInterchainDB(interchainDB).verifyRemoteEntry(versionedEntry); } - // @notice This function is exposed for simplicity of Go tests. It uses the version signalled - // by the InterchainDB contract to encode the versioned batch. - function mockVerifyRemoteBatchStruct(address interchainDB, InterchainBatch memory batch) external { - bytes memory versionedBatch = VersionedPayloadLib.encodeVersionedPayload({ + /// @notice This function is exposed for simplicity of Go tests. It uses the version signalled + /// by the InterchainDB contract to encode the versioned entry. + function mockVerifyRemoteEntryStruct(address interchainDB, InterchainEntry memory entry) external { + bytes memory versionedEntry = VersionedPayloadLib.encodeVersionedPayload({ version: IInterchainDB(interchainDB).DB_VERSION(), - payload: InterchainBatchLib.encodeBatch(batch) + payload: InterchainEntryLib.encodeEntry(entry) }); - IInterchainDB(interchainDB).verifyRemoteBatch(versionedBatch); + IInterchainDB(interchainDB).verifyRemoteEntry(versionedEntry); } } diff --git a/packages/contracts-communication/test/modules/SynapseModule.Destination.t.sol b/packages/contracts-communication/test/modules/SynapseModule.Destination.t.sol index 5f23955235..5562e6965d 100644 --- a/packages/contracts-communication/test/modules/SynapseModule.Destination.t.sol +++ b/packages/contracts-communication/test/modules/SynapseModule.Destination.t.sol @@ -4,11 +4,11 @@ pragma solidity 0.8.20; import {InterchainModuleEvents} from "../../contracts/events/InterchainModuleEvents.sol"; import {SynapseModuleEvents} from "../../contracts/events/SynapseModuleEvents.sol"; import {IInterchainModule} from "../../contracts/interfaces/IInterchainModule.sol"; -import {InterchainBatch} from "../../contracts/libs/InterchainBatch.sol"; +import {InterchainEntry} from "../../contracts/libs/InterchainEntry.sol"; import {ThresholdECDSALib} from "../../contracts/libs/ThresholdECDSA.sol"; import {SynapseModule} from "../../contracts/modules/SynapseModule.sol"; -import {InterchainBatchLibHarness} from "../harnesses/InterchainBatchLibHarness.sol"; +import {InterchainEntryLibHarness} from "../harnesses/InterchainEntryLibHarness.sol"; import {VersionedPayloadLibHarness} from "../harnesses/VersionedPayloadLibHarness.sol"; import {SynapseGasOracleMock} from "../mocks/SynapseGasOracleMock.sol"; @@ -19,7 +19,7 @@ import {Test} from "forge-std/Test.sol"; // solhint-disable func-name-mixedcase // solhint-disable ordering contract SynapseModuleDestinationTest is Test, InterchainModuleEvents, SynapseModuleEvents { - InterchainBatchLibHarness public batchLibHarness; + InterchainEntryLibHarness public entryLibHarness; VersionedPayloadLibHarness public payloadLibHarness; SynapseModule public module; @@ -34,9 +34,9 @@ contract SynapseModuleDestinationTest is Test, InterchainModuleEvents, SynapseMo uint16 public constant MOCK_DB_VERSION = 42; - InterchainBatch public mockBatch = - InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: 2, batchRoot: bytes32(uint256(3))}); - bytes public mockVersionedBatch; + InterchainEntry public mockEntry = + InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: 2, entryValue: bytes32(uint256(3))}); + bytes public mockVersionedEntry; bytes public mockModuleData = ""; uint256 public constant PK_0 = 1000; @@ -56,9 +56,9 @@ contract SynapseModuleDestinationTest is Test, InterchainModuleEvents, SynapseMo interchainDB = new InterchainDBMock(); module = new SynapseModule(address(interchainDB), owner); gasOracle = new SynapseGasOracleMock(); - batchLibHarness = new InterchainBatchLibHarness(); + entryLibHarness = new InterchainEntryLibHarness(); payloadLibHarness = new VersionedPayloadLibHarness(); - mockVersionedBatch = getVersionedBatch(mockBatch); + mockVersionedEntry = getVersionedEntry(mockEntry); vm.startPrank(owner); module.setGasOracle(address(gasOracle)); module.setFeeRecipient(feeRecipient); @@ -95,25 +95,25 @@ contract SynapseModuleDestinationTest is Test, InterchainModuleEvents, SynapseMo arr[2] = c; } - function encodeAndHashBatch(InterchainBatch memory batch) + function encodeAndHashEntry(InterchainEntry memory entry) internal view - returns (bytes memory encodedBatch, bytes32 ethSignedHash) + returns (bytes memory encodedEntry, bytes32 ethSignedHash) { - bytes memory versionedBatch = getVersionedBatch(batch); - encodedBatch = abi.encode(versionedBatch, mockModuleData); - ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(encodedBatch))); + bytes memory versionedEntry = getVersionedEntry(entry); + encodedEntry = abi.encode(versionedEntry, mockModuleData); + ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(encodedEntry))); } - function signBatch( - InterchainBatch memory batch, + function signEntry( + InterchainEntry memory entry, uint256[] memory pks ) internal view returns (bytes memory signatures) { - (, bytes32 ethSignedHash) = encodeAndHashBatch(batch); + (, bytes32 ethSignedHash) = encodeAndHashEntry(entry); signatures = ""; for (uint256 i = 0; i < pks.length; ++i) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(pks[i], ethSignedHash); @@ -121,28 +121,28 @@ contract SynapseModuleDestinationTest is Test, InterchainModuleEvents, SynapseMo } } - function getVersionedBatch(InterchainBatch memory batch) internal view returns (bytes memory versionedBatch) { - versionedBatch = payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, batchLibHarness.encodeBatch(batch)); + function getVersionedEntry(InterchainEntry memory entry) internal view returns (bytes memory versionedEntry) { + versionedEntry = payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, entryLibHarness.encodeEntry(entry)); } - function verifyRemoteBatch(bytes memory versionedBatch, bytes memory signatures) internal { - module.verifyRemoteBatch(abi.encode(versionedBatch, mockModuleData), signatures); + function verifyRemoteEntry(bytes memory versionedEntry, bytes memory signatures) internal { + module.verifyRemoteEntry(abi.encode(versionedEntry, mockModuleData), signatures); } // ═══════════════════════════════════════════════ TEST HELPERS ════════════════════════════════════════════════════ - function expectCallVerifyRemoteBatch(InterchainBatch memory batch) internal { - bytes memory versionedBatch = - payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, batchLibHarness.encodeBatch(batch)); - bytes memory expectedCallData = abi.encodeCall(IInterchainDB.verifyRemoteBatch, (versionedBatch)); + function expectCallVerifyRemoteEntry(InterchainEntry memory entry) internal { + bytes memory versionedEntry = + payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, entryLibHarness.encodeEntry(entry)); + bytes memory expectedCallData = abi.encodeCall(IInterchainDB.verifyRemoteEntry, (versionedEntry)); // expectCall(address callee, bytes calldata data, uint64 count) vm.expectCall(address(interchainDB), expectedCallData, 1); } - function expectEventBatchVerified(InterchainBatch memory batch) internal { - (bytes memory encodedBatch, bytes32 ethSignedHash) = encodeAndHashBatch(batch); + function expectEventEntryVerified(InterchainEntry memory entry) internal { + (bytes memory encodedEntry, bytes32 ethSignedHash) = encodeAndHashEntry(entry); vm.expectEmit(address(module)); - emit BatchVerified(batch.srcChainId, encodedBatch, ethSignedHash); + emit EntryVerified(entry.srcChainId, encodedEntry, ethSignedHash); } function expectRevertSignaturesPayloadLengthInvalid(uint256 length) internal { @@ -167,186 +167,186 @@ contract SynapseModuleDestinationTest is Test, InterchainModuleEvents, SynapseMo vm.expectRevert(abi.encodeWithSelector(IInterchainModule.InterchainModule__ChainIdNotRemote.selector, chainId)); } - // ════════════════════════════════════════════ TESTS: VERIFY BATCH ════════════════════════════════════════════════ + // ════════════════════════════════════════════ TESTS: VERIFY ENTRY ════════════════════════════════════════════════ // Signers order sorted by their address: // SIGNER_1, SIGNER_4, SIGNER_0, SIGNER_3, SIGNER_2 // Should be verified if the enough valid signatures, which match the signers ascending order - function test_verifyRemoteBatch_zeroSignatures_revertSignaturesAmountBelowThreshold() public { + function test_verifyRemoteEntry_zeroSignatures_revertSignaturesAmountBelowThreshold() public { expectRevertSignaturesAmountBelowThreshold(0, 2); - verifyRemoteBatch(mockVersionedBatch, ""); + verifyRemoteEntry(mockVersionedEntry, ""); } - function test_verifyRemoteBatch_oneSignature_valid_revertSignaturesAmountBelowThreshold() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_0)); + function test_verifyRemoteEntry_oneSignature_valid_revertSignaturesAmountBelowThreshold() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_0)); expectRevertSignaturesAmountBelowThreshold(1, 2); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_oneSignature_invalid_revertSignaturesAmountBelowThreshold() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_3)); + function test_verifyRemoteEntry_oneSignature_invalid_revertSignaturesAmountBelowThreshold() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_3)); expectRevertSignaturesAmountBelowThreshold(0, 2); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_valid_sorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_0)); - expectCallVerifyRemoteBatch(mockBatch); - expectEventBatchVerified(mockBatch); - verifyRemoteBatch(mockVersionedBatch, signatures); + function test_verifyRemoteEntry_twoSignatures_valid_sorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_0)); + expectCallVerifyRemoteEntry(mockEntry); + expectEventEntryVerified(mockEntry); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_valid_duplicate_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_1)); + function test_verifyRemoteEntry_twoSignatures_valid_duplicate_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_1)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_valid_unsorted_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_0, PK_1)); + function test_verifyRemoteEntry_twoSignatures_valid_unsorted_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_0, PK_1)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_invalidOne_sorted_revertSignaturesAmountBelowThreshold() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_3)); + function test_verifyRemoteEntry_twoSignatures_invalidOne_sorted_revertSignaturesAmountBelowThreshold() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_3)); expectRevertSignaturesAmountBelowThreshold(1, 2); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_invalidOne_unsorted_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_3, PK_1)); + function test_verifyRemoteEntry_twoSignatures_invalidOne_unsorted_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_3, PK_1)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_invalidTwo_sorted_revertSignaturesAmountBelowThreshold() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_3)); + function test_verifyRemoteEntry_twoSignatures_invalidTwo_sorted_revertSignaturesAmountBelowThreshold() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_3)); expectRevertSignaturesAmountBelowThreshold(0, 2); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_twoSignatures_invalidTwo_duplicate_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_4)); + function test_verifyRemoteEntry_twoSignatures_invalidTwo_duplicate_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_4)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_valid_sorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_0, PK_2)); - expectCallVerifyRemoteBatch(mockBatch); - expectEventBatchVerified(mockBatch); - verifyRemoteBatch(mockVersionedBatch, signatures); + function test_verifyRemoteEntry_threeSignatures_valid_sorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_0, PK_2)); + expectCallVerifyRemoteEntry(mockEntry); + expectEventEntryVerified(mockEntry); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_valid_duplicate_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_0, PK_0)); + function test_verifyRemoteEntry_threeSignatures_valid_duplicate_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_0, PK_0)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_valid_unsorted_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_0, PK_2, PK_1)); + function test_verifyRemoteEntry_threeSignatures_valid_unsorted_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_0, PK_2, PK_1)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidOne_sorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_0, PK_2)); - expectCallVerifyRemoteBatch(mockBatch); - expectEventBatchVerified(mockBatch); - verifyRemoteBatch(mockVersionedBatch, signatures); + function test_verifyRemoteEntry_threeSignatures_invalidOne_sorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_0, PK_2)); + expectCallVerifyRemoteEntry(mockEntry); + expectEventEntryVerified(mockEntry); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidOne_duplicate_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_0, PK_0)); + function test_verifyRemoteEntry_threeSignatures_invalidOne_duplicate_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_0, PK_0)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidOne_unsorted_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_0, PK_4, PK_1)); + function test_verifyRemoteEntry_threeSignatures_invalidOne_unsorted_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_0, PK_4, PK_1)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidTwo_sorted_revertSignaturesAmountBelowThreshold() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_3, PK_2)); + function test_verifyRemoteEntry_threeSignatures_invalidTwo_sorted_revertSignaturesAmountBelowThreshold() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_3, PK_2)); expectRevertSignaturesAmountBelowThreshold(1, 2); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidTwo_duplicate_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_0, PK_3, PK_3)); + function test_verifyRemoteEntry_threeSignatures_invalidTwo_duplicate_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_0, PK_3, PK_3)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidTwo_unsorted_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_3, PK_0, PK_4)); + function test_verifyRemoteEntry_threeSignatures_invalidTwo_unsorted_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_3, PK_0, PK_4)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidThree_sorted_revertSignaturesAmountBelowThreshold() public { + function test_verifyRemoteEntry_threeSignatures_invalidThree_sorted_revertSignaturesAmountBelowThreshold() public { vm.prank(owner); module.removeVerifier(SIGNER_0); - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_0, PK_3)); + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_0, PK_3)); expectRevertSignaturesAmountBelowThreshold(0, 2); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidThree_duplicate_revertNotSorted() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_4, PK_3, PK_3)); + function test_verifyRemoteEntry_threeSignatures_invalidThree_duplicate_revertNotSorted() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_4, PK_3, PK_3)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_threeSignatures_invalidThree_unsorted_revertNotSorted() public { + function test_verifyRemoteEntry_threeSignatures_invalidThree_unsorted_revertNotSorted() public { vm.prank(owner); module.removeVerifier(SIGNER_0); - bytes memory signatures = signBatch(mockBatch, toArray(PK_3, PK_4, PK_0)); + bytes memory signatures = signEntry(mockEntry, toArray(PK_3, PK_4, PK_0)); expectRevertRecoveredSignersNotSorted(); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_revertChainIdNotRemote() public { - InterchainBatch memory batch = mockBatch; - batch.srcChainId = DST_CHAIN_ID; - bytes memory versionedBatch = getVersionedBatch(batch); - bytes memory signatures = signBatch(batch, toArray(PK_1, PK_0)); + function test_verifyRemoteEntry_revertChainIdNotRemote() public { + InterchainEntry memory entry = mockEntry; + entry.srcChainId = DST_CHAIN_ID; + bytes memory versionedEntry = getVersionedEntry(entry); + bytes memory signatures = signEntry(entry, toArray(PK_1, PK_0)); expectRevertChainIdNotRemote(DST_CHAIN_ID); - verifyRemoteBatch(versionedBatch, signatures); + verifyRemoteEntry(versionedEntry, signatures); } - function test_verifyRemoteBatch_revertThresholdZero() public { + function test_verifyRemoteEntry_revertThresholdZero() public { // Deploy a module without setting up the threshold module = new SynapseModule(address(interchainDB), owner); vm.startPrank(owner); module.addVerifier(SIGNER_0); module.addVerifier(SIGNER_1); vm.stopPrank(); - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_0)); + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_0)); vm.expectRevert(ThresholdECDSALib.ThresholdECDSA__ThresholdZero.selector); - verifyRemoteBatch(mockVersionedBatch, signatures); + verifyRemoteEntry(mockVersionedEntry, signatures); } - function test_verifyRemoteBatch_revertSignaturesPayloadLengthInvalidTooShort() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_0)); + function test_verifyRemoteEntry_revertSignaturesPayloadLengthInvalidTooShort() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_0)); bytes memory signaturesShort = new bytes(signatures.length - 1); for (uint256 i = 0; i < signaturesShort.length; ++i) { signaturesShort[i] = signatures[i]; } expectRevertSignaturesPayloadLengthInvalid(signaturesShort.length); - verifyRemoteBatch(mockVersionedBatch, signaturesShort); + verifyRemoteEntry(mockVersionedEntry, signaturesShort); } - function test_verifyRemoteBatch_revertSignaturesPayloadLengthInvalidTooLong() public { - bytes memory signatures = signBatch(mockBatch, toArray(PK_1, PK_0)); + function test_verifyRemoteEntry_revertSignaturesPayloadLengthInvalidTooLong() public { + bytes memory signatures = signEntry(mockEntry, toArray(PK_1, PK_0)); bytes memory signaturesLong = bytes.concat(signatures, bytes1(0x2A)); expectRevertSignaturesPayloadLengthInvalid(signaturesLong.length); - verifyRemoteBatch(mockVersionedBatch, signaturesLong); + verifyRemoteEntry(mockVersionedEntry, signaturesLong); } } diff --git a/packages/contracts-communication/test/modules/SynapseModule.Source.t.sol b/packages/contracts-communication/test/modules/SynapseModule.Source.t.sol index 2a039f76c1..dd431f4585 100644 --- a/packages/contracts-communication/test/modules/SynapseModule.Source.t.sol +++ b/packages/contracts-communication/test/modules/SynapseModule.Source.t.sol @@ -6,10 +6,10 @@ import {InterchainModuleEvents} from "../../contracts/events/InterchainModuleEve import {SynapseModuleEvents} from "../../contracts/events/SynapseModuleEvents.sol"; import {IClaimableFees} from "../../contracts/interfaces/IClaimableFees.sol"; import {IInterchainModule} from "../../contracts/interfaces/IInterchainModule.sol"; -import {InterchainBatch} from "../../contracts/libs/InterchainBatch.sol"; +import {InterchainEntry} from "../../contracts/libs/InterchainEntry.sol"; import {SynapseModule} from "../../contracts/modules/SynapseModule.sol"; -import {InterchainBatchLibHarness} from "../harnesses/InterchainBatchLibHarness.sol"; +import {InterchainEntryLibHarness} from "../harnesses/InterchainEntryLibHarness.sol"; import {VersionedPayloadLibHarness} from "../harnesses/VersionedPayloadLibHarness.sol"; import {SynapseGasOracleMock} from "../mocks/SynapseGasOracleMock.sol"; @@ -18,7 +18,7 @@ import {Test} from "forge-std/Test.sol"; // solhint-disable func-name-mixedcase // solhint-disable ordering contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleEvents, SynapseModuleEvents { - InterchainBatchLibHarness public batchLibHarness; + InterchainEntryLibHarness public entryLibHarness; VersionedPayloadLibHarness public payloadLibHarness; SynapseModule public module; @@ -38,15 +38,15 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE uint256 public constant FEE = 100; - InterchainBatch public mockBatch = - InterchainBatch({srcChainId: SRC_CHAIN_ID, dbNonce: 2, batchRoot: bytes32(uint256(3))}); + InterchainEntry public mockEntry = + InterchainEntry({srcChainId: SRC_CHAIN_ID, dbNonce: 2, entryValue: bytes32(uint256(3))}); bytes public mockModuleData = ""; function setUp() public { vm.chainId(SRC_CHAIN_ID); module = new SynapseModule(interchainDB, owner); gasOracle = new SynapseGasOracleMock(); - batchLibHarness = new InterchainBatchLibHarness(); + entryLibHarness = new InterchainEntryLibHarness(); payloadLibHarness = new VersionedPayloadLibHarness(); vm.startPrank(owner); module.setGasOracle(address(gasOracle)); @@ -63,25 +63,25 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE ); } - function getVersionedBatch(InterchainBatch memory batch) internal view returns (bytes memory) { - return payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, batchLibHarness.encodeBatch(batch)); + function getVersionedEntry(InterchainEntry memory entry) internal view returns (bytes memory) { + return payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, entryLibHarness.encodeEntry(entry)); } - function requestBatchVerification(uint256 msgValue, uint64 batchNonce, bytes memory versionedBatch) internal { + function requestEntryVerification(uint256 msgValue, bytes memory versionedEntry) internal { deal(interchainDB, msgValue); vm.prank(interchainDB); - module.requestBatchVerification{value: msgValue}(DST_CHAIN_ID, batchNonce, versionedBatch); + module.requestEntryVerification{value: msgValue}(DST_CHAIN_ID, versionedEntry); } - function encodeAndHashBatch(InterchainBatch memory batch) + function encodeAndHashEntry(InterchainEntry memory entry) internal view - returns (bytes memory encodedBatch, bytes32 ethSignedHash) + returns (bytes memory encodedEntry, bytes32 ethSignedHash) { - bytes memory versionedBatch = - payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, batchLibHarness.encodeBatch(batch)); - encodedBatch = abi.encode(versionedBatch, mockModuleData); - ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(encodedBatch))); + bytes memory versionedEntry = + payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, entryLibHarness.encodeEntry(entry)); + encodedEntry = abi.encode(versionedEntry, mockModuleData); + ethSignedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", keccak256(encodedEntry))); } function test_setup() public view { @@ -93,41 +93,41 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE } function test_requestVerification_emitsEvent() public { - (bytes memory encodedBatch, bytes32 ethSignedHash) = encodeAndHashBatch(mockBatch); - bytes memory versionedBatch = getVersionedBatch(mockBatch); + (bytes memory encodedEntry, bytes32 ethSignedHash) = encodeAndHashEntry(mockEntry); + bytes memory versionedEntry = getVersionedEntry(mockEntry); vm.expectEmit(address(module)); - emit BatchVerificationRequested(DST_CHAIN_ID, encodedBatch, ethSignedHash); - requestBatchVerification(FEE, mockBatch.dbNonce, versionedBatch); + emit EntryVerificationRequested(DST_CHAIN_ID, encodedEntry, ethSignedHash); + requestEntryVerification(FEE, versionedEntry); } function test_requestVerification_accumulatesFee() public { deal(address(module), 5 ether); - bytes memory versionedBatch = getVersionedBatch(mockBatch); - requestBatchVerification(FEE, mockBatch.dbNonce, versionedBatch); + bytes memory versionedEntry = getVersionedEntry(mockEntry); + requestEntryVerification(FEE, versionedEntry); assertEq(address(module).balance, 5 ether + FEE); } function test_requestVerification_feeAboveRequired_emitsEvent() public { - (bytes memory encodedBatch, bytes32 ethSignedHash) = encodeAndHashBatch(mockBatch); - bytes memory versionedBatch = getVersionedBatch(mockBatch); + (bytes memory encodedEntry, bytes32 ethSignedHash) = encodeAndHashEntry(mockEntry); + bytes memory versionedEntry = getVersionedEntry(mockEntry); vm.expectEmit(address(module)); - emit BatchVerificationRequested(DST_CHAIN_ID, encodedBatch, ethSignedHash); - requestBatchVerification(FEE + 1, mockBatch.dbNonce, versionedBatch); + emit EntryVerificationRequested(DST_CHAIN_ID, encodedEntry, ethSignedHash); + requestEntryVerification(FEE + 1, versionedEntry); } function test_requestVerification_feeAboveRequired_accumulatesFee() public { deal(address(module), 5 ether); - bytes memory versionedBatch = getVersionedBatch(mockBatch); - requestBatchVerification(FEE + 1, mockBatch.dbNonce, versionedBatch); + bytes memory versionedEntry = getVersionedEntry(mockEntry); + requestEntryVerification(FEE + 1, versionedEntry); assertEq(address(module).balance, 5 ether + FEE + 1); } function test_requestVerification_revert_feeBelowRequired() public { - bytes memory versionedBatch = getVersionedBatch(mockBatch); + bytes memory versionedEntry = getVersionedEntry(mockEntry); vm.expectRevert( abi.encodeWithSelector(IInterchainModule.InterchainModule__FeeAmountBelowMin.selector, FEE - 1, FEE) ); - requestBatchVerification(FEE - 1, mockBatch.dbNonce, versionedBatch); + requestEntryVerification(FEE - 1, versionedEntry); } function test_claimFees_zeroClaimFee_emitsEvent() public { @@ -233,20 +233,18 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE } function test_getModuleFee_thresholdTwo() public view { - // TODO: dbNonce - assertEq(module.getModuleFee(DST_CHAIN_ID, 0), FEE); + assertEq(module.getModuleFee(DST_CHAIN_ID), FEE); } function test_getModuleFee_callsGasOracle_gasLimitDefault_twoSigners() public { bytes memory mockedSignatures = new bytes(2 * 65); bytes memory remoteCalldata = - abi.encodeCall(module.verifyRemoteBatch, (abi.encode(mockBatch), mockedSignatures)); + abi.encodeCall(module.verifyRemoteEntry, (abi.encode(mockEntry), mockedSignatures)); bytes memory expectedCalldata = abi.encodeCall( gasOracle.estimateTxCostInLocalUnits, (DST_CHAIN_ID, DEFAULT_GAS_LIMIT, remoteCalldata.length) ); vm.expectCall(address(gasOracle), expectedCalldata); - // TODO: dbNonce - module.getModuleFee(DST_CHAIN_ID, 0); + module.getModuleFee(DST_CHAIN_ID); } function test_getModuleFee_callsGasOracle_gasLimitDefault_threeSigners() public { @@ -254,13 +252,12 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE module.setThreshold(3); bytes memory mockedSignatures = new bytes(3 * 65); bytes memory remoteCalldata = - abi.encodeCall(module.verifyRemoteBatch, (abi.encode(mockBatch), mockedSignatures)); + abi.encodeCall(module.verifyRemoteEntry, (abi.encode(mockEntry), mockedSignatures)); bytes memory expectedCalldata = abi.encodeCall( gasOracle.estimateTxCostInLocalUnits, (DST_CHAIN_ID, DEFAULT_GAS_LIMIT, remoteCalldata.length) ); vm.expectCall(address(gasOracle), expectedCalldata); - // TODO: dbNonce - module.getModuleFee(DST_CHAIN_ID, 0); + module.getModuleFee(DST_CHAIN_ID); } function test_getModuleFee_callsGasOracle_gasLimitSet_twoSigners() public { @@ -268,12 +265,11 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE module.setVerifyGasLimit(DST_CHAIN_ID, 200_000); bytes memory mockedSignatures = new bytes(2 * 65); bytes memory remoteCalldata = - abi.encodeCall(module.verifyRemoteBatch, (abi.encode(mockBatch), mockedSignatures)); + abi.encodeCall(module.verifyRemoteEntry, (abi.encode(mockEntry), mockedSignatures)); bytes memory expectedCalldata = abi.encodeCall(gasOracle.estimateTxCostInLocalUnits, (DST_CHAIN_ID, 200_000, remoteCalldata.length)); vm.expectCall(address(gasOracle), expectedCalldata); - // TODO: dbNonce - module.getModuleFee(DST_CHAIN_ID, 0); + module.getModuleFee(DST_CHAIN_ID); } function test_getModuleFee_callsGasOracle_gasLimitSet_threeSigners() public { @@ -283,12 +279,11 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE module.setVerifyGasLimit(DST_CHAIN_ID, 200_000); bytes memory mockedSignatures = new bytes(3 * 65); bytes memory remoteCalldata = - abi.encodeCall(module.verifyRemoteBatch, (abi.encode(mockBatch), mockedSignatures)); + abi.encodeCall(module.verifyRemoteEntry, (abi.encode(mockEntry), mockedSignatures)); bytes memory expectedCalldata = abi.encodeCall(gasOracle.estimateTxCostInLocalUnits, (DST_CHAIN_ID, 200_000, remoteCalldata.length)); vm.expectCall(address(gasOracle), expectedCalldata); - // TODO: dbNonce - module.getModuleFee(DST_CHAIN_ID, 0); + module.getModuleFee(DST_CHAIN_ID); } function test_getVerifyGasLimit_default() public view { diff --git a/packages/rest-api/CHANGELOG.md b/packages/rest-api/CHANGELOG.md index 55cf41f84a..accce47d26 100644 --- a/packages/rest-api/CHANGELOG.md +++ b/packages/rest-api/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## [1.0.64](https://github.com/synapsecns/sanguine/compare/@synapsecns/rest-api@1.0.63...@synapsecns/rest-api@1.0.64) (2024-05-09) + +**Note:** Version bump only for package @synapsecns/rest-api + + + + + ## [1.0.63](https://github.com/synapsecns/sanguine/compare/@synapsecns/rest-api@1.0.62...@synapsecns/rest-api@1.0.63) (2024-05-08) **Note:** Version bump only for package @synapsecns/rest-api diff --git a/packages/rest-api/package.json b/packages/rest-api/package.json index ab7bc3128a..08a9c1d772 100644 --- a/packages/rest-api/package.json +++ b/packages/rest-api/package.json @@ -1,6 +1,6 @@ { "name": "@synapsecns/rest-api", - "version": "1.0.63", + "version": "1.0.64", "private": "true", "engines": { "node": ">=18.17.0" @@ -23,7 +23,7 @@ "@ethersproject/bignumber": "^5.7.0", "@ethersproject/providers": "^5.7.2", "@ethersproject/units": "5.7.0", - "@synapsecns/sdk-router": "^0.5.1", + "@synapsecns/sdk-router": "^0.6.0", "bignumber": "^1.1.0", "ethers": "5.7.2", "express": "^4.18.2", diff --git a/packages/sdk-router/CHANGELOG.md b/packages/sdk-router/CHANGELOG.md index e599b16577..b8a565eafd 100644 --- a/packages/sdk-router/CHANGELOG.md +++ b/packages/sdk-router/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.6.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/sdk-router@0.5.1...@synapsecns/sdk-router@0.6.0) (2024-05-09) + + +### Features + +* **widget:** suppress console errors ([#2594](https://github.com/synapsecns/sanguine/issues/2594)) ([925447b](https://github.com/synapsecns/sanguine/commit/925447badd2065444d5df7cc14a6e6c56e10355f)), closes [#2591](https://github.com/synapsecns/sanguine/issues/2591) [#2593](https://github.com/synapsecns/sanguine/issues/2593) + + + + + ## [0.5.1](https://github.com/synapsecns/sanguine/compare/@synapsecns/sdk-router@0.5.0...@synapsecns/sdk-router@0.5.1) (2024-05-08) diff --git a/packages/sdk-router/package.json b/packages/sdk-router/package.json index 1763b59887..13af037e3b 100644 --- a/packages/sdk-router/package.json +++ b/packages/sdk-router/package.json @@ -1,7 +1,7 @@ { "name": "@synapsecns/sdk-router", "description": "An SDK for interacting with the Synapse Protocol", - "version": "0.5.1", + "version": "0.6.0", "license": "MIT", "main": "dist/index.js", "typings": "dist/index.d.ts", diff --git a/packages/sdk-router/src/rfq/fastBridgeRouter.ts b/packages/sdk-router/src/rfq/fastBridgeRouter.ts index 3ca11063d7..2bd5c48431 100644 --- a/packages/sdk-router/src/rfq/fastBridgeRouter.ts +++ b/packages/sdk-router/src/rfq/fastBridgeRouter.ts @@ -62,7 +62,10 @@ export class FastBridgeRouter implements SynapseModule { // try { // await Promise.all([this.getProtocolFeeRate()]) // } catch (e) { - // console.error('fastBridgeRouter: Error hydrating cache', e) + // console.error( + // '[SynapseSDK: FastBridgeRouter] Error hydrating cache: ', + // e + // ) // } // } // } diff --git a/packages/sdk-router/src/router/router.ts b/packages/sdk-router/src/router/router.ts index 8432fd534c..133a0766bf 100644 --- a/packages/sdk-router/src/router/router.ts +++ b/packages/sdk-router/src/router/router.ts @@ -117,7 +117,10 @@ export abstract class Router implements SynapseModule { // Don't filter anything, as the amount of returned queries should match the amount of symbols return this.getOriginAmountOut(tokenIn, tokenSymbols, amountIn) } catch (error) { - console.error('Failed to fetch origin queries', error) + console.error( + '[SynapseSDK: Router] Failed to fetch origin queries', + error + ) throw error } } @@ -138,7 +141,10 @@ export abstract class Router implements SynapseModule { // Don't filter anything, as the amount of returned queries should match the amount of requests return this.getDestinationAmountOut(requests, tokenOut) } catch (error) { - console.error('Failed to fetch destination queries', error) + console.error( + '[SynapseSDK: Router] Failed to fetch destination queries', + error + ) throw error } } diff --git a/packages/sdk-router/src/router/routerSet.ts b/packages/sdk-router/src/router/routerSet.ts index 2a32a03366..5155e5056b 100644 --- a/packages/sdk-router/src/router/routerSet.ts +++ b/packages/sdk-router/src/router/routerSet.ts @@ -141,7 +141,7 @@ export abstract class RouterSet extends SynapseModuleSet { ) } catch (error) { console.error( - `Error when trying to calculate the best quote with bridge tokens: ${bridgeTokens}`, + `[SynapseSDK: RouterSet] Error when trying to calculate the best quote with bridge tokens: ${bridgeTokens} `, error ) return [] diff --git a/packages/sdk-router/src/router/synapseCCTPRouter.ts b/packages/sdk-router/src/router/synapseCCTPRouter.ts index 43d66d3027..019bb3ca07 100644 --- a/packages/sdk-router/src/router/synapseCCTPRouter.ts +++ b/packages/sdk-router/src/router/synapseCCTPRouter.ts @@ -59,7 +59,10 @@ export class SynapseCCTPRouter extends Router { // try { // await Promise.all([this.chainGasAmount()]) // } catch (e) { - // console.error('synapseCCTPRouter: Error hydrating cache', e) + // console.error( + // '[SynapseSDK: SynapseCCTPRouter] Error hydrating cache: ', + // e + // ) // } // } // } diff --git a/packages/sdk-router/src/router/synapseRouter.ts b/packages/sdk-router/src/router/synapseRouter.ts index 48d5de39b4..9ad3caa13b 100644 --- a/packages/sdk-router/src/router/synapseRouter.ts +++ b/packages/sdk-router/src/router/synapseRouter.ts @@ -110,7 +110,7 @@ export class SynapseRouter extends Router { // try { // await Promise.all([this.chainGasAmount()]) // } catch (e) { - // console.error('synapseRouter: Error hydrating cache', e) + // console.error('[SynapseSDK: SynapseRouter] Error hydrating cache: ', e) // } // } // } diff --git a/packages/sdk-router/src/utils/RouterCache.ts b/packages/sdk-router/src/utils/RouterCache.ts index ac9e34a465..bb2a329a62 100644 --- a/packages/sdk-router/src/utils/RouterCache.ts +++ b/packages/sdk-router/src/utils/RouterCache.ts @@ -57,8 +57,10 @@ export const RouterCache = (maxAge: number) => { return res }) .catch((e) => { - console.error('RouterCache error', e) - console.log(this.chainId) + console.error( + `[SynapseSDK: RouterCache] Error on ChainID ${this.chainId}: `, + e + ) }) return result } diff --git a/packages/synapse-interface/CHANGELOG.md b/packages/synapse-interface/CHANGELOG.md index c99331d54d..de286d76a7 100644 --- a/packages/synapse-interface/CHANGELOG.md +++ b/packages/synapse-interface/CHANGELOG.md @@ -3,6 +3,28 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.23.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.22.5...@synapsecns/synapse-interface@0.23.0) (2024-05-09) + + +### Features + +* **synapse-interface:** bridge gas handler ([#2437](https://github.com/synapsecns/sanguine/issues/2437)) ([4fcfcab](https://github.com/synapsecns/sanguine/commit/4fcfcab4fd5de08788ad017fc9faf350391cf3e5)), closes [#2598](https://github.com/synapsecns/sanguine/issues/2598) + + + + + +## [0.22.5](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.22.4...@synapsecns/synapse-interface@0.22.5) (2024-05-09) + + +### Reverts + +* Revert "update bl" ([3693110](https://github.com/synapsecns/sanguine/commit/3693110e0f9df6177935bbbfba5444df62b11866)) + + + + + ## [0.22.4](https://github.com/synapsecns/sanguine/compare/@synapsecns/synapse-interface@0.22.3...@synapsecns/synapse-interface@0.22.4) (2024-05-08) **Note:** Version bump only for package @synapsecns/synapse-interface diff --git a/packages/synapse-interface/components/Portfolio/components/HoverTooltip.tsx b/packages/synapse-interface/components/HoverTooltip.tsx similarity index 55% rename from packages/synapse-interface/components/Portfolio/components/HoverTooltip.tsx rename to packages/synapse-interface/components/HoverTooltip.tsx index 88e01b5999..d27d5a8aab 100644 --- a/packages/synapse-interface/components/Portfolio/components/HoverTooltip.tsx +++ b/packages/synapse-interface/components/HoverTooltip.tsx @@ -1,21 +1,35 @@ import React, { useState } from 'react' -export const HoverTooltip = ({ children, hoverContent }) => { +export const HoverTooltip = ({ + children, + hoverContent, + isActive = true, +}: { + children: React.ReactNode + hoverContent: React.ReactNode + isActive?: boolean +}) => { const [showTooltip, setShowTooltip] = useState(false) const activateTooltip = () => setShowTooltip(true) const hideTooltip = () => setShowTooltip(false) - return ( -