-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Contracts/communication synapse module (#2050)
* Isolate some common logic into abstract contract * Scaffold `ThresholdECDSAModule` * Add more views * Implement management tests * Implement management actions * Add `InterchainDB` Mock * Reorg events following #2049 * Also emit ethSingedMsg hash * More `InterchainModule` errors * Implement tests for fee collector management * Fix: use the entry hash for signing * Implement `feeCollector` management * Start doing source tests * Add GasOracle interface * Update `verifyEntry()` interface * Add source chain tests * Implement source chain funcs * Add tests: `bytes` for signatures instead of `bytes[]` * Implement library update * Simplify math * Implement `verifyEntry()` * Add tests for destination chain * Don't use infinity as default threshold * Check source chain id in any InterchainModule * Deprecate old SynapseModule * Fix ClientV1 test * Chore: cleanup * Chore: renamoooor * Revert "Fix ClientV1 test" This reverts commit e724c38. * Revert "Chore: cleanup" This reverts commit 41949cd. * Fix ClientV1 test * Chore: cleanup
- Loading branch information
1 parent
00da108
commit c9a789f
Showing
20 changed files
with
1,104 additions
and
548 deletions.
There are no files selected for viewing
12 changes: 0 additions & 12 deletions
12
packages/contracts-communication/contracts/InterchainModule.sol
This file was deleted.
Oops, something went wrong.
10 changes: 10 additions & 0 deletions
10
packages/contracts-communication/contracts/events/InterchainModuleEvents.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {InterchainEntry} from "../libs/InterchainEntry.sol"; | ||
|
||
abstract contract InterchainModuleEvents { | ||
event VerificationRequested(uint256 indexed destChainId, bytes entry, bytes32 ethSignedEntryHash); | ||
|
||
event EntryVerified(InterchainEntry entry); | ||
} |
10 changes: 6 additions & 4 deletions
10
packages/contracts-communication/contracts/events/SynapseModuleEvents.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,11 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {InterchainEntry} from "../libs/InterchainEntry.sol"; | ||
|
||
abstract contract SynapseModuleEvents { | ||
event VerificationRequested(uint256 indexed destChainId, InterchainEntry entry, bytes32 signableEntryHash); | ||
event EntryVerified(InterchainEntry entry, bytes32 signableEntryHash); | ||
event VerifierAdded(address verifier); | ||
event VerifierRemoved(address verifier); | ||
event ThresholdChanged(uint256 threshold); | ||
|
||
event FeeCollectorChanged(address feeCollector); | ||
event GasOracleChanged(address gasOracle); | ||
} |
40 changes: 40 additions & 0 deletions
40
packages/contracts-communication/contracts/interfaces/IGasOracle.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
interface IGasOracle { | ||
/// @notice Convert a value from the native token of a remote chain to the local native token. | ||
/// @dev Will revert if no price is available for the remote chain. | ||
/// @param remoteChainId The chain id of the remote chain. | ||
/// @param value The value to convert. | ||
function convertRemoteValueToLocalUnits(uint256 remoteChainId, uint256 value) external view returns (uint256); | ||
|
||
/// @notice Estimate the cost of execution a transaction on a remote chain, | ||
/// and convert it to the local native token. | ||
/// @dev Will revert if no price is available for the remote chain. | ||
/// @param remoteChainId The chain id of the remote chain. | ||
/// @param gasLimit The gas limit of the transaction. | ||
/// @param calldataSize The size of the transaction calldata. | ||
function estimateTxCostInLocalUnits( | ||
uint256 remoteChainId, | ||
uint256 gasLimit, | ||
uint256 calldataSize | ||
) | ||
external | ||
view | ||
returns (uint256); | ||
|
||
/// @notice Estimate the cost of execution a transaction on a remote chain, | ||
/// and return it as is in the remote chain's native token. | ||
/// @dev Will revert if no price is available for the remote chain. | ||
/// @param remoteChainId The chain id of the remote chain. | ||
/// @param gasLimit The gas limit of the transaction. | ||
/// @param calldataSize The size of the transaction calldata. | ||
function estimateTxCostInRemoteUnits( | ||
uint256 remoteChainId, | ||
uint256 gasLimit, | ||
uint256 calldataSize | ||
) | ||
external | ||
view | ||
returns (uint256); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 58 additions & 30 deletions
88
packages/contracts-communication/contracts/interfaces/ISynapseModule.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,62 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {InterchainEntry} from "../libs/InterchainEntry.sol"; | ||
|
||
interface ISynapseModule { | ||
/// @notice Sets the address of the InterchainDB contract to be used for verifying entries. | ||
/// @dev This function can only be called by the contract owner. | ||
/// @param _interchainDB The address of the InterchainDB contract. | ||
function setInterchainDB(address _interchainDB) external; | ||
|
||
/// @notice Sets the required threshold for verification. | ||
/// @dev This function updates the threshold value that determines the minimum number of verifications required for an entry to be considered valid. Can only be called by the contract owner. | ||
/// @param _threshold The new threshold value. | ||
function setRequiredThreshold(uint256 _threshold) external; | ||
|
||
/// @notice Updates the list of verifier addresses. | ||
/// @dev This function sets the addresses that are allowed to act as verifiers for entries. Can only be called by the contract owner. | ||
/// @param _verifiers An array of addresses to be set as verifiers. | ||
function setVerifiers(address[] calldata _verifiers) external; | ||
|
||
/// @notice Requests off-chain verification of an interchain entry for a specified destination chain. This function requires a fee. | ||
/// @dev This function can only be called by the InterchainDB contract. It checks if the sent value covers the module fee for the requested destination chain, then proceeds to pay the fee for execution. Emits a VerificationRequested event upon success. | ||
/// @param destChainId The ID of the destination chain where the entry needs to be verified. | ||
/// @param entry The interchain entry to be verified. | ||
function requestVerification(uint256 destChainId, InterchainEntry memory entry) external payable; | ||
|
||
/// @notice Verifies an interchain entry using a set of verifier signatures. | ||
/// @dev This function checks if the provided signatures meet the required threshold for verification. | ||
/// It then calls the InterchainDB contract to verify the entry. Requires that the number of valid signatures meets or exceeds the required threshold. | ||
/// @param entry The interchain entry to be verified. | ||
/// @param signatures An array of signatures used to verify the entry. | ||
function verifyEntry(InterchainEntry memory entry, bytes[] calldata signatures) external; | ||
import {IInterchainModule} from "./IInterchainModule.sol"; | ||
|
||
interface ISynapseModule is IInterchainModule { | ||
error SynapseModule__GasOracleNotContract(address gasOracle); | ||
|
||
// ═══════════════════════════════════════════════ PERMISSIONED ════════════════════════════════════════════════════ | ||
|
||
/// @notice Adds a new verifier to the module. | ||
/// @dev Could be only called by the owner. Will revert if the verifier is already added. | ||
/// @param verifier The address of the verifier to add | ||
function addVerifier(address verifier) external; | ||
|
||
/// @notice Removes a verifier from the module. | ||
/// @dev Could be only called by the owner. Will revert if the verifier is not added. | ||
/// @param verifier The address of the verifier to remove | ||
function removeVerifier(address verifier) external; | ||
|
||
/// @notice Sets the threshold of the module. | ||
/// @dev Could be only called by the owner. Will revert if the threshold is zero. | ||
/// @param threshold The new threshold value | ||
function setThreshold(uint256 threshold) external; | ||
|
||
/// @notice Sets the address of the fee collector, which will have the verification fees forwarded to it. | ||
/// @dev Could be only called by the owner. | ||
/// @param feeCollector_ The address of the fee collector | ||
function setFeeCollector(address feeCollector_) external; | ||
|
||
/// @notice Sets the address of the gas oracle to be used for estimating the verification fees. | ||
/// @dev Could be only called by the owner. Will revert if the gas oracle is not a contract. | ||
/// @param gasOracle_ The address of the gas oracle contract | ||
function setGasOracle(address gasOracle_) external; | ||
|
||
// ══════════════════════════════════════════════ PERMISSIONLESS ═══════════════════════════════════════════════════ | ||
|
||
/// @notice Verifies an entry 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 encodedEntry The encoded entry to verify | ||
/// @param signatures Signatures used to verify the entry, concatenated | ||
function verifyEntry(bytes calldata encodedEntry, bytes calldata signatures) external; | ||
|
||
// ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════ | ||
|
||
/// @notice Returns the address of the fee collector for the module. | ||
function feeCollector() external view returns (address); | ||
|
||
/// @notice Returns the address of the gas oracle used for estimating the verification fees. | ||
function gasOracle() external view returns (address); | ||
|
||
/// @notice Returns the list of verifiers for the module. | ||
function getVerifiers() external view returns (address[] memory); | ||
|
||
/// @notice Gets the threshold of the module. | ||
/// This is the minimum number of signatures required for verification. | ||
function getThreshold() external view returns (uint256); | ||
|
||
/// @notice Checks if the given account is a verifier for the module. | ||
function isVerifier(address account) external view returns (bool); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
packages/contracts-communication/contracts/modules/InterchainModule.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import {InterchainModuleEvents} from "../events/InterchainModuleEvents.sol"; | ||
import {IInterchainDB} from "../interfaces/IInterchainDB.sol"; | ||
import {IInterchainModule} from "../interfaces/IInterchainModule.sol"; | ||
|
||
import {InterchainEntry} from "../libs/InterchainEntry.sol"; | ||
|
||
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; | ||
|
||
/// @notice Common logic for all Interchain Modules. | ||
abstract contract InterchainModule is InterchainModuleEvents, IInterchainModule { | ||
address public immutable INTERCHAIN_DB; | ||
|
||
constructor(address interchainDB) { | ||
INTERCHAIN_DB = interchainDB; | ||
} | ||
|
||
/// @inheritdoc IInterchainModule | ||
function requestVerification(uint256 destChainId, InterchainEntry memory entry) external payable { | ||
if (msg.sender != INTERCHAIN_DB) { | ||
revert InterchainModule__NotInterchainDB(); | ||
} | ||
if (destChainId == block.chainid) { | ||
revert InterchainModule__SameChainId(); | ||
} | ||
if (entry.srcChainId != block.chainid) { | ||
revert InterchainModule__IncorrectSourceChainId({chainId: entry.srcChainId}); | ||
} | ||
uint256 requiredFee = _getModuleFee(destChainId); | ||
if (msg.value < requiredFee) { | ||
revert InterchainModule__InsufficientFee({actual: msg.value, required: requiredFee}); | ||
} | ||
bytes memory encodedEntry = abi.encode(entry); | ||
bytes32 ethSignedEntryHash = MessageHashUtils.toEthSignedMessageHash(keccak256(encodedEntry)); | ||
_requestVerification(destChainId, encodedEntry); | ||
emit VerificationRequested(destChainId, encodedEntry, ethSignedEntryHash); | ||
} | ||
|
||
/// @inheritdoc IInterchainModule | ||
function getModuleFee(uint256 destChainId) external view returns (uint256) { | ||
return _getModuleFee(destChainId); | ||
} | ||
|
||
/// @dev Should be called once the Module has verified the entry and needs to signal this | ||
/// to the InterchainDB. | ||
function _verifyEntry(bytes memory encodedEntry) internal { | ||
InterchainEntry memory entry = abi.decode(encodedEntry, (InterchainEntry)); | ||
if (entry.srcChainId == block.chainid) { | ||
revert InterchainModule__SameChainId(); | ||
} | ||
IInterchainDB(INTERCHAIN_DB).verifyEntry(entry); | ||
emit EntryVerified(entry); | ||
} | ||
|
||
/// @dev Internal logic to request the verification of an entry on the destination chain. | ||
function _requestVerification(uint256 destChainId, bytes memory encodedEntry) internal virtual; | ||
|
||
/// @dev Internal logic to get the module fee for verifying an entry on the specified destination chain. | ||
function _getModuleFee(uint256 destChainId) internal view virtual returns (uint256); | ||
} |
29 changes: 0 additions & 29 deletions
29
packages/contracts-communication/contracts/modules/SynapseGasService.sol
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.