Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(contracts-communication): interchain module ignore nonces #2604

Merged
merged 3 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions packages/contracts-communication/contracts/InterchainDB.sol
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB {
/// @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 Check if the entry is verified by the Interchain Module on the destination chain.
Expand Down Expand Up @@ -221,7 +221,7 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB {
)
internal
{
(uint256[] memory fees, uint256 totalFee) = _getModuleFees(dstChainId, entry.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) {
Expand All @@ -234,9 +234,7 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB {
payload: InterchainEntryLib.encodeEntry(entry)
});
for (uint256 i = 0; i < len; ++i) {
IInterchainModule(srcModules[i]).requestEntryVerification{value: fees[i]}(
dstChainId, entry.dbNonce, versionedEntry
);
IInterchainModule(srcModules[i]).requestEntryVerification{value: fees[i]}(dstChainId, versionedEntry);
}
emit InterchainEntryVerificationRequested(dstChainId, entry.dbNonce, srcModules);
}
Expand Down Expand Up @@ -265,7 +263,6 @@ contract InterchainDB is InterchainDBEvents, IInterchainDB {
/// @dev Get the verification fees for the modules
function _getModuleFees(
uint64 dstChainId,
uint64 dbNonce,
address[] calldata srcModules
)
internal
Expand All @@ -278,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];
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ interface IInterchainModule {

function requestEntryVerification(
uint64 dstChainId,
uint64 dbNonce,
bytes memory versionedEntry
)
external
payable;

// ═══════════════════════════════════════════════════ VIEWS ═══════════════════════════════════════════════════════

function getModuleFee(uint64 dstChainId, uint64 dbNonce) external view returns (uint256);
function getModuleFee(uint64 dstChainId) external view returns (uint256);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,19 @@
/// 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 dbNonce The database nonce of the entry on the source chain
/// @param versionedEntry The versioned entry to verify
function requestEntryVerification(
uint64 dstChainId,
uint64 dbNonce,
bytes memory versionedEntry
)
external
payable
{
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, dbNonce);
uint256 requiredFee = _getModuleFee(dstChainId);
if (msg.value < requiredFee) {
revert InterchainModule__FeeAmountBelowMin({feeAmount: msg.value, minRequired: requiredFee});
}
bytes memory moduleData = _fillModuleData(dstChainId, dbNonce);
bytes memory moduleData = _fillModuleData(dstChainId);
bytes memory encodedEntry = ModuleEntryLib.encodeVersionedModuleEntry(versionedEntry, moduleData);
bytes32 ethSignedEntryHash = MessageHashUtils.toEthSignedMessageHash(keccak256(encodedEntry));
_requestVerification(dstChainId, encodedEntry);
Expand All @@ -57,9 +49,8 @@

/// @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 entry 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 entry and needs to signal this
Expand All @@ -83,11 +74,11 @@
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) {}
Dismissed Show dismissed Hide dismissed

/// @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 entry on the specified destination chain.
function _getModuleFee(uint64 dstChainId, uint64 dbNonce) internal view virtual returns (uint256);
function _getModuleFee(uint64 dstChainId) internal view virtual returns (uint256);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -236,15 +229,7 @@ contract SynapseModule is InterchainModule, ClaimableFees, Ownable, SynapseModul
// ══════════════════════════════════════════════ INTERNAL VIEWS ═══════════════════════════════════════════════════

/// @dev Internal logic to get the module fee for verifying an entry on the specified destination chain.
function _getModuleFee(
uint64 dstChainId,
uint64 // dbNonce
)
internal
view
override
returns (uint256)
{
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) + entry + signatures
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ contract InterchainDBSourceTest is Test, InterchainDBEvents {
}

function getModuleCalldata(InterchainEntry memory entry) internal view returns (bytes memory) {
bytes memory vEntry = getVersionedEntry(entry);
return abi.encodeCall(IInterchainModule.requestEntryVerification, (DST_CHAIN_ID, entry.dbNonce, vEntry));
bytes memory versionedEntry = getVersionedEntry(entry);
return abi.encodeCall(IInterchainModule.requestEntryVerification, (DST_CHAIN_ID, versionedEntry));
}

function addressToBytes32(address addr) internal pure returns (bytes32) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,9 @@ import {VersionedPayloadLib} from "../../contracts/libs/VersionedPayload.sol";
// solhint-disable ordering
// solhint-disable no-empty-blocks
contract InterchainModuleMock is IInterchainModule {
function requestEntryVerification(
uint64 dstChainId,
uint64 dbNonce,
bytes calldata versionedEntry
)
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 mockVerifyRemoteEntry(address interchainDB, bytes calldata versionedEntry) external {
IInterchainDB(interchainDB).verifyRemoteEntry(versionedEntry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
return payloadLibHarness.encodeVersionedPayload(MOCK_DB_VERSION, entryLibHarness.encodeEntry(entry));
}

function requestEntryVerification(uint256 msgValue, uint64 dbNonce, bytes memory versionedEntry) internal {
function requestEntryVerification(uint256 msgValue, bytes memory versionedEntry) internal {
deal(interchainDB, msgValue);
vm.prank(interchainDB);
module.requestEntryVerification{value: msgValue}(DST_CHAIN_ID, dbNonce, versionedEntry);
module.requestEntryVerification{value: msgValue}(DST_CHAIN_ID, versionedEntry);
}

function encodeAndHashEntry(InterchainEntry memory entry)
Expand All @@ -97,13 +97,13 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
bytes memory versionedEntry = getVersionedEntry(mockEntry);
vm.expectEmit(address(module));
emit EntryVerificationRequested(DST_CHAIN_ID, encodedEntry, ethSignedHash);
requestEntryVerification(FEE, mockEntry.dbNonce, versionedEntry);
requestEntryVerification(FEE, versionedEntry);
}

function test_requestVerification_accumulatesFee() public {
deal(address(module), 5 ether);
bytes memory versionedEntry = getVersionedEntry(mockEntry);
requestEntryVerification(FEE, mockEntry.dbNonce, versionedEntry);
requestEntryVerification(FEE, versionedEntry);
assertEq(address(module).balance, 5 ether + FEE);
}

Expand All @@ -112,13 +112,13 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
bytes memory versionedEntry = getVersionedEntry(mockEntry);
vm.expectEmit(address(module));
emit EntryVerificationRequested(DST_CHAIN_ID, encodedEntry, ethSignedHash);
requestEntryVerification(FEE + 1, mockEntry.dbNonce, versionedEntry);
requestEntryVerification(FEE + 1, versionedEntry);
}

function test_requestVerification_feeAboveRequired_accumulatesFee() public {
deal(address(module), 5 ether);
bytes memory versionedEntry = getVersionedEntry(mockEntry);
requestEntryVerification(FEE + 1, mockEntry.dbNonce, versionedEntry);
requestEntryVerification(FEE + 1, versionedEntry);
assertEq(address(module).balance, 5 ether + FEE + 1);
}

Expand All @@ -127,7 +127,7 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
vm.expectRevert(
abi.encodeWithSelector(IInterchainModule.InterchainModule__FeeAmountBelowMin.selector, FEE - 1, FEE)
);
requestEntryVerification(FEE - 1, mockEntry.dbNonce, versionedEntry);
requestEntryVerification(FEE - 1, versionedEntry);
}

function test_claimFees_zeroClaimFee_emitsEvent() public {
Expand Down Expand Up @@ -233,8 +233,7 @@ 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 {
Expand All @@ -245,8 +244,7 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
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 {
Expand All @@ -259,8 +257,7 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
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 {
Expand All @@ -272,8 +269,7 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
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 {
Expand All @@ -287,8 +283,7 @@ contract SynapseModuleSourceTest is Test, ClaimableFeesEvents, InterchainModuleE
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 {
Expand Down
Loading