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

FE release 2024-03-29 #2400

Merged
merged 17 commits into from
Mar 29, 2024
Merged

FE release 2024-03-29 #2400

merged 17 commits into from
Mar 29, 2024

Conversation

abtestingalpha
Copy link
Collaborator

@abtestingalpha abtestingalpha commented Mar 29, 2024

null
4172612d475723b7198f4c5e76de21a3d27a1113: synapse-interface preview link

Summary by CodeRabbit

  • New Features
    • Introduced a function for retrieving distinct chain IDs based on address and status, enhancing transaction processing efficiency.
    • Added support for new chain IDs for Avalanche, Base, and Polygon networks, expanding network compatibility.
  • Enhancements
    • Updated Docker image tag for improved CI/CD process reliability.
    • Enhanced transaction processing logic for better performance and accuracy.
  • Documentation
    • Updated CHANGELOGs across various packages to document notable changes, version bumps, and dependency updates.
  • Refactor
    • Refined code structure and naming conventions in the executionservice package for clarity and maintainability.
  • Tests
    • Added tests to validate the retrieval of chain IDs by status.
  • Chores
    • Updated contracts, scripts, tests, and package versions to align with new functionality and structural changes.
  • Style
    • Improved Solidity contract processing with updated flatten.sh scripts, facilitating easier contract management and deployment.

trajan0x and others added 17 commits March 28, 2024 14:11
Co-authored-by: Trajan0x <trajan0x@users.noreply.github.com>
 - contracts-communication@1.0.1
 - @synapsecns/contracts-core@1.0.30
 - FastBridge@0.1.1
* Install OZ contracts-upgradeable 5.0.1

* Scaffold SynapseExecutionServiceV1

* Port ExecService tests

* Implement management

* Implement fees/execution request

* Implement ERC-7201 storage

* Properly exclude proxy admin from fuzz tests

* Update integration tests

* Remove deprecated impl

* Adjust configuration script

* Adjust deployment workflow

* Fix: config script

* Chore: yarn install

* Add harness for `SynapseExecutionServiceV1`

* Update `ExecutionService.sol` references

* Regenerate `sin-executor`

* Chore: ExecutionService -> SynapseExecutionServiceV1Harness

* Update ExecService deployment workflow in tests

* Chore: implicit TransparentUpgradeableProxy deployment, docs

* Chore: fix linter warnings

* Regenerate

* Mark SynExecServiceV1 functions as virtual to simplify V2 development

* Implement global markup management

* Chore: simplify Fees test

* Add new tests

* Implement global markup

* Regenerate `sin-executor`
* Scaffold legacy message library

* Implement

* Scaffold legacy options library

* Implement `LegacyOptionsLib`

* Scaffold wrapper for Legacy MessageBus

* Add interface for legacy receiver contracts

* Expose nonce in MessageBus

* Add unit tests for MessageBus

* Implement management

* Implement sending

* Implement receiving, with some TODOs

* Chore: fix linter warnings

* Resolve TODOs, leave notes

* Chore: consistent params ordering

* Chore: silence linter in tests
 - contracts-communication@1.0.2
)

* Scaffold `payloadSize` library func

* Add smol lib for math purposes

* Implement `payloadSize`

* Use `payloadSize()` instead of encoding in ClientV1

* Rework `client.getInterchainFee()` to take message len as param

* Update Apps to use message length for getters

* Chore: fix outdated terminology

* Regenerate `sin-executor`

* Chore: lint
Co-authored-by: Trajan0x <trajan0x@users.noreply.github.com>
* Fix: follow naming convention for deployed proxy

* Fix: naming convention for ProxyAdmin (deployed by proxy)
 - contracts-communication@1.0.3
* Feat: add GetChainIDsByStatus() to db service; fetch pending txs by chain

* Feat: add TestGetChainIDsByStatus

* [goreleaser]

* Fix: mark ReplacedOrConfirmed on Pending / Stored statuses

* [goreleaser]
* Fix: shadowing

* Chore: silence linter warnings in scripts
 - contracts-communication@1.0.4
 - @synapsecns/rest-api@1.0.58
 - @synapsecns/sdk-router@0.4.0
 - @synapsecns/synapse-interface@0.15.2
 - @synapsecns/widget@0.1.12
* v3 SIN testnet deployment

* Chore: rename to comply with #2392

* Chore: `forge fmt`

---------

Co-authored-by: ChiTimesChi <88190723+ChiTimesChi@users.noreply.github.com>
 - contracts-communication@1.0.5
Copy link
Contributor

coderabbitai bot commented Mar 29, 2024

Walkthrough

This update involves enhancing a blockchain-related project with new features and improvements across its infrastructure. It introduces a function to retrieve chain IDs based on status, updates Docker tags for actions, and adds new chain IDs for various networks. The changes also include updates to contracts, scripts, and dependencies across several packages, aiming to improve functionality, compatibility, and security.

Changes

Files Change Summary
.github/workflows/... Updated Docker image tag for git-changes-action.
ethergo/submitter/db/mocks/service.go Added GetChainIDsByStatus mock function.
ethergo/submitter/db/service.go Introduced GetChainIDsByStatus function.
ethergo/submitter/db/txdb/store.go Expanded functionality and added GetChainIDsByStatus.
ethergo/submitter/db_test.go Added test for GetChainIDsByStatus.
ethergo/submitter/queue.go Updated structure for transaction processing.
make/scripts/..., packages/contracts-.../script/sh/... Updated flatten.sh script for Solidity contracts.
packages/contracts-.../CHANGELOG.md, packages/.../package.json Documented changes and updated versions and dependencies.
services/cctp-relayer/relayer/chains.go Added new chain IDs for Avalanche, Base, and Polygon networks.
sin-executor/contracts/executionservice/* Updated naming conventions and functionality.

Possibly related issues

  • Dependency Dashboard #16: The extensive dependency updates and improvements in CI/CD workflows align with the objectives of addressing repository problems and ensuring compatibility and stability through updates.

🐰✨
A hop, a skip, in the blockchain's embrace,
We've added, we've fixed, with diligent grace.
Chains intertwine, in a digital race,
Updates far and wide, setting the pace.
With each line of code, we chase,
A better tomorrow, in this cybernetic space.
🌟🐾

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Comment on lines +87 to +119
function getExecutionFee(
uint256 dstChainId,
uint256 txPayloadSize,
bytes memory options
)
public
view
virtual
returns (uint256 executionFee)
{
address cachedGasOracle = gasOracle();
if (cachedGasOracle == address(0)) {
revert SynapseExecutionService__GasOracleNotSet();
}
// TODO: the "exact version" check should be generalized
(uint8 version,) = OptionsLib.decodeVersionedOptions(options);
if (version > OptionsLib.OPTIONS_V1) {
revert SynapseExecutionService__OptionsVersionNotSupported(version);
}
OptionsV1 memory optionsV1 = OptionsLib.decodeOptionsV1(options);
executionFee = IGasOracle(cachedGasOracle).estimateTxCostInLocalUnits({
remoteChainId: dstChainId,
gasLimit: optionsV1.gasLimit,
calldataSize: txPayloadSize
});
if (optionsV1.gasAirdrop > 0) {
executionFee += IGasOracle(cachedGasOracle).convertRemoteValueToLocalUnits({
remoteChainId: dstChainId,
value: optionsV1.gasAirdrop
});
}
executionFee += executionFee * globalMarkup() / WAD;
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +20 to +60
function sendMessage(
bytes32 receiver,
uint256 dstChainId,
bytes calldata message,
bytes calldata options
)
external
payable
{
address dstReceiver = TypeCasts.bytes32ToAddress(receiver);
if (TypeCasts.addressToBytes32(dstReceiver) != receiver) {
revert MessageBus__NotEVMReceiver(receiver);
}
uint64 cachedNonce = nonce++;
// Note: we are using the internal nonce here to generate the unique message ID.
// This is used for tracking purposes and is not used for replay protection.
// Instead, we rely on the Interchain Client to provide replay protection.
bytes memory encodedLegacyMsg = LegacyMessageLib.encodeLegacyMessage({
srcSender: msg.sender,
dstReceiver: dstReceiver,
srcNonce: cachedNonce,
message: message
});
_sendToLinkedApp({
dstChainId: dstChainId,
messageFee: msg.value,
options: _icOptionsV1(options),
message: encodedLegacyMsg
});
emit MessageSent({
sender: msg.sender,
srcChainID: block.chainid,
receiver: receiver,
dstChainId: dstChainId,
message: message,
nonce: cachedNonce,
options: options,
fee: msg.value,
messageId: keccak256(encodedLegacyMsg)
});
}
Comment on lines +87 to +113
function _receiveMessage(
uint256 srcChainId,
bytes32, // sender
uint256, // dbNonce
uint64, // entryIndex
bytes calldata encodedLegacyMsg
)
internal
override
{
(address srcSender, address dstReceiver, uint64 srcNonce, bytes memory message) =
LegacyMessageLib.decodeLegacyMessage(encodedLegacyMsg);
// Note: we rely on the Interchain Client to provide replay protection.
ILegacyReceiver(dstReceiver).executeMessage({
srcAddress: TypeCasts.addressToBytes32(srcSender),
srcChainId: srcChainId,
message: message,
executor: msg.sender
});
emit Executed({
messageId: keccak256(encodedLegacyMsg),
status: TxStatus.Success,
dstAddress: dstReceiver,
srcChainId: uint64(srcChainId),
srcNonce: srcNonce
});
}
Comment on lines +140 to +145
function _getSynapseExecutionServiceV1Storage() private pure returns (SynapseExecutionServiceV1Storage storage $) {
// solhint-disable-next-line no-inline-assembly
assembly {
$.slot := SYNAPSE_EXECUTION_SERVICE_V1_STORAGE_LOCATION
}
}

Check warning

Code scanning / Slither

Assembly usage Warning

Comment on lines +17 to +19
function encodeLegacyOptions(uint256 gasLimit) internal pure returns (bytes memory legacyOpts) {
return abi.encodePacked(LEGACY_OPTIONS_VERSION, gasLimit);
}

Check warning

Code scanning / Slither

Dead-code Warning

LegacyOptionsLib.encodeLegacyOptions(uint256) is never used and should be removed
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

Check warning

Code scanning / Slither

Incorrect versions of Solidity Warning

Pragma version^0.8.0 allows old versions
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

Check warning

Code scanning / Slither

Incorrect versions of Solidity Warning

Pragma version^0.8.0 allows old versions
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

Check warning

Code scanning / Slither

Incorrect versions of Solidity Warning

Pragma version^0.8.0 allows old versions
@@ -0,0 +1,119 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

Check warning

Code scanning / Slither

Incorrect versions of Solidity Warning

Pragma version0.8.20 necessitates a version too recent to be trusted. Consider deploying with 0.8.18.
/// @dev The length of the legacy options format: 2 bytes for the version and 32 bytes for the gas limit.
uint256 private constant LEGACY_OPTIONS_LENGTH = 34;
/// @dev The offset of the gas limit in the legacy options format.
uint256 private constant GAS_LIMIT_OFFSET = 2;

Check warning

Code scanning / Slither

Unused state variable Warning

Copy link

codecov bot commented Mar 29, 2024

Codecov Report

Attention: Patch coverage is 59.44056% with 58 lines in your changes are missing coverage. Please review.

Project coverage is 49.13394%. Comparing base (914561c) to head (ae858ad).
Report is 4 commits behind head on fe-release.

Files Patch % Lines
...acts-communication/script/deploy/DeployProxy.s.sol 0.00000% 14 Missing ⚠️
...pt/config/ConfigureSynapseExecutionServiceV1.s.sol 0.00000% 13 Missing ⚠️
...on/script/config/ConfigureSynapseGasOracleV1.s.sol 0.00000% 11 Missing ⚠️
ethergo/submitter/queue.go 61.90476% 7 Missing and 1 partial ⚠️
...cript/deploy/DeploySynapseExecutionServiceV1.s.sol 0.00000% 3 Missing ⚠️
sin-executor/testutil/deployers.go 57.14286% 2 Missing and 1 partial ⚠️
...s-communication/script/config/ConfigureAppV1.s.sol 0.00000% 2 Missing ⚠️
sin-executor/testutil/typecast.go 0.00000% 2 Missing ⚠️
...unication/contracts/apps/examples/ExampleAppV1.sol 0.00000% 1 Missing ⚠️
.../contracts/execution/SynapseExecutionServiceV1.sol 97.22222% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@                 Coverage Diff                  @@
##           fe-release       #2400         +/-   ##
====================================================
+ Coverage    47.18914%   49.13394%   +1.94480%     
====================================================
  Files             417         464         +47     
  Lines           29973       31522       +1549     
  Branches          220         509        +289     
====================================================
+ Hits            14144       15488       +1344     
- Misses          14357       14488        +131     
- Partials         1472        1546         +74     
Flag Coverage Δ
packages 90.52734% <ø> (-0.09767%) ⬇️
solidity 77.41379% <59.82143%> (+19.54577%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines +6 to +11
# [0.4.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/sdk-router@0.3.29...@synapsecns/sdk-router@0.4.0) (2024-03-29)


### Features

* **sdk-router:** Add Base to the list of supported RFQ chains ([#2398](https://github.com/synapsecns/sanguine/issues/2398)) ([0425595](https://github.com/synapsecns/sanguine/commit/0425595c026bbc698a5f8a9ffd8f500fd2db1ae9))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog update for version 0.4.0 correctly documents the addition of "Base" to the list of supported RFQ chains. However, there's a minor typographical issue detected in the context around the feature description. It's generally a good practice to ensure all textual content is free from spelling mistakes to maintain professionalism in documentation.

-* **sdk-router:** Add Base to the list of supported RFQ chains ([#2398](https://github.com/synapsecns/sanguine/issues/2398)) ([0425595](https://github.com/synapsecns/sanguine/commit/0425595c026bbc698a5f8a9ffd8f500fd2db1ae9))
+* **sdk-router:** Added Base to the list of supported RFQ chains ([#2398](https://github.com/synapsecns/sanguine/issues/2398)) ([0425595](https://github.com/synapsecns/sanguine/commit/0425595c026bbc698a5f8a9ffd8f500fd2db1ae9))

While the original text is not incorrect, adjusting the verb tense to "Added" aligns better with the conventional past tense used in changelogs for completed actions.


Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
# [0.4.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/sdk-router@0.3.29...@synapsecns/sdk-router@0.4.0) (2024-03-29)
### Features
* **sdk-router:** Add Base to the list of supported RFQ chains ([#2398](https://github.com/synapsecns/sanguine/issues/2398)) ([0425595](https://github.com/synapsecns/sanguine/commit/0425595c026bbc698a5f8a9ffd8f500fd2db1ae9))
# [0.4.0](https://github.com/synapsecns/sanguine/compare/@synapsecns/sdk-router@0.3.29...@synapsecns/sdk-router@0.4.0) (2024-03-29)
### Features
* **sdk-router:** Added Base to the list of supported RFQ chains ([#2398](https://github.com/synapsecns/sanguine/issues/2398)) ([0425595](https://github.com/synapsecns/sanguine/commit/0425595c026bbc698a5f8a9ffd8f500fd2db1ae9))

@@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive pragma solidity ^0.8.0; is too broad, potentially allowing for compilation with older, less secure versions of Solidity. Consider specifying a more precise version range or the latest version to ensure compatibility and security.

- pragma solidity ^0.8.0;
+ pragma solidity 0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity 0.8.20;

@@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive pragma solidity ^0.8.0; is too broad, potentially allowing for compilation with older, less secure versions of Solidity. Consider specifying a more precise version range or the latest version to ensure compatibility and security.

- pragma solidity ^0.8.0;
+ pragma solidity 0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity 0.8.20;

@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive pragma solidity ^0.8.0; is too broad, potentially allowing for compilation with older, less secure versions of Solidity. Consider specifying a more precise version range or the latest version to ensure compatibility and security.

- pragma solidity ^0.8.0;
+ pragma solidity 0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity 0.8.20;

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive pragma solidity ^0.8.0; is too broad, potentially allowing for compilation with older, less secure versions of Solidity. Consider specifying a more precise version range or the latest version to ensure compatibility and security.

- pragma solidity ^0.8.0;
+ pragma solidity 0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity 0.8.20;

Comment on lines +357 to +383
// GetChainIDsByStatus returns the distinct chain ids for a given address and status.
func (s *Store) GetChainIDsByStatus(ctx context.Context, fromAddress common.Address, matchStatuses ...db.Status) (chainIDs []*big.Int, err error) {
chainIDs64 := []uint64{}

inArgs := statusToArgs(matchStatuses...)

query := ETHTX{
From: fromAddress.String(),
}

tx := s.DB().WithContext(ctx).
Model(&ETHTX{}).
Select(chainIDFieldName).
Distinct().
Where(query).
Where(fmt.Sprintf("%s IN ?", statusFieldName), inArgs).
Find(&chainIDs64)
if tx.Error != nil {
return nil, fmt.Errorf("could not get chain ids: %w", tx.Error)
}

for _, chainID64 := range chainIDs64 {
chainIDs = append(chainIDs, new(big.Int).SetUint64(chainID64))
}

return chainIDs, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of the GetChainIDsByStatus function is a significant enhancement. It introduces a new capability to retrieve distinct chain IDs for a given address and status, which can be crucial for operations that need to process transactions based on their blockchain and status. Ensure that this function is thoroughly tested, especially for edge cases such as no matching records or handling of multiple statuses.

Would you like me to help with generating unit tests for the GetChainIDsByStatus function?

Comment on lines +4 to +8
import {OptionsLib, OptionsV1} from "../../contracts/libs/Options.sol";

import {SynapseExecutionServiceV1Test} from "./SynapseExecutionServiceV1.t.sol";

import {SynapseGasOracleMock} from "../mocks/SynapseGasOracleMock.sol";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider grouping imports for better readability and maintainability.

-import {OptionsLib, OptionsV1} from "../../contracts/libs/Options.sol";
-import {SynapseExecutionServiceV1Test} from "./SynapseExecutionServiceV1.t.sol";
-import {SynapseGasOracleMock} from "../mocks/SynapseGasOracleMock.sol";
+import {
+    OptionsLib,
+    OptionsV1
+} from "../../contracts/libs/Options.sol";
+import { SynapseExecutionServiceV1Test } from "./SynapseExecutionServiceV1.t.sol";
+import { SynapseGasOracleMock } from "../mocks/SynapseGasOracleMock.sol";

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
import {OptionsLib, OptionsV1} from "../../contracts/libs/Options.sol";
import {SynapseExecutionServiceV1Test} from "./SynapseExecutionServiceV1.t.sol";
import {SynapseGasOracleMock} from "../mocks/SynapseGasOracleMock.sol";
import {
OptionsLib,
OptionsV1
} from "../../contracts/libs/Options.sol";
import { SynapseExecutionServiceV1Test } from "./SynapseExecutionServiceV1.t.sol";
import { SynapseGasOracleMock } from "../mocks/SynapseGasOracleMock.sol";

Comment on lines +116 to +122
function test_getExecutionFee_noAirdrop() public {
uint256 fee = service.getExecutionFee({
dstChainId: REMOTE_CHAIN_ID,
txPayloadSize: MOCK_CALLDATA_SIZE,
options: optionsNoAirdrop.encodeOptionsV1()
});
assertEq(fee, MOCK_FEE_NO_AIRDROP);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test test_getExecutionFee_noAirdrop correctly asserts the execution fee without airdrop. Ensure comprehensive coverage by adding tests for edge cases and unexpected inputs.

Would you like me to help generate additional test cases for edge conditions?

Comment on lines +163 to +176
function test_requestExecution_clientA_noAirdrop_exactFee() public {
expectEventExecutionRequested(MOCK_TX_ID, icClientA);
requestExecution(icClientA, MOCK_FEE_NO_AIRDROP, encodedOptionsNoAirdrop);
}

function test_requestExecution_clientA_noAirdrop_higherFee() public {
expectEventExecutionRequested(MOCK_TX_ID, icClientA);
requestExecution(icClientA, MOCK_FEE_NO_AIRDROP + 1, encodedOptionsNoAirdrop);
}

function test_requestExecution_clientA_noAirdrop_revert_lowerFee() public {
expectRevertFeeAmountTooLow(MOCK_FEE_NO_AIRDROP - 1, MOCK_FEE_NO_AIRDROP);
requestExecution(icClientA, MOCK_FEE_NO_AIRDROP - 1, encodedOptionsNoAirdrop);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests for requestExecution with exact, higher, and lower fees are well-structured. However, consider adding tests for boundary values of the fee amount to ensure robustness.

Would you like assistance in creating boundary value tests for the fee amount?

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive ^0.8.0 allows for older, potentially less secure versions of Solidity. Consider specifying a more recent version, such as ^0.8.20, to ensure the use of up-to-date compiler features and security fixes.

- pragma solidity ^0.8.0;
+ pragma solidity ^0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity ^0.8.20;

@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive ^0.8.0 allows older, potentially insecure versions of Solidity. Consider specifying a more recent or fixed version, such as ^0.8.20, for improved security and compatibility.

- pragma solidity ^0.8.0;
+ pragma solidity ^0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity ^0.8.20;

Comment on lines +29 to +37
function setGovernor() internal {
printLog("Setting Governor");
bytes32 governorRole = service.GOVERNOR_ROLE();
if (!service.hasRole(governorRole, msg.sender)) {
service.grantRole(governorRole, msg.sender);
printSuccessWithIndent(string.concat("Granted Governor role to ", vm.toString(msg.sender)));
} else {
printSkipWithIndent(string.concat("governor role already granted to ", vm.toString(msg.sender)));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setGovernor function correctly checks for the governor role before granting it, which is a secure practice. However, ensure that test coverage is added for this function to verify its behavior under various conditions.

Would you like me to help with adding test coverage for this function?

@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive ^0.8.0 allows for older, potentially less secure versions of Solidity. Consider specifying a more recent version, such as ^0.8.20, to ensure the use of up-to-date compiler features and security fixes.

- pragma solidity ^0.8.0;
+ pragma solidity ^0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity ^0.8.20;

@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pragma directive ^0.8.0 allows for older, potentially less secure versions of Solidity. Consider specifying a more recent version, such as ^0.8.20, to ensure the use of up-to-date compiler features and security fixes.

- pragma solidity ^0.8.0;
+ pragma solidity ^0.8.20;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity ^0.8.0;
pragma solidity ^0.8.20;

@@ -51,7 +51,7 @@
view
returns (uint256)
{
return _getMessageFee(dstChainId, OptionsV1({gasLimit: gasLimit, gasAirdrop: gasAirdrop}), message);
return _getMessageFee(dstChainId, OptionsV1({gasLimit: gasLimit, gasAirdrop: gasAirdrop}), message.length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update to pass message.length to _getMessageFee in the getMessageFee function is consistent with the shift towards using message lengths for fee calculations. However, this line was flagged by static analysis as not covered by tests. Ensure that there are tests covering this change to validate its correctness and to prevent regressions in the future.

+ // TODO: Add test coverage for getMessageFee with message.length

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
return _getMessageFee(dstChainId, OptionsV1({gasLimit: gasLimit, gasAirdrop: gasAirdrop}), message.length);
// TODO: Add test coverage for getMessageFee with message.length
return _getMessageFee(dstChainId, OptionsV1({gasLimit: gasLimit, gasAirdrop: gasAirdrop}), message.length);

Comment on lines +20 to +60
function sendMessage(
bytes32 receiver,
uint256 dstChainId,
bytes calldata message,
bytes calldata options
)
external
payable
{
address dstReceiver = TypeCasts.bytes32ToAddress(receiver);
if (TypeCasts.addressToBytes32(dstReceiver) != receiver) {
revert MessageBus__NotEVMReceiver(receiver);
}
uint64 cachedNonce = nonce++;
// Note: we are using the internal nonce here to generate the unique message ID.
// This is used for tracking purposes and is not used for replay protection.
// Instead, we rely on the Interchain Client to provide replay protection.
bytes memory encodedLegacyMsg = LegacyMessageLib.encodeLegacyMessage({
srcSender: msg.sender,
dstReceiver: dstReceiver,
srcNonce: cachedNonce,
message: message
});
_sendToLinkedApp({
dstChainId: dstChainId,
messageFee: msg.value,
options: _icOptionsV1(options),
message: encodedLegacyMsg
});
emit MessageSent({
sender: msg.sender,
srcChainID: block.chainid,
receiver: receiver,
dstChainId: dstChainId,
message: message,
nonce: cachedNonce,
options: options,
fee: msg.value,
messageId: keccak256(encodedLegacyMsg)
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sendMessage function in the MessageBus contract correctly implements the logic for sending messages across chains. However, the static analysis tool flagged a potential reentrancy vulnerability due to the external call in _sendToLinkedApp followed by an event emission.

Consider using the Checks-Effects-Interactions pattern to mitigate potential reentrancy attacks. Ensure that all state changes are completed before calling external contracts and emitting events.

-        _sendToLinkedApp({
+        emit MessageSent({
+            sender: msg.sender,
+            srcChainID: block.chainid,
+            receiver: receiver,
+            dstChainId: dstChainId,
+            message: message,
+            nonce: cachedNonce,
+            options: options,
+            fee: msg.value,
+            messageId: keccak256(encodedLegacyMsg)
+        });
+        _sendToLinkedApp({

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
function sendMessage(
bytes32 receiver,
uint256 dstChainId,
bytes calldata message,
bytes calldata options
)
external
payable
{
address dstReceiver = TypeCasts.bytes32ToAddress(receiver);
if (TypeCasts.addressToBytes32(dstReceiver) != receiver) {
revert MessageBus__NotEVMReceiver(receiver);
}
uint64 cachedNonce = nonce++;
// Note: we are using the internal nonce here to generate the unique message ID.
// This is used for tracking purposes and is not used for replay protection.
// Instead, we rely on the Interchain Client to provide replay protection.
bytes memory encodedLegacyMsg = LegacyMessageLib.encodeLegacyMessage({
srcSender: msg.sender,
dstReceiver: dstReceiver,
srcNonce: cachedNonce,
message: message
});
_sendToLinkedApp({
dstChainId: dstChainId,
messageFee: msg.value,
options: _icOptionsV1(options),
message: encodedLegacyMsg
});
emit MessageSent({
sender: msg.sender,
srcChainID: block.chainid,
receiver: receiver,
dstChainId: dstChainId,
message: message,
nonce: cachedNonce,
options: options,
fee: msg.value,
messageId: keccak256(encodedLegacyMsg)
});
}
function sendMessage(
bytes32 receiver,
uint256 dstChainId,
bytes calldata message,
bytes calldata options
)
external
payable
{
address dstReceiver = TypeCasts.bytes32ToAddress(receiver);
if (TypeCasts.addressToBytes32(dstReceiver) != receiver) {
revert MessageBus__NotEVMReceiver(receiver);
}
uint64 cachedNonce = nonce++;
// Note: we are using the internal nonce here to generate the unique message ID.
// This is used for tracking purposes and is not used for replay protection.
// Instead, we rely on the Interchain Client to provide replay protection.
bytes memory encodedLegacyMsg = LegacyMessageLib.encodeLegacyMessage({
srcSender: msg.sender,
dstReceiver: dstReceiver,
srcNonce: cachedNonce,
message: message
});
emit MessageSent({
sender: msg.sender,
srcChainID: block.chainid,
receiver: receiver,
dstChainId: dstChainId,
message: message,
nonce: cachedNonce,
options: options,
fee: msg.value,
messageId: keccak256(encodedLegacyMsg)
});
_sendToLinkedApp({
dstChainId: dstChainId,
messageFee: msg.value,
options: _icOptionsV1(options),
message: encodedLegacyMsg
});
}

Comment on lines +87 to +113
function _receiveMessage(
uint256 srcChainId,
bytes32, // sender
uint256, // dbNonce
uint64, // entryIndex
bytes calldata encodedLegacyMsg
)
internal
override
{
(address srcSender, address dstReceiver, uint64 srcNonce, bytes memory message) =
LegacyMessageLib.decodeLegacyMessage(encodedLegacyMsg);
// Note: we rely on the Interchain Client to provide replay protection.
ILegacyReceiver(dstReceiver).executeMessage({
srcAddress: TypeCasts.addressToBytes32(srcSender),
srcChainId: srcChainId,
message: message,
executor: msg.sender
});
emit Executed({
messageId: keccak256(encodedLegacyMsg),
status: TxStatus.Success,
dstAddress: dstReceiver,
srcChainId: uint64(srcChainId),
srcNonce: srcNonce
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _receiveMessage function handles the receipt of messages, invoking the executeMessage function on the destination receiver. The static analysis tool flagged a potential reentrancy vulnerability here as well.

To mitigate potential reentrancy attacks in _receiveMessage, ensure that all state changes and validations occur before making external calls.
Consider reordering operations or using mutexes to prevent reentrancy if state changes are required after the external call.

@@ -0,0 +1,119 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Solidity version specified (0.8.20) is flagged as too recent to be trusted. While newer versions often include important fixes and improvements, they might also introduce new, undiscovered issues.

Consider using a more widely adopted and tested version of Solidity, such as 0.8.18, unless specific features or fixes from 0.8.20 are required for this contract.

- pragma solidity 0.8.20;
+ pragma solidity 0.8.18;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity 0.8.20;
pragma solidity 0.8.18;

Comment on lines +87 to +119
function getExecutionFee(
uint256 dstChainId,
uint256 txPayloadSize,
bytes memory options
)
public
view
virtual
returns (uint256 executionFee)
{
address cachedGasOracle = gasOracle();
if (cachedGasOracle == address(0)) {
revert SynapseExecutionService__GasOracleNotSet();
}
// TODO: the "exact version" check should be generalized
(uint8 version,) = OptionsLib.decodeVersionedOptions(options);
if (version > OptionsLib.OPTIONS_V1) {
revert SynapseExecutionService__OptionsVersionNotSupported(version);
}
OptionsV1 memory optionsV1 = OptionsLib.decodeOptionsV1(options);
executionFee = IGasOracle(cachedGasOracle).estimateTxCostInLocalUnits({
remoteChainId: dstChainId,
gasLimit: optionsV1.gasLimit,
calldataSize: txPayloadSize
});
if (optionsV1.gasAirdrop > 0) {
executionFee += IGasOracle(cachedGasOracle).convertRemoteValueToLocalUnits({
remoteChainId: dstChainId,
value: optionsV1.gasAirdrop
});
}
executionFee += executionFee * globalMarkup() / WAD;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getExecutionFee function calculates the execution fee based on the destination chain ID, transaction payload size, and options. However, the static analysis tool flagged an unused return value in the decodeVersionedOptions call.

Ensure that all returned values from function calls are used appropriately or explicitly ignored if not needed. This helps in avoiding potential bugs and makes the code more readable.

-        (uint8 version,) = OptionsLib.decodeVersionedOptions(options);
+        (uint8 version, ) = OptionsLib.decodeVersionedOptions(options);
+        require(version <= OptionsLib.OPTIONS_V1, "Unsupported options version");

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
function getExecutionFee(
uint256 dstChainId,
uint256 txPayloadSize,
bytes memory options
)
public
view
virtual
returns (uint256 executionFee)
{
address cachedGasOracle = gasOracle();
if (cachedGasOracle == address(0)) {
revert SynapseExecutionService__GasOracleNotSet();
}
// TODO: the "exact version" check should be generalized
(uint8 version,) = OptionsLib.decodeVersionedOptions(options);
if (version > OptionsLib.OPTIONS_V1) {
revert SynapseExecutionService__OptionsVersionNotSupported(version);
}
OptionsV1 memory optionsV1 = OptionsLib.decodeOptionsV1(options);
executionFee = IGasOracle(cachedGasOracle).estimateTxCostInLocalUnits({
remoteChainId: dstChainId,
gasLimit: optionsV1.gasLimit,
calldataSize: txPayloadSize
});
if (optionsV1.gasAirdrop > 0) {
executionFee += IGasOracle(cachedGasOracle).convertRemoteValueToLocalUnits({
remoteChainId: dstChainId,
value: optionsV1.gasAirdrop
});
}
executionFee += executionFee * globalMarkup() / WAD;
}
function getExecutionFee(
uint256 dstChainId,
uint256 txPayloadSize,
bytes memory options
)
public
view
virtual
returns (uint256 executionFee)
{
address cachedGasOracle = gasOracle();
if (cachedGasOracle == address(0)) {
revert SynapseExecutionService__GasOracleNotSet();
}
// TODO: the "exact version" check should be generalized
(uint8 version, ) = OptionsLib.decodeVersionedOptions(options);
require(version <= OptionsLib.OPTIONS_V1, "Unsupported options version");
OptionsV1 memory optionsV1 = OptionsLib.decodeOptionsV1(options);
executionFee = IGasOracle(cachedGasOracle).estimateTxCostInLocalUnits({
remoteChainId: dstChainId,
gasLimit: optionsV1.gasLimit,
calldataSize: txPayloadSize
});
if (optionsV1.gasAirdrop > 0) {
executionFee += IGasOracle(cachedGasOracle).convertRemoteValueToLocalUnits({
remoteChainId: dstChainId,
value: optionsV1.gasAirdrop
});
}
executionFee += executionFee * globalMarkup() / WAD;
}

Comment on lines +62 to +67
function payloadSize(uint256 optionsLen, uint256 messageLen) internal pure returns (uint256) {
// 8 fields * 32 bytes (6 values for static, 2 offsets for dynamic) + 2 * 32 bytes (lengths for dynamic) = 320
// abi.encode() also prepends the global offset (which is always 0x20) if there's a dynamic field, making it 352
// Both options and message are dynamic fields, which are padded up to 32 bytes
return 352 + optionsLen.roundUpToWord() + messageLen.roundUpToWord();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new payloadSize function provides a way to calculate the payload size of an interchain transaction. This is a critical addition for accurately estimating transaction costs. Ensure that this function is covered by unit tests to validate its correctness across a range of input values.

+ // TODO: Add unit tests for payloadSize function

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
function payloadSize(uint256 optionsLen, uint256 messageLen) internal pure returns (uint256) {
// 8 fields * 32 bytes (6 values for static, 2 offsets for dynamic) + 2 * 32 bytes (lengths for dynamic) = 320
// abi.encode() also prepends the global offset (which is always 0x20) if there's a dynamic field, making it 352
// Both options and message are dynamic fields, which are padded up to 32 bytes
return 352 + optionsLen.roundUpToWord() + messageLen.roundUpToWord();
}
function payloadSize(uint256 optionsLen, uint256 messageLen) internal pure returns (uint256) {
// 8 fields * 32 bytes (6 values for static, 2 offsets for dynamic) + 2 * 32 bytes (lengths for dynamic) = 320
// abi.encode() also prepends the global offset (which is always 0x20) if there's a dynamic field, making it 352
// Both options and message are dynamic fields, which are padded up to 32 bytes
// TODO: Add unit tests for payloadSize function
return 352 + optionsLen.roundUpToWord() + messageLen.roundUpToWord();
}

@@ -0,0 +1,146 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Solidity version specified (0.8.20) is flagged as too recent to be trusted. While newer versions often include important fixes and improvements, they might also introduce new, undiscovered issues.

Consider using a more widely adopted and tested version of Solidity, such as 0.8.18, unless specific features or fixes from 0.8.20 are required for this contract.

- pragma solidity 0.8.20;
+ pragma solidity 0.8.18;

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
pragma solidity 0.8.20;
pragma solidity 0.8.18;

@aureliusbtc aureliusbtc merged commit 102d27d into fe-release Mar 29, 2024
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2-reviewers go Pull requests that update Go code M-ci Module: CI M-contracts Module: Contracts M-synapse-interface size/l
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants