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

Feat/basic order contract #1072

Merged
merged 26 commits into from
Nov 15, 2024
Merged

Feat/basic order contract #1072

merged 26 commits into from
Nov 15, 2024

Conversation

mn13
Copy link
Contributor

@mn13 mn13 commented Nov 14, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced the BasicOrder smart contract for managing order execution based on price conditions.
    • Added OrderFactory contract to facilitate the creation and management of order contracts.
    • Implemented MockSlinkyPrecompile and MockWardenPrecompile contracts for testing purposes.
  • Improvements

    • Updated build and test scripts for better source path specification and execution parameters.
    • Added new mappings for precompiled contracts.
    • Revised documentation to reflect changes in build and test commands.
  • Bug Fixes

    • Removed deprecated contracts and tests to streamline functionality.
  • Tests

    • Added comprehensive tests for the BasicOrder contract to ensure proper functionality and state validation.

Copy link
Contributor

coderabbitai bot commented Nov 14, 2024

📝 Walkthrough
📝 Walkthrough

Walkthrough

The pull request includes significant changes to the @wardenprotocol/orders project. Key modifications involve the reintroduction of dependencies and updates to build and test scripts in package.json. New precompile mappings are added in remappings.txt. Several Solidity contracts are introduced, including BasicOrder, OrderFactory, and associated types in Types.sol, while existing contracts like Deploy and Foo are removed. Additionally, mock contracts for testing purposes are created, and a test suite for BasicOrder is established.

Changes

File Path Change Summary
solidity/orders/package.json - Dependency reintroduced: @openzeppelin/contracts
- Updated build command
- Modified test command with --via-ir
solidity/orders/remappings.txt - Added new mappings: precompile-common, precompile-warden, precompile-slinky, @openzeppelin/contracts, forge-std
solidity/orders/script/Deploy.s.sol - Contract removed: Deploy
solidity/orders/src/BasicOrder.sol - Contract added: BasicOrder
- Added multiple methods for order execution and management
solidity/orders/src/Foo.sol - Contract removed: Foo
solidity/orders/src/IExecution.sol - Interface added: IExecution
- Added methods for execution logic
solidity/orders/src/OrderFactory.sol - Contract added: OrderFactory
- Added order creation functionality and registry management
solidity/orders/src/Types.sol - Library added: Types
- Added various data structures and enumerations for order management
solidity/orders/test/BasicOrder.t.sol - Contract added: BasicOrderTest
- Established test framework for BasicOrder functionality
solidity/orders/test/Foo.t.sol - Contract removed: FooTest
solidity/orders/test/mocks/MockSlinkyPrecompile.sol - Contract added: MockSlinkyPrecompile
- Functions for price management
solidity/orders/test/mocks/MockWardenPrecompile.sol - Contract added: MockWardenPrecompile
- Functions for key management

Possibly related PRs

  • Added slinky precompile #975: The addition of the Slinky precompile is relevant as it introduces new functionality that may interact with the changes made in the main PR regarding the @openzeppelin/contracts dependency and the new BasicOrder contract.
  • Migrate to foundry  #1040: The migration to Foundry aligns with the updates in the main PR, particularly in the context of modifying build and test commands in the package.json.
  • Automated Orders: Scheduler #1069: The changes related to the Scheduler may connect with the overall architecture and functionality introduced in the main PR, especially if they involve the management of orders or interactions with the blockchain.

Suggested labels

basic-automated-orders, protocol

Suggested reviewers

  • backsapc
  • jjheywood
  • artur-abliazimov

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>, please review it.
    • 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @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.
    • @coderabbitai help me debug CodeRabbit configuration file.

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 using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

This was linked to issues Nov 14, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 20

🧹 Outside diff range and nitpick comments (14)
solidity/orders/package.json (1)

16-16: Consider the implications of --via-ir flag

Adding the --via-ir flag enables the IR-based pipeline in the Solidity compiler, which can provide better optimization but may increase compilation time. This is a good practice for production builds but consider making it configurable for development.

Consider adding a separate script for development testing without --via-ir:

 "scripts": {
   "test": "forge test --via-ir",
+  "test:dev": "forge test",
   "test:coverage": "forge coverage",
solidity/orders/test/mocks/MockWardenPrecompile.sol (2)

1-5: Consider relaxing the Solidity version constraint

The version constraint >=0.8.25 <0.9.0 is very recent and might cause compatibility issues. Consider using a more established version like ^0.8.0 unless there are specific features from 0.8.25 that are required.


29-31: Enhance addKey implementation

The function should emit an event when updating the key status for better testability and observability.

     function addKey(uint64 keyId, bool isGood) external {
         goodKeys[keyId] = isGood;
+        emit KeyStatusUpdated(keyId, isGood);
     }
solidity/orders/test/mocks/MockSlinkyPrecompile.sol (2)

1-4: Consider relaxing the Solidity version constraint

The version constraint >=0.8.25 <0.9.0 is very narrow and requires a recent compiler version. Since this is a mock contract for testing, consider relaxing it to ^0.8.0 unless specific 0.8.25 features are needed.

-pragma solidity >=0.8.25 <0.9.0;
+pragma solidity ^0.8.0;

36-42: Enhance setPrice with validation and events

Add price validation and emit an event for better test observability.

+    event PriceSet(string base, string quote, uint256 price);
+
     function setPrice(
         string calldata base,
         string calldata quote,
         uint256 price
     ) external {
+        if (bytes(base).length == 0 || bytes(quote).length == 0) {
+            revert InvalidInput();
+        }
         prices[base][quote] = price;
+        emit PriceSet(base, quote, price);
     }
solidity/orders/src/Types.sol (2)

24-27: Consider adding EQUAL condition and documentation

The PriceCondition enum could benefit from additional conditions and documentation.

Consider:

+/// @notice Defines price comparison conditions for order execution
 enum PriceCondition {
+    /// @notice Less than or equal to
     LTE,
+    /// @notice Greater than or equal to
     GTE,
+    /// @notice Exactly equal to
+    EQUAL
 }

44-48: Add field documentation and consider gas parameters

The struct lacks documentation explaining the purpose of each field and when they should be used.

Add NatSpec documentation:

+/// @notice Transaction fields defined by the order creator
 struct CreatorDefinedTxFields {
+    /// @notice Amount of native tokens to send with the transaction
     uint256 value;
+    /// @notice Target chain ID for the transaction
     uint256 chainId;
+    /// @notice Destination address for the transaction
     address to;
 }
solidity/orders/test/BasicOrder.t.sol (2)

137-143: Follow consistent naming conventions

Function names should follow a consistent convention. Current mix of camelCase and snake_case in test names makes the code less readable.

-    function test_basicOrderRevertWhenConditionNotMet() public {
+    function test_BasicOrder_RevertWhenConditionNotMet() public {

145-155: Track TODOs and improve test coverage

The commented-out test cases indicate missing coverage for important scenarios:

  1. Oracle integration tests
  2. Unauthorized access tests
  3. Successful execution tests

Consider creating GitHub issues to track these pending test implementations.

Would you like me to help create GitHub issues to track these missing test cases?

solidity/orders/src/OrderFactory.sol (1)

45-45: Typo in comment: correct 'regisry' to 'registry'

There is a typographical error in the comment. 'regisry' should be corrected to 'registry'.

Apply this diff to fix the typo:

- // TODO: register in regisry
+ // TODO: register in registry
solidity/orders/src/IExecution.sol (4)

47-50: Typographical error in Natspec comment

The Natspec comment for setByAIService has a typo. The word "whenever" should be "whether" to accurately convey the intended meaning.

Suggested fix:

         * @param data Data from AI service.
-        * @return success A boolean value indicating whenever data was processed correctly.
+        * @return success A boolean value indicating whether data was processed correctly.

37-38: Clarify Natspec comment for 'calledByScheduler' function

The Natspec comment for calledByScheduler is ambiguous and could be clearer.

Suggested revision:

/**
-         * @dev Indicates if this contract intended to be called by scheduler.
+         * @dev Indicates whether the contract was called by the scheduler.

42-43: Clarify Natspec comment for 'calledByAIService' function

The Natspec comment for calledByAIService is ambiguous and could be improved for clarity.

Suggested revision:

/**
-         * @dev Indicates if this contract intended to be called by AI service.
+         * @dev Indicates whether the contract was called by the AI service.

54-54: Improve Natspec comment for 'isExecuted' function

The Natspec comment for isExecuted can be rephrased for better clarity.

Suggested revision:

/**
-         * @dev Indicates if execution was executed already.
+         * @dev Indicates whether the execution has already occurred.
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 13b597d and a55cb05.

📒 Files selected for processing (12)
  • solidity/orders/package.json (1 hunks)
  • solidity/orders/remappings.txt (1 hunks)
  • solidity/orders/script/Deploy.s.sol (0 hunks)
  • solidity/orders/src/BasicOrder.sol (1 hunks)
  • solidity/orders/src/Foo.sol (0 hunks)
  • solidity/orders/src/IExecution.sol (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/src/Types.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
  • solidity/orders/test/Foo.t.sol (0 hunks)
  • solidity/orders/test/mocks/MockSlinkyPrecompile.sol (1 hunks)
  • solidity/orders/test/mocks/MockWardenPrecompile.sol (1 hunks)
💤 Files with no reviewable changes (3)
  • solidity/orders/script/Deploy.s.sol
  • solidity/orders/src/Foo.sol
  • solidity/orders/test/Foo.t.sol
✅ Files skipped from review due to trivial changes (1)
  • solidity/orders/remappings.txt
🔇 Additional comments (6)
solidity/orders/package.json (2)

11-11: Verify the src directory specification in build command

The build command now explicitly specifies the src directory. While this is more precise, ensure all contract files are within this directory structure.

#!/bin/bash
# Description: Verify all Solidity files are in the correct directory

# List all Solidity files and their locations
echo "Checking Solidity file locations..."
fd -e sol --exclude "test/" --exclude "script/"

# Specifically check if any contracts exist outside src/
echo "Checking for contracts outside src/..."
fd -e sol --exclude "test/" --exclude "script/" --exclude "src/"

1-10: ⚠️ Potential issue

Verify the removal of @openzeppelin/contracts dependency

The removal of @openzeppelin/contracts is concerning since this PR introduces new contract code. OpenZeppelin provides critical security-focused implementations and is typically essential for smart contract development.

solidity/orders/test/mocks/MockSlinkyPrecompile.sol (1)

7-8: LGTM!

The nested mapping is well-structured for currency pair price storage with appropriate visibility.

solidity/orders/src/Types.sol (1)

1-2: Consider broadening the Solidity version constraint

The version constraint >=0.8.25 <0.9.0 is very narrow and requires a very recent Solidity version. This might cause compatibility issues with other contracts or development tools that haven't been updated to support 0.8.25 yet.

Consider using a more flexible range like ^0.8.0 unless there are specific features from 0.8.25 that are required.

solidity/orders/test/BasicOrder.t.sol (1)

2-2: Verify Solidity version compatibility

The specified Solidity version (>=0.8.25) is very recent and might not be widely supported yet. Consider if a lower minimum version would suffice for your needs while maintaining better compatibility.

✅ Verification successful

Solidity version constraint is consistent with project standards

The version constraint >=0.8.25 <0.9.0 is consistently used across all contracts in the solidity/orders/ directory, which is the main project scope. The precompiles interfaces use a lower version (>=0.8.18), but this is appropriate as they are external interfaces.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if other contracts in the project use different Solidity versions
rg -g "*.sol" "pragma solidity" 

Length of output: 831

solidity/orders/src/IExecution.sol (1)

30-34: Verify the necessity of including both 'gasPrice' and EIP-1559 parameters

The execute function includes parameters for gasPrice, maxPriorityFeePerGas, and maxFeePerGas. With EIP-1559 implemented, gasPrice is generally replaced by maxPriorityFeePerGas and maxFeePerGas. Please verify if all these parameters are necessary, or if gasPrice can be deprecated.

Run the following script to check the usage of gas parameters:

✅ Verification successful

Both gasPrice and EIP-1559 parameters are necessary for backward compatibility

The codebase shows that both legacy gasPrice and EIP-1559 parameters (maxPriorityFeePerGas, maxFeePerGas) are actively used across different components:

  • The Solidity contracts use all parameters in their execution flow (see BasicOrder.sol, Types.sol)
  • The frontend components (spaceward/src/features/modals) handle both types of gas parameters
  • Backend services support both transaction types (see warden/x/warden/types/v1beta2/sign_method_handler_ethereum.go)

This dual support is important for compatibility with both pre and post EIP-1559 networks, making it a necessary design choice rather than a redundancy.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if 'gasPrice' is required alongside EIP-1559 parameters.

# Search for 'gasPrice' usage in the codebase
rg 'gasPrice' --type solidity

# Search for 'maxPriorityFeePerGas' and 'maxFeePerGas' usage
rg 'maxPriorityFeePerGas' --type solidity
rg 'maxFeePerGas' --type solidity

Length of output: 204


Script:

#!/bin/bash
# Description: Verify if 'gasPrice' is required alongside EIP-1559 parameters.

# Search for 'gasPrice' usage in the codebase
rg "gasPrice"

# Search for 'maxPriorityFeePerGas' and 'maxFeePerGas' usage
rg "maxPriorityFeePerGas"
rg "maxFeePerGas"

# Search for any implementations of the execute function
ast-grep --pattern 'function execute($$$) $$$'

Length of output: 4454

Comment on lines +8 to +9
mapping(uint64 keyId => KeyResponse keyResponse) private keys;
mapping(uint64 keyId => bool isGood) private goodKeys;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add events for state changes and implement keys mapping

  1. The keys mapping is declared but never written to, making keyById always return empty values.
  2. Consider adding events for state changes in addKey for better observability.
 contract MockWardenPrecompile {
     mapping(uint64 keyId => KeyResponse keyResponse) private keys;
     mapping(uint64 keyId => bool isGood) private goodKeys;
+    
+    event KeyStatusUpdated(uint64 indexed keyId, bool isGood);
+    event KeyAdded(uint64 indexed keyId, KeyResponse keyResponse);
+    
+    function setKey(uint64 keyId, KeyResponse calldata response) external {
+        keys[keyId] = response;
+        emit KeyAdded(keyId, response);
+    }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines 11 to 31
function keyById(uint64 id, int32[] calldata) external view returns (KeyResponse memory key) {
return keys[id];
}

function newSignRequest(
uint64 keyId,
bytes calldata,
bytes[] calldata,
bytes calldata,
Types.Coin[] calldata,
uint64,
uint64,
string calldata,
string calldata
) external view returns (bool isGood) {
isGood = goodKeys[keyId];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve mock implementation accuracy

  1. keyById should probably revert for non-existent keys to better simulate the real precompile behavior.
  2. newSignRequest ignores most parameters, which might not accurately represent the real implementation's validation logic.
-    function keyById(uint64 id, int32[] calldata) external view returns (KeyResponse memory key) {
-        return keys[id];
+    function keyById(uint64 id, int32[] calldata) external view returns (KeyResponse memory key) {
+        key = keys[id];
+        require(key.pubKey.length > 0, "Key not found");
+        return key;
     }
📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function keyById(uint64 id, int32[] calldata) external view returns (KeyResponse memory key) {
return keys[id];
}
function newSignRequest(
uint64 keyId,
bytes calldata,
bytes[] calldata,
bytes calldata,
Types.Coin[] calldata,
uint64,
uint64,
string calldata,
string calldata
) external view returns (bool isGood) {
isGood = goodKeys[keyId];
}
function keyById(uint64 id, int32[] calldata) external view returns (KeyResponse memory key) {
key = keys[id];
require(key.pubKey.length > 0, "Key not found");
return key;
}
function newSignRequest(
uint64 keyId,
bytes calldata,
bytes[] calldata,
bytes calldata,
Types.Coin[] calldata,
uint64,
uint64,
string calldata,
string calldata
) external view returns (bool isGood) {
isGood = goodKeys[keyId];
}

Comment on lines 4 to 7
import {IWarden, KeyResponse} from "precompile-warden/IWarden.sol";
import {Types} from "precompile-common/Types.sol";

contract MockWardenPrecompile {
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Mock implementation is incomplete

The MockWardenPrecompile contract only implements 3 methods (keyById, newSignRequest, and addKey) out of the 29 methods defined in the IWarden interface. This significant gap in implementation suggests that:

  • The mock is likely implementing only the minimal functionality needed for specific test cases
  • Many interface methods are not being tested through this mock
  • The mock includes a non-interface method (addKey) which appears to be test-specific

Key missing methods include:

  • Critical keychain management: addKeychainAdmin, removeKeychainAdmin, newKeychain
  • Space management: newSpace, addSpaceOwner, updateSpace
  • Request handling: fulfilKeyRequest, rejectKeyRequest, fulfilSignRequest
  • Query methods: allKeys, spaces, keychains
🔗 Analysis chain

Verify interface implementation completeness

Let's verify if this mock implements all necessary methods from the IWarden interface.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find and compare interface methods with mock implementation
ast-grep --pattern 'interface IWarden {
  $$$
  function $name($$$) $$$;
  $$$
}'

Length of output: 83


Script:

#!/bin/bash
# Let's first check if we can find the IWarden interface file
fd IWarden.sol

# Then let's examine both the interface and mock implementation
echo "=== IWarden Interface ==="
rg "function" -A 1 $(fd IWarden.sol) || true

echo -e "\n=== MockWardenPrecompile Implementation ==="
rg "function" -A 1 solidity/orders/test/mocks/MockWardenPrecompile.sol || true

Length of output: 2325

Comment on lines 14 to 20
if(price == 0) {
string memory s1 = string.concat("no price / nonce reported for CurrencyPair: ", base);
string memory s2 = string.concat(s1, "/");
string memory s3 = string.concat(s2, quote);
string memory s4 = string.concat(s3, ", the module is not tracking this CurrencyPair");
revert(s4);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Optimize error message construction

The current string concatenation approach is gas-inefficient. Consider using a more efficient error handling mechanism.

-                string memory s1 = string.concat("no price / nonce reported for CurrencyPair: ", base);
-                string memory s2 = string.concat(s1, "/");
-                string memory s3 = string.concat(s2, quote);
-                string memory s4 = string.concat(s3, ", the module is not tracking this CurrencyPair");
-                revert(s4);
+                revert PriceNotFound(base, quote);

Add this custom error at the contract level:

error PriceNotFound(string base, string quote);

Comment on lines 9 to 29
function getPrice(
string calldata base,
string calldata quote
) external view returns (GetPriceResponse memory response) {
uint256 price = prices[base][quote];
if(price == 0) {
string memory s1 = string.concat("no price / nonce reported for CurrencyPair: ", base);
string memory s2 = string.concat(s1, "/");
string memory s3 = string.concat(s2, quote);
string memory s4 = string.concat(s3, ", the module is not tracking this CurrencyPair");
revert(s4);
}

QuotePrice memory quotePrice = QuotePrice({
blockHeight: 0,
blockTimestamp: 0,
price: price
});

response = GetPriceResponse ({
id: 0,
nonce: 0,
decimals: 9,
price: quotePrice
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add input validation and consider parameterizing decimals

The function needs additional validation and improvements:

  1. Missing validation for empty base/quote strings
  2. Hardcoded decimals value should be configurable
+    uint8 public immutable decimals;
+
+    constructor(uint8 _decimals) {
+        decimals = _decimals;
+    }
+
     function getPrice(
         string calldata base,
         string calldata quote
     ) external view returns (GetPriceResponse memory response) {
+        if (bytes(base).length == 0 || bytes(quote).length == 0) {
+            revert InvalidInput();
+        }
         // ... rest of the function ...
         response = GetPriceResponse ({
             id: 0,
             nonce: 0,
-            decimals: 9,
+            decimals: decimals,
             price: quotePrice
         });
     }

Committable suggestion skipped: line range outside the PR's diff.

solidity/orders/src/OrderFactory.sol Outdated Show resolved Hide resolved
solidity/orders/src/IExecution.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
Copy link

vercel bot commented Nov 14, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
warden-help-center ⬜️ Ignored (Inspect) Visit Preview Nov 15, 2024 10:29am

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (3)
solidity/orders/package.json (1)

19-19: Consider the tradeoffs of enabling IR-based codegen

Adding the --via-ir flag enables the IR-based codegen pipeline, which can produce more optimized bytecode but may increase compilation time. This is a good optimization for production builds, but consider making it configurable for development workflows.

Consider splitting the test script into development and production variants:

-    "test": "forge test --via-ir",
+    "test": "forge test",
+    "test:prod": "forge test --via-ir",
solidity/orders/test/BasicOrder.t.sol (2)

39-71: Refactor beforeTestSetup Function to Reduce Code Duplication

The beforeTestSetup function contains repetitive code blocks for different test selectors. Consider refactoring to reduce duplication and enhance maintainability.

Apply this diff to refactor the function:

 function beforeTestSetup(
     bytes4 testSelector
 ) public pure returns (bytes[] memory beforeTestCalldata) {
     beforeTestCalldata = new bytes[](1);
-    if (testSelector == this.test_BasicOrder_StateBeforeExecution.selector) {
-        beforeTestCalldata[0] = abi.encodeWithSignature(
-            "test_BasicOrder_Create(bool,uint8)",
-            true,
-            Types.PriceCondition.LTE);
-    } else if (testSelector == this.test_basicOrderRevertWhenConditionNotMet.selector) {
-        beforeTestCalldata[0] = abi.encodeWithSignature(
-            "test_BasicOrder_Create(bool,uint8)",
-            true,
-            Types.PriceCondition.LTE);
-    } else if (testSelector == this.test_basicOrderRevertWhenUnauthorized.selector) {
-        beforeTestCalldata[0] = abi.encodeWithSignature(
-            "test_BasicOrder_Create(bool,uint8)",
-            true,
-            Types.PriceCondition.LTE);
-    } else if (testSelector == this.test_basicOrderExecuteWhenPriceMovesDown.selector) {
-        beforeTestCalldata[0] = abi.encodeWithSignature(
-            "test_BasicOrder_Create(bool,uint8)",
-            true,
-            Types.PriceCondition.LTE);
-    } else if (testSelector == this.test_basicOrderExecuteWhenPriceMovesUp.selector) {
-        beforeTestCalldata[0] = abi.encodeWithSignature(
-            "test_BasicOrder_Create(bool,uint8)",
-            true,
-            Types.PriceCondition.GTE);
-    }
+    uint8 priceCondition = Types.PriceCondition.LTE;
+    if (testSelector == this.test_basicOrderExecuteWhenPriceMovesUp.selector) {
+        priceCondition = Types.PriceCondition.GTE;
+    }
+    beforeTestCalldata[0] = abi.encodeWithSignature(
+        "test_BasicOrder_Create(bool,uint8)",
+        true,
+        priceCondition
+    );
 }

204-204: Use Meaningful Variables Instead of Magic Numbers in order.execute

In the calls to order.execute(1, 1, 1, 1, 1);, the arguments are all literal 1s. Consider defining variables or constants with meaningful names to improve code clarity and maintainability.

Also applies to: 223-223

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a55cb05 and e5920a6.

📒 Files selected for processing (6)
  • solidity/orders/package.json (1 hunks)
  • solidity/orders/remappings.txt (1 hunks)
  • solidity/orders/src/BasicOrder.sol (1 hunks)
  • solidity/orders/src/IExecution.sol (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • solidity/orders/src/BasicOrder.sol
  • solidity/orders/src/IExecution.sol
  • solidity/orders/src/OrderFactory.sol
🔇 Additional comments (5)
solidity/orders/remappings.txt (2)

1-2: LGTM: Standard dependency mappings are correctly configured

The mappings for @openzeppelin/contracts and forge-std are properly configured to point to their respective locations in node_modules.


3-5: Verify precompile paths and consider using environment variables

The precompile mappings use relative paths that point outside the project directory. Let's verify these paths exist and consider making them more maintainable.

Consider:

  1. Using environment variables for precompile paths to make them configurable
  2. Adding documentation about the required precompile structure
  3. Including validation in the build process to ensure precompiles exist
✅ Verification successful

Let me try a different approach to verify the paths by searching within the repository structure.


Relative paths in remappings.txt are correct and valid

The repository structure shows that the precompile directories (precompiles/common/, precompiles/warden/, precompiles/slinky/) exist at the correct locations relative to solidity/orders/remappings.txt. The paths in remappings.txt (../../precompiles/...) are valid and follow the standard Solidity remapping convention. Using environment variables is not necessary here as:

  • These are fixed paths relative to the project structure
  • Remappings are a standard Solidity/Foundry feature for import resolution
  • The paths are already maintainable within the monorepo context
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of precompile directories and their content

# Check if the precompile directories exist and contain Solidity files
for dir in common warden slinky; do
  echo "Checking precompiles/$dir:"
  if [ -d "../../precompiles/$dir" ]; then
    # List .sol files in the directory
    find "../../precompiles/$dir" -name "*.sol" -type f
  else
    echo "Directory not found: ../../precompiles/$dir"
  fi
done

Length of output: 719


Script:

#!/bin/bash
# Check the actual repository structure for precompiles
echo "Repository structure around precompiles:"
fd precompile
fd -t d slinky
fd -t d warden
fd -t d common

echo -e "\nChecking remappings.txt location and content:"
fd remappings.txt -x cat {}

Length of output: 1405

solidity/orders/package.json (2)

14-14: Verify the impact of src-specific build command

The build command now explicitly targets the src directory. While this is more specific, we should verify that no critical contract files exist outside the src directory.

#!/bin/bash
# Find all Solidity files outside src directory
echo "Solidity files outside src directory:"
fd -e sol -E "src/**"

# Check if there are any forge.toml or foundry.toml configurations that might be affected
fd "forge.toml|foundry.toml"

9-11: Verify OpenZeppelin Contracts version compatibility and security

The addition of @openzeppelin/contracts v5.0.1 is significant for smart contract security. Let's verify its stability and security status.

✅ Verification successful

OpenZeppelin Contracts v5.0.1 usage is appropriate and minimal

The dependency is being used appropriately in BasicOrder.sol for the ReentrancyGuard functionality, which is a critical security feature. Version 5.0.1 is a stable release, and the implementation shows minimal and focused usage of OpenZeppelin's battle-tested security contracts.

  • solidity/orders/src/BasicOrder.sol imports only the necessary ReentrancyGuard contract
  • The dependency has been consistently managed in the package.json with no concerning version changes
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for security advisories and latest versions
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "@openzeppelin/contracts") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

# Check if any contracts in the project use OpenZeppelin imports
rg -l "import.*@openzeppelin/contracts" --type sol

Length of output: 835


Script:

#!/bin/bash
# Check for OpenZeppelin imports and their usage
rg -l "@openzeppelin/contracts" solidity/orders/src/
rg "@openzeppelin/contracts" solidity/orders/src/ -A 2

# Check if there are any previous versions in package.json history
git log -p solidity/orders/package.json | grep -A 5 -B 5 "@openzeppelin/contracts"

Length of output: 1318

solidity/orders/test/BasicOrder.t.sol (1)

191-191: Verify Usage of vm.broadcast(address(0))

Broadcasting from address(0) is unusual and may not function as intended. Please verify whether broadcasting from the zero address is appropriate in this context.

Run the following script to check for unintended usage of address(0):

✅ Verification successful

vm.broadcast(address(0)) is correctly used in unauthorized access test

The usage of address(0) with vm.broadcast is intentional and appropriate in this context. It's part of a test function test_basicOrderRevertWhenUnauthorized() that verifies the contract correctly reverts when called by an unauthorized address. Using address(0) is a common practice to test unauthorized access, and it's properly combined with vm.expectRevert to verify the reversion behavior.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for instances of vm.broadcast(address(0)) in the codebase

# Test: Ensure that vm.broadcast is not used incorrectly with address(0).
rg 'vm\.broadcast\(address\(0\)\)'

Length of output: 107


Script:

#!/bin/bash
# Let's check the context around this broadcast to understand its usage
rg -B 5 -A 5 'vm\.broadcast\(address\(0\)\)' solidity/orders/test/BasicOrder.t.sol

Length of output: 432

address(bytes20(bytes("0xeE567Fe1712Faf6149d80dA1E6934E354124CfE3")));
address private constant RECEIVER = address(bytes20(bytes("0x18517Cb2779186B86b1F8947dFdB6078C1B9C9db")));

event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address orderContact);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Typographical Error in Event Declaration

The parameter name orderContact in the OrderCreated event should likely be orderContract.

Apply this diff to fix the typo:

-event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address orderContact);
+event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address orderContract);
📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address orderContact);
event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address orderContract);

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
solidity/orders/test/BasicOrder.t.sol (3)

63-63: Consider using a mock registry for clarity

Currently, the registry is set to address(this) as a placeholder. Using a dedicated mock registry contract can improve the clarity of the test setup and make future maintenance easier.


134-134: Make chainId configurable for flexibility

Using a hardcoded chainId (11_155_111) may cause issues when deploying or testing on different networks. Consider retrieving the chain ID dynamically using block.chainid or making it an input parameter to enhance flexibility.

Apply this diff to use the dynamic chain ID:

-                chainId: 11_155_111,
+                chainId: block.chainid,

151-156: Add assertions to enhance test robustness

Currently, the test_BasicOrder_StateBeforeExecution function checks several state variables. To improve test robustness, consider adding assertions to verify that the order cannot be executed and has not been executed, reinforcing the expected initial state.

Apply this diff to add more assertions:

         function test_BasicOrder_StateBeforeExecution() public {
+            assertFalse(order.canExecute(), "Order should not be executable before conditions are met");
+            assertFalse(order.isExecuted(), "Order should not be marked as executed");
             assert(order.calledByScheduler());
             assert(!order.calledByAIService());
         }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a55cb05 and 1c135c3.

📒 Files selected for processing (9)
  • solidity/orders/package.json (1 hunks)
  • solidity/orders/remappings.txt (1 hunks)
  • solidity/orders/src/BasicOrder.sol (1 hunks)
  • solidity/orders/src/IExecution.sol (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/src/Types.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
  • solidity/orders/test/mocks/MockSlinkyPrecompile.sol (1 hunks)
  • solidity/orders/test/mocks/MockWardenPrecompile.sol (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (7)
  • solidity/orders/package.json
  • solidity/orders/src/BasicOrder.sol
  • solidity/orders/src/IExecution.sol
  • solidity/orders/src/OrderFactory.sol
  • solidity/orders/src/Types.sol
  • solidity/orders/test/mocks/MockSlinkyPrecompile.sol
  • solidity/orders/test/mocks/MockWardenPrecompile.sol
🔇 Additional comments (2)
solidity/orders/remappings.txt (2)

3-5: Verify precompile paths exist

The precompile mappings reference paths in the parent directory. Let's verify these paths exist and contain the expected contracts.

✅ Verification successful

Precompile paths verified successfully

The remappings are correctly configured. All referenced precompile paths exist and contain the expected Solidity interface files:

  • precompile-common → precompiles/common/Types.sol
  • precompile-warden → precompiles/warden/IWarden.sol
  • precompile-slinky → precompiles/slinky/ISlinky.sol
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that precompile paths exist and contain Solidity contracts

# Check if the precompile directories exist and contain .sol files
for dir in "../../precompiles/common" "../../precompiles/warden" "../../precompiles/slinky"; do
  echo "Checking $dir:"
  if [ -d "$dir" ]; then
    echo "Directory exists"
    find "$dir" -name "*.sol" -type f
  else
    echo "Directory not found"
  fi
done

Length of output: 260


Script:

#!/bin/bash
# Let's try a different approach using fd to find the precompile directories
echo "Searching for precompile directories:"
fd -t d "precompiles"

echo -e "\nSearching for Solidity files in precompiles:"
fd -e sol . "precompiles"

Length of output: 366


1-2: External dependency mappings look good

The mappings for @openzeppelin/contracts and forge-std follow the standard convention.

✅ Verification successful

External dependency mappings are correctly configured

The remappings in solidity/orders/remappings.txt are properly set up and actively used in the codebase:

  • @openzeppelin/contracts/ is used for importing ReentrancyGuard in BasicOrder.sol
  • forge-std/ is used for importing Test in test files

The imports are consistent with the remapping paths and follow standard conventions for Foundry projects.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify @openzeppelin version compatibility

# Check package.json for @openzeppelin version
if [ -f "package.json" ]; then
  echo "OpenZeppelin version from package.json:"
  jq '.dependencies["@openzeppelin/contracts"]' package.json
fi

# Look for OpenZeppelin imports in Solidity files
echo "Files importing OpenZeppelin:"
rg -l '@openzeppelin/contracts' --type sol

Length of output: 260


Script:

#!/bin/bash
# Let's verify the dependencies and imports more thoroughly

# Check if package.json exists and its content
echo "Checking package.json:"
if [ -f "package.json" ]; then
    cat package.json
fi

# Check if node_modules/@openzeppelin exists
echo -e "\nChecking OpenZeppelin directory:"
ls -la node_modules/@openzeppelin 2>/dev/null || echo "OpenZeppelin directory not found"

# Check if node_modules/forge-std exists
echo -e "\nChecking forge-std directory:"
ls -la node_modules/forge-std 2>/dev/null || echo "forge-std directory not found"

# Search for Solidity files that might import these dependencies
echo -e "\nSearching for Solidity files:"
fd -e sol

# Check content of found Solidity files for imports
echo -e "\nChecking imports in Solidity files:"
fd -e sol -x cat {} \; 2>/dev/null

Length of output: 55095

solidity/orders/test/BasicOrder.t.sol Show resolved Hide resolved
Comment on lines +93 to +131
if (condition > 1) {
condition = 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance condition validation with stricter checks

The current condition check silently defaults to 0 when condition > 1. Consider using proper validation to ensure that only valid PriceCondition enums are accepted, and revert when an invalid condition is provided.

Apply this diff to improve the validation:

-        if (condition > 1) {
-            condition = 0;
-        }
+        require(condition <= uint8(Types.PriceCondition.GTE), "Invalid condition");
📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (condition > 1) {
condition = 0;
}
require(condition <= uint8(Types.PriceCondition.GTE), "Invalid condition");

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (6)
solidity/orders/README.md (3)

4-6: Add comma for better readability

The sentence structure would be clearer with a comma after "commands".

-Before using commands install dependencies with `yarn install`.
+Before using commands, install dependencies with `yarn install`.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~5-~5: Possible missing comma found.
Context: ...p contracts ### Commands Before using commands install dependencies with `yarn install...

(AI_HYDRA_LEO_MISSING_COMMA)


8-12: Add more context about the build process

The build command documentation could be more helpful by explaining what gets built and where the output is stored.

#### Build

```sh
yarn build

+This command builds the Solidity contracts and generates artifacts in the out directory.


---

`14-16`: **Enhance test documentation**

The test section would benefit from additional information about the test suite and available options.

```diff
#### Tests

```sh
yarn test

+This command runs the full test suite for all contracts. For running specific tests, you can use:
+
+sh +yarn test -m <test_function_name> # Run a specific test +yarn test --match-contract <contract_name> # Run tests for a specific contract +


</blockquote></details>
<details>
<summary>solidity/orders/src/OrderFactory.sol (1)</summary><blockquote>

`57-57`: **Fix typo in comment**

There's a typo in the comment: "regisry" should be "registry".



Apply this diff to fix the typo:

```diff
- // TODO: register in regisry
+ // TODO: register in registry
solidity/orders/test/BasicOrder.t.sol (2)

37-59: Refactor beforeTestSetup to reduce code duplication

The beforeTestSetup function contains repetitive code blocks when initializing beforeTestCalldata. Refactoring this function will improve maintainability and readability.

Apply this diff to refactor the function:

 function beforeTestSetup(bytes4 testSelector) public pure returns (bytes[] memory beforeTestCalldata) {
+    bytes memory encodedCalldata;
     if (testSelector == this.test_basicOrderExecuteWhenPriceMovesUp.selector) {
-        beforeTestCalldata = new bytes[](1);
-        beforeTestCalldata[0] =
-            abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.GTE);
+        encodedCalldata = abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.GTE);
     } else {
-        beforeTestCalldata = new bytes[](1);
-        beforeTestCalldata[0] =
-            abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.LTE);
+        encodedCalldata = abi.encodeWithSignature("test_BasicOrder_Create(bool,uint8)", true, Types.PriceCondition.LTE);
     }
+    beforeTestCalldata = new bytes[](1);
+    beforeTestCalldata[0] = encodedCalldata;
 }

177-179: Specify event parameters in vm.expectEmit for precise event verification

Currently, vm.expectEmit(false, false, false, false); is used before emitting the Executed event. This configuration does not check any topics or data. To ensure the test accurately verifies that the Executed event is emitted with the correct parameters, consider setting the appropriate flags to true.

For example, if you want to check that the event is emitted without caring about topics or data, you can omit vm.expectEmit. Otherwise, set at least one of the flags to true:

- vm.expectEmit(false, false, false, false);
+ vm.expectEmit(true, false, false, false);
  emit Executed();

Also applies to: 197-199

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 1c135c3 and 835eb32.

📒 Files selected for processing (5)
  • solidity/orders/.prettierignore (2 hunks)
  • solidity/orders/README.md (1 hunks)
  • solidity/orders/package.json (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • solidity/orders/.prettierignore
🚧 Files skipped from review as they are similar to previous changes (1)
  • solidity/orders/package.json
🧰 Additional context used
📓 Path-based instructions (1)
solidity/orders/README.md (1)

Pattern **/*.md: "Assess the documentation for misspellings, grammatical errors, missing documentation and correctness"

🪛 LanguageTool
solidity/orders/README.md

[uncategorized] ~5-~5: Possible missing comma found.
Context: ...p contracts ### Commands Before using commands install dependencies with `yarn install...

(AI_HYDRA_LEO_MISSING_COMMA)

🔇 Additional comments (3)
solidity/orders/src/OrderFactory.sol (1)

23-23: Typo in event parameter name orderContact

The parameter name orderContact in the OrderCreated event appears to be a typo. It should likely be orderContract to accurately represent the address of the created order contract.

solidity/orders/test/BasicOrder.t.sol (2)

61-89: Initialization in setUp function is appropriate

The setUp function correctly initializes the test environment, including deploying mock precompiles and setting up test data. This setup ensures that the tests run in a predictable environment.


85-85: Confirm the validity of the price pair

The price pair is set to { base: "ETH", quote: "DOGE" }. Ensure that DOGE is a valid and supported quote in your testing environment.

Run the following script to check the supported price pairs:

✅ Verification successful

DOGE is a valid quote currency in the test environment

The mock Slinky precompile implementation (MockSlinkyPrecompile.sol) uses a flexible mapping that can handle any base/quote pair, and the test suite successfully uses "DOGE" as a quote currency in multiple test cases:

  • The price pair is properly initialized in the test setup
  • Multiple test cases (test_basicOrderExecuteWhenPriceMovesDown, test_basicOrderExecuteWhenPriceMovesUp) successfully set and use ETH/DOGE prices
  • The mock precompile correctly handles price updates for this pair
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify if 'DOGE' is a supported quote currency in the mock precompile.

# Expected Result: 'DOGE' should be listed among the supported quotes.

# List supported quotes
ast-grep --pattern 'struct PricePair { base: $_; quote: $_; }' **/*.sol

Length of output: 131


Script:

#!/bin/bash
# Let's try a different approach to find price pair related structures and their usage
# First, let's find files that might contain price pair definitions
fd -e sol | xargs rg -l "PricePair|DOGE"

# Then let's look for any struct definitions or enums that might define supported currencies
fd -e sol | xargs rg "struct.*Price|enum.*Currency|DOGE" -A 5 -B 5

Length of output: 2534


Script:

#!/bin/bash
# Let's check the mock precompile implementation to see if it handles DOGE quotes
fd -e sol | xargs rg "mock.*Slinky|MockSlinky" -A 10 -B 10

# Also check for any test setup related to price pairs
fd -e sol | xargs rg "setUp.*mock.*Slinky|mock.*Price" -A 10 -B 10

Length of output: 15611

### Factory
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add content to empty sections

The "Order" and "Factory" sections are empty. These sections should include explanations of their respective components and usage examples.

Would you like me to help generate comprehensive documentation for these sections based on the contract implementations?

solidity/orders/src/OrderFactory.sol Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/OrderFactory.sol Outdated Show resolved Hide resolved
solidity/orders/src/OrderFactory.sol Show resolved Hide resolved
solidity/orders/src/OrderFactory.sol Outdated Show resolved Hide resolved
solidity/orders/src/OrderFactory.sol Outdated Show resolved Hide resolved
solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
@artur-abliazimov artur-abliazimov self-requested a review November 14, 2024 10:22
Copy link
Contributor

@artur-abliazimov artur-abliazimov left a comment

Choose a reason for hiding this comment

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

Accidentally chosen Approve =)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (9)
solidity/orders/src/IExecution.sol (3)

4-10: Add NatSpec documentation for the ExecutionData struct and its fields.

While the struct fields are well-organized and use appropriate types, adding documentation would improve code maintainability and integration experience.

+/// @notice Represents the data required for executing a transaction
 struct ExecutionData {
+    /// @notice The address initiating the execution
     address caller;
+    /// @notice The target address for the execution
     address to;
+    /// @notice The chain ID where the execution should occur
     uint256 chainId;
+    /// @notice The calldata for the execution
     bytes data;
+    /// @notice The amount of native tokens to send with the execution
     uint256 value;
 }

12-15: Add NatSpec documentation for the Caller enum.

The enum values would benefit from documentation explaining their roles and usage context.

+/// @notice Defines the types of entities that can initiate executions
 enum Caller {
+    /// @notice Represents the automated scheduler system
     Scheduler,
+    /// @notice Represents the AI-based execution service
     AI
 }

34-42: Enhance documentation for execute function parameters.

The gas-related parameters would benefit from more detailed documentation explaining their constraints and relationships.

     /**
      * @dev Creates action for new sign request from stored order data.
      * If action created successfully then emit Executed event.
      * @param nonce The key account nonce.
-     * @param gas gas parameter in eth transaction.
-     * @param gasPrice gasPrice parameter in eth transaction.
-     * @param maxPriorityFeePerGas maxPriorityFeePerGas parameter in eth transaction.
-     * @param maxFeePerGas maxFeePerGas parameter in eth transaction.
+     * @param gas The amount of gas to allocate for the transaction execution
+     * @param gasPrice The legacy gas price in wei (only used for legacy transactions)
+     * @param maxPriorityFeePerGas The maximum priority fee per gas in wei (EIP-1559)
+     * @param maxFeePerGas The maximum total fee per gas in wei (EIP-1559)
      * @return A boolean value indicating parameter action was created.
      */
solidity/orders/src/OrderFactory.sol (2)

14-17: Consider moving common errors to a separate file.

Following the existing review suggestion, consider creating a separate errors.sol file for common errors like InvalidRegistryAddress and InvalidSchedulerAddress, while keeping contract-specific errors like Unimplemented and UnsupportedOrder here.


78-78: Implement registry registration.

The TODO comment indicates missing functionality for registering the order in the registry.

Would you like me to help implement the registry registration functionality or create a GitHub issue to track this task?

solidity/orders/src/BasicOrder.sol (2)

25-25: Reorganize functions according to Solidity style guide

The contract should follow the recommended function ordering:

  1. constructor
  2. receive/fallback
  3. external
  4. public
  5. internal
  6. private

Consider reorganizing the functions in this order for better readability and maintainability.


165-174: Consider caching packed swap data

The executionData function repacks swap data on every call using _packSwapData(). This is inefficient for frequently accessed data.

Consider caching the packed data:

+    bytes private _cachedSwapData;
+
     function executionData() external view returns (ExecutionData memory data) {
-        bytes memory d = _packSwapData();
         data = ExecutionData({
             caller: _keyAddress,
             to: orderData.creatorDefinedTxFields.to,
             chainId: orderData.creatorDefinedTxFields.chainId,
             value: orderData.creatorDefinedTxFields.value,
-            data: d
+            data: _cachedSwapData
         });
     }
solidity/orders/test/BasicOrder.t.sol (2)

59-92: Consider making beforeTestSetup function private

The beforeTestSetup function is currently declared as public, but it appears to be used only internally within the test contract. Changing its visibility to private can improve encapsulation and prevent unintended external access.

Apply this diff to adjust the function visibility:

-function beforeTestSetup(bytes4 testSelector) public pure returns (bytes[] memory beforeTestCalldata) {
+function beforeTestSetup(bytes4 testSelector) private pure returns (bytes[] memory beforeTestCalldata) {

245-271: Consider making saveOrderData function private

The saveOrderData function is declared as public, but it seems to be used internally for setting up test data. Changing its visibility to private enhances encapsulation and aligns with best practices.

Apply this diff to adjust the function visibility:

-function saveOrderData() public {
+function saveOrderData() private {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 835eb32 and bc2d60d.

📒 Files selected for processing (4)
  • solidity/orders/src/BasicOrder.sol (1 hunks)
  • solidity/orders/src/IExecution.sol (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
🔇 Additional comments (10)
solidity/orders/src/IExecution.sol (2)

1-2: LGTM! Appropriate license and Solidity version constraints.

The file uses a specific version range that leverages recent Solidity security features while preventing compilation with potentially incompatible future versions.


54-54: Consider adding validation requirements for setByAIService.

The function should document any validation requirements or constraints for the input data to ensure proper integration.

solidity/orders/src/OrderFactory.sol (5)

1-7: LGTM! Well-structured imports and appropriate version constraints.

The pragma version is appropriately constrained, and imports are organized logically.


19-19: Fix typo in event parameter name.

The parameter name orderContact should be orderContract.


27-31: LGTM! Well-documented state variables.

The state variables are appropriately marked as public and well-documented with comments.


33-44: LGTM! Robust constructor with proper validations.

The constructor includes appropriate zero-address checks and proper initialization order.


46-61: Add input validation for order creation parameters.

As suggested in the past review, add validation to prevent creation of invalid orders.

solidity/orders/test/BasicOrder.t.sol (3)

55-57: Duplicate Comment: Consider making addresses configurable

The past review comment regarding hardcoded addresses for SEPOLIA_UNISWAP_V2_ROUTER and RECEIVER is still valid. Making these addresses configurable enhances test flexibility and prevents potential issues when testing on different networks.


129-131: Duplicate Comment: Improve condition validation

The previous suggestion to enhance condition validation is still applicable. Using a require statement for validation provides clearer error handling compared to silently defaulting the condition.


203-203: Duplicate Comment: Avoid using address(0) in vm.broadcast

The past comment about not using address(0) in vm.broadcast remains relevant. Using a specific unauthorized test address would simulate unauthorized access more effectively.

/**
* @dev Returns the list of intended callers.
*/
function callers() external returns (Caller[] memory callersList);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add view modifiers to state-reading functions.

These functions don't modify state and should be marked as view:

-    function callers() external returns (Caller[] memory callersList);
+    function callers() external view returns (Caller[] memory callersList);

-    function isExecuted() external returns (bool);
+    function isExecuted() external view returns (bool);

-    function executionData() external returns (ExecutionData memory executionData);
+    function executionData() external view returns (ExecutionData memory executionData);

Also applies to: 59-59, 65-65

Comment on lines 63 to 66
function changeScheduler(address _scheduler) public onlyOwner {
emit SchedulerChanged(scheduler, _scheduler);
scheduler = _scheduler;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add zero-address validation in changeScheduler.

The function should validate that the new scheduler address is not zero to maintain consistency with constructor checks.

 function changeScheduler(address _scheduler) public onlyOwner {
+    if (_scheduler == address(0)) {
+        revert InvalidSchedulerAddress();
+    }
     emit SchedulerChanged(scheduler, _scheduler);
     scheduler = _scheduler;
 }

Comment on lines +176 to +178
function setByAIService(bytes calldata) external pure returns (bool success) {
success = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement or remove placeholder AI service function

The setByAIService function appears to be a placeholder that always returns false. This could lead to confusion about the contract's capabilities.

Either implement the function properly or remove it if not needed. If it's intentionally disabled, add a comment explaining why:

-    function setByAIService(bytes calldata) external pure returns (bool success) {
-        success = false;
-    }
+    /// @dev AI service integration is not supported in basic orders
+    function setByAIService(bytes calldata) external pure returns (bool) {
+        revert("AI service integration not supported");
+    }
📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function setByAIService(bytes calldata) external pure returns (bool success) {
success = false;
}
/// @dev AI service integration is not supported in basic orders
function setByAIService(bytes calldata) external pure returns (bool) {
revert("AI service integration not supported");
}

Comment on lines 71 to 76
_wardenPrecompile = IWarden(IWARDEN_PRECOMPILE_ADDRESS);
KeyResponse memory keyResponse = _wardenPrecompile.keyById(_orderData.signRequestData.keyId, new int32[](0));
_keyAddress = address(bytes20(keccak256(keyResponse.key.publicKey)));

_slinkyPrecompile = ISlinky(ISLINKY_PRECOMPILE_ADDRESS);
_slinkyPrecompile.getPrice(_orderData.pricePair.base, _orderData.pricePair.quote);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for precompile contract calls

The constructor makes external calls to _wardenPrecompile and _slinkyPrecompile without handling potential failures. These calls could revert and make contract deployment impossible.

Add try-catch blocks or appropriate error handling:

-        KeyResponse memory keyResponse = _wardenPrecompile.keyById(_orderData.signRequestData.keyId, new int32[](0));
+        try _wardenPrecompile.keyById(_orderData.signRequestData.keyId, new int32[](0)) returns (KeyResponse memory keyResponse) {
+            _keyAddress = address(bytes20(keccak256(keyResponse.key.publicKey)));
+        } catch {
+            revert("Failed to retrieve key from warden precompile");
+        }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +96 to +102
function execute(
uint256 nonce,
uint256 gas,
uint256 gasPrice,
uint256 maxPriorityFeePerGas,
uint256 maxFeePerGas
)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add validation for gas-related parameters

The execute function accepts gas-related parameters without validation. This could lead to failed transactions if these parameters are set incorrectly.

Add validation checks:

     function execute(
         uint256 nonce,
         uint256 gas,
         uint256 gasPrice,
         uint256 maxPriorityFeePerGas,
         uint256 maxFeePerGas
     ) external nonReentrant returns (bool) {
+        if (gas == 0) revert("Invalid gas value");
+        if (maxFeePerGas < maxPriorityFeePerGas) revert("Invalid fee values");
+        if (maxFeePerGas > 0 && gasPrice > 0) revert("Cannot specify both gasPrice and maxFeePerGas");

Committable suggestion skipped: line range outside the PR's diff.

@mn13 mn13 force-pushed the feat/basic-order-contract branch from bc2d60d to f3f3176 Compare November 15, 2024 09:49
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (10)
solidity/orders/README.md (1)

5-5: Add a comma for better readability

Consider adding a comma after "commands" to improve readability.

-Before using commands install dependencies with `yarn install`.
+Before using commands, install dependencies with `yarn install`.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~5-~5: Possible missing comma found.
Context: ...p contracts ### Commands Before using commands install dependencies with `yarn install...

(AI_HYDRA_LEO_MISSING_COMMA)

solidity/orders/src/OrderFactory.sol (3)

19-19: Add index to orderContact parameter in OrderCreated event

Adding an index to the orderContact parameter will improve filtering capabilities when querying events.

- event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address indexed orderContact);
+ event OrderCreated(address indexed orderCreator, OrderType indexed orderType, address indexed orderContact);

14-17: Consider moving common errors to a separate file

For better organization and reusability, consider moving generic errors like InvalidRegistryAddress and InvalidSchedulerAddress to a separate errors.sol file, while keeping contract-specific errors like UnsupportedOrder here.


78-78: Implement registry registration

The TODO comment indicates missing registry registration functionality. This should be implemented to ensure proper order tracking.

Would you like me to help implement the registry registration logic?

solidity/orders/src/BasicOrder.sol (2)

11-22: Add NatSpec documentation for custom errors

Adding NatSpec documentation for custom errors would improve code maintainability and developer experience by clearly explaining when each error is thrown.

Example:

+/// @notice Thrown when the price condition for order execution is not met
 error ConditionNotMet();
+/// @notice Thrown when attempting to execute an already executed order
 error ExecutedError();

165-174: Cache packed swap data in executionData

The function calls _packSwapData which performs encoding operations. Consider caching the result if this function is called frequently.

     function executionData() external view returns (ExecutionData memory data) {
-        bytes memory d = _packSwapData();
+        bytes memory d = _cachedSwapData != bytes(0) ? _cachedSwapData : _packSwapData();
         data = ExecutionData({
solidity/orders/test/BasicOrder.t.sol (4)

198-198: Replace magic numbers in _order.execute call with named constants

Using magic numbers in the call _order.execute(1, 1, 1, 1, 1); reduces readability. Define named constants or variables for these parameters to improve code clarity and maintainability.


216-216: Replace magic numbers in _order.execute call with named constants

Using magic numbers in the call _order.execute(1, 1, 1, 1, 1); reduces readability. Define named constants or variables for these parameters to improve code clarity and maintainability.


235-235: Replace magic numbers in _order.execute call with named constants

Using magic numbers in the call _order.execute(1, 1, 1, 1, 1); reduces readability. Define named constants or variables for these parameters to improve code clarity and maintainability.


128-128: Ensure consistent naming conventions in test function names

The test function names are inconsistent in their casing after underscores, such as test_BasicOrder_Create and test_basicOrderRevertWhenConditionNotMet. For better readability and maintainability, consider following a consistent naming convention throughout the test suite.

Also applies to: 193-193, 207-207, 226-226

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between bc2d60d and f3f3176.

📒 Files selected for processing (14)
  • solidity/orders/.prettierignore (2 hunks)
  • solidity/orders/README.md (1 hunks)
  • solidity/orders/package.json (1 hunks)
  • solidity/orders/remappings.txt (1 hunks)
  • solidity/orders/script/Deploy.s.sol (0 hunks)
  • solidity/orders/src/BasicOrder.sol (1 hunks)
  • solidity/orders/src/Foo.sol (0 hunks)
  • solidity/orders/src/IExecution.sol (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/src/Types.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
  • solidity/orders/test/Foo.t.sol (0 hunks)
  • solidity/orders/test/mocks/MockSlinkyPrecompile.sol (1 hunks)
  • solidity/orders/test/mocks/MockWardenPrecompile.sol (1 hunks)
💤 Files with no reviewable changes (3)
  • solidity/orders/script/Deploy.s.sol
  • solidity/orders/src/Foo.sol
  • solidity/orders/test/Foo.t.sol
🚧 Files skipped from review as they are similar to previous changes (7)
  • solidity/orders/.prettierignore
  • solidity/orders/package.json
  • solidity/orders/remappings.txt
  • solidity/orders/src/IExecution.sol
  • solidity/orders/src/Types.sol
  • solidity/orders/test/mocks/MockSlinkyPrecompile.sol
  • solidity/orders/test/mocks/MockWardenPrecompile.sol
🧰 Additional context used
📓 Path-based instructions (1)
solidity/orders/README.md (1)

Pattern **/*.md: "Assess the documentation for misspellings, grammatical errors, missing documentation and correctness"

🪛 LanguageTool
solidity/orders/README.md

[uncategorized] ~5-~5: Possible missing comma found.
Context: ...p contracts ### Commands Before using commands install dependencies with `yarn install...

(AI_HYDRA_LEO_MISSING_COMMA)

🔇 Additional comments (6)
solidity/orders/README.md (1)

8-16: LGTM: Clear and consistent build/test instructions

The build and test instructions are clear, properly formatted in code blocks, and consistently use yarn commands.

solidity/orders/src/OrderFactory.sol (3)

1-8: LGTM! Well-structured imports and version constraints.

The file structure follows best practices with clear license, pragma, and organized imports.


33-44: LGTM! Well-implemented constructor with proper validations.

The constructor correctly validates addresses and initializes state variables.


46-61: 🛠️ Refactor suggestion

Consider removing scheduler parameter from createOrder

As suggested in past reviews, consider moving scheduler management entirely to the constructor and admin functions, rather than allowing it to be passed in createOrder. This would provide better control over scheduler changes.

 function createOrder(
     Types.OrderData calldata _orderData,
-    CommonTypes.Coin[] calldata maxKeychainFees,
-    OrderType orderType
+    CommonTypes.Coin[] calldata maxKeychainFees
 )
     public
     returns (address order)
 {
     if (orderType == OrderType.Basic) {
-        return _createBasicOrder(_orderData, maxKeychainFees, scheduler);
+        return _createBasicOrder(_orderData, maxKeychainFees);
     } else if (orderType == OrderType.Advanced) {
         return _createAdvancedOrder(_orderData, maxKeychainFees);
     } else {
         revert UnsupportedOrder();
     }
 }

Likely invalid or redundant comment.

solidity/orders/src/BasicOrder.sol (2)

96-106: 🛠️ Refactor suggestion

Add validation for gas-related parameters

The execute function accepts gas-related parameters without proper validation, which could lead to failed transactions.

+        if (gas == 0) revert("Invalid gas value");
+        if (maxFeePerGas > 0 && gasPrice > 0) revert("Cannot specify both gasPrice and maxFeePerGas");
+        if (maxFeePerGas < maxPriorityFeePerGas) revert("MaxFeePerGas must be >= maxPriorityFeePerGas");

Likely invalid or redundant comment.


71-76: ⚠️ Potential issue

Add error handling for precompile contract calls

The constructor makes external calls to precompile contracts without proper error handling. These calls could fail and make contract deployment impossible.

-        KeyResponse memory keyResponse = _wardenPrecompile.keyById(_orderData.signRequestData.keyId, new int32[](0));
+        try _wardenPrecompile.keyById(_orderData.signRequestData.keyId, new int32[](0)) returns (KeyResponse memory keyResponse) {
+            _keyAddress = address(bytes20(keccak256(keyResponse.key.publicKey)));
+        } catch {
+            revert("Failed to retrieve key from warden precompile");
+        }

Likely invalid or redundant comment.

Comment on lines +39 to +41
for (uint256 i = 0; i < maxKeychainFees.length; i++) {
_coins.push(maxKeychainFees[i]);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for maxKeychainFees array length

The loop that copies maxKeychainFees could potentially consume excessive gas if the array is too large. Consider adding a maximum length check.

+        if (maxKeychainFees.length > 10) { // adjust maximum as needed
+            revert("MaxKeychainFees array too long");
+        }
         for (uint256 i = 0; i < maxKeychainFees.length; i++) {

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +180 to +188
function _packSwapData() internal view returns (bytes memory data) {
data = abi.encodeWithSignature(
SWAP_EXACT_ETH_FOR_TOKENS,
orderData.swapData.amountIn,
orderData.swapData.path,
orderData.swapData.to,
orderData.swapData.deadline
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation for swap path array

The _packSwapData function packs the path array without validating its contents. Consider adding checks for:

  • Minimum path length (at least 2 tokens)
  • Valid token addresses (non-zero)
  • Path starts with wrapped native token for ETH swaps
     function _packSwapData() internal view returns (bytes memory data) {
+        if (orderData.swapData.path.length < 2) {
+            revert("Invalid path length");
+        }
+        for (uint i = 0; i < orderData.swapData.path.length; i++) {
+            if (orderData.swapData.path[i] == address(0)) {
+                revert("Invalid token address in path");
+            }
+        }
         data = abi.encodeWithSignature(

Committable suggestion skipped: line range outside the PR's diff.

condition = 0;
}

address[] memory path;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Validate that swapData.path is not empty

The swapData.path array is initialized but left empty. An empty path can lead to errors during the swap execution, as the swap function may require at least one token address in the path. Ensure that swapData.path is properly populated with the token addresses involved in the swap.

Apply this diff to initialize path with the necessary token addresses:

-    address[] memory path;
+    address[] memory path = new address[](2);
+    // Initialize 'path' with token addresses
+    path[0] = address(/* Token A address */);
+    path[1] = address(/* Token B address */);

Also applies to: 158-158, 246-246, 253-253

Comment on lines +207 to +224
function test_basicOrderExecuteWhenPriceMovesDown() public {
uint256 price = _testData.thresholdPrice - 1;
_testData.mockSlinkyPrecompile.setPrice(_testData.pricePair.base, _testData.pricePair.quote, price);

assert(_order.canExecute());

vm.expectEmit(false, false, false, false);
emit Executed();

bool executed = _order.execute(1, 1, 1, 1, 1);

assert(executed);

assert(_order.isExecuted());

vm.expectRevert(ExecutedError.selector);
_order.execute(1, 1, 1, 1, 1);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor to reduce code duplication in test functions

The test functions test_basicOrderExecuteWhenPriceMovesDown and test_basicOrderExecuteWhenPriceMovesUp contain similar logic with minor differences. Consider refactoring the shared code into a helper function to improve maintainability and reduce duplication.

Also applies to: 226-243

solidity/orders/src/BasicOrder.sol Outdated Show resolved Hide resolved
solidity/orders/src/OrderFactory.sol Outdated Show resolved Hide resolved
solidity/orders/src/OrderFactory.sol Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (6)
solidity/orders/src/OrderFactory.sol (1)

82-82: Address TODO comment about registry registration

The TODO comment indicates missing functionality for registering the order in the registry. This should be implemented to ensure proper order tracking.

Would you like me to help implement the registry registration functionality or create a GitHub issue to track this task?

solidity/orders/src/BasicOrder.sol (1)

11-24: Add error definition for invalid swap path

Consider adding an error definition for invalid swap path length to maintain consistency with other validation errors.

+error InvalidSwapPath();
solidity/orders/test/BasicOrder.t.sol (4)

207-243: Refactor test functions to reduce code duplication

The test functions test_basicOrderExecuteWhenPriceMovesDown and test_basicOrderExecuteWhenPriceMovesUp contain similar logic. Consider refactoring shared code into a helper function to improve maintainability.

Example refactoring:

+        function executeOrderAtPrice(uint256 price) internal {
+            _testData.mockSlinkyPrecompile.setPrice(_testData.pricePair.base, _testData.pricePair.quote, price);
+            assert(_order.canExecute());
+            vm.expectEmit(false, false, false, false);
+            emit Executed();
+            bool executed = _order.execute(1, 1, 1, 1, 1);
+            assert(executed);
+            assert(_order.isExecuted());
+            vm.expectRevert(ExecutedError.selector);
+            _order.execute(1, 1, 1, 1, 1);
+        }

         function test_basicOrderExecuteWhenPriceMovesDown() public {
-            uint256 price = _testData.thresholdPrice - 1;
-            _testData.mockSlinkyPrecompile.setPrice(_testData.pricePair.base, _testData.pricePair.quote, price);
-
-            assert(_order.canExecute());
-
-            vm.expectEmit(false, false, false, false);
-            emit Executed();
-
-            bool executed = _order.execute(1, 1, 1, 1, 1);
-
-            assert(executed);
-
-            assert(_order.isExecuted());
-
-            vm.expectRevert(ExecutedError.selector);
-            _order.execute(1, 1, 1, 1, 1);
+            executeOrderAtPrice(_testData.thresholdPrice - 1);
         }

         function test_basicOrderExecuteWhenPriceMovesUp() public {
-            uint256 price = _testData.thresholdPrice + 1;
-            _testData.mockSlinkyPrecompile.setPrice(_testData.pricePair.base, _testData.pricePair.quote, price);
-
-            assert(_order.canExecute());
-
-            vm.expectEmit(false, false, false, false);
-            emit Executed();
-
-            bool executed = _order.execute(1, 1, 1, 1, 1);
-
-            assert(executed);
-
-            assert(_order.isExecuted());
-
-            vm.expectRevert(ExecutedError.selector);
-            _order.execute(1, 1, 1, 1, 1);
+            executeOrderAtPrice(_testData.thresholdPrice + 1);
         }

52-54: Remove redundant error declaration

The error OwnableUnauthorizedAccount is already defined in OpenZeppelin's Ownable.sol. Since you're importing OpenZeppelin contracts, you can remove this redundant declaration to avoid conflicts.

Apply this diff to remove the redundant error:

-        // @openzeppelin Ownable.sol
-        error OwnableUnauthorizedAccount(address account);

55-57: Consider making addresses configurable for flexibility

Hardcoding addresses like SEPOLIA_UNISWAP_V2_ROUTER and RECEIVER can limit testing flexibility across different environments. Consider making them configurable via constructor parameters or environment variables.

Example adjustment:

-        address private constant SEPOLIA_UNISWAP_V2_ROUTER =
-            address(bytes20(bytes("0xeE567Fe1712Faf6149d80dA1E6934E354124CfE3")));
-        address private constant RECEIVER = address(bytes20(bytes("0x18517Cb2779186B86b1F8947dFdB6078C1B9C9db"));
+        address private immutable uniswapV2Router;
+        address private immutable receiver;
+
+        constructor(address _uniswapV2Router, address _receiver) {
+            uniswapV2Router = _uniswapV2Router;
+            receiver = _receiver;
+        }

96-98: Use mock addresses for clarity

Using address(this) for registry, scheduler, and owner in the setUp function may reduce readability. Consider defining explicit mock addresses to clarify their roles.

Example:

-            address registry = address(this);
-            address scheduler = address(this);
-            address owner = address(this);
+            address mockRegistry = address(this);
+            address mockScheduler = address(this);
+            address mockOwner = address(this);
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f3f3176 and 5c9afe9.

📒 Files selected for processing (3)
  • solidity/orders/src/BasicOrder.sol (1 hunks)
  • solidity/orders/src/OrderFactory.sol (1 hunks)
  • solidity/orders/test/BasicOrder.t.sol (1 hunks)
🔇 Additional comments (11)
solidity/orders/src/OrderFactory.sol (3)

33-44: LGTM! Well-structured constructor with proper validations

The constructor follows best practices:

  • Validates zero addresses
  • Properly initializes state variables
  • Correctly passes owner to the Ownable constructor

88-97: LGTM! Well-structured unimplemented function

The _createAdvancedOrder function is properly marked as unimplemented:

  • Correctly marked as pure since it doesn't access state
  • Uses a custom error for unimplemented state
  • Has proper parameter names omitted since they're unused

2-2: Consider relaxing the minimum Solidity version requirement

The pragma version >=0.8.25 is very recent and might limit compatibility with some development environments or tools. Consider using a more established version like >=0.8.20 unless specific 0.8.25 features are required.

solidity/orders/src/BasicOrder.sol (4)

1-10: LGTM! Well-structured imports and version pragma

The contract uses appropriate version constraints and necessary imports. The inclusion of ReentrancyGuard shows good security practices.


180-188: 🛠️ Refactor suggestion

Add path validation and documentation

The _packSwapData function should validate the swap path and include natspec documentation.

+    /// @notice Packs swap data for transaction execution
+    /// @return data The packed swap data
     function _packSwapData() internal view returns (bytes memory data) {
+        if (orderData.swapData.path.length < 2) {
+            revert InvalidSwapPath();
+        }
+        for (uint i = 0; i < orderData.swapData.path.length; i++) {
+            if (orderData.swapData.path[i] == address(0)) {
+                revert("Invalid token address in path");
+            }
+        }

Likely invalid or redundant comment.


38-41: 🛠️ Refactor suggestion

Optimize array copying and add length validation

The array copying loop could be gas-intensive for large arrays. Consider adding a maximum length check and using memory pointer optimization.

+       if (maxKeychainFees.length > 10) {
+           revert("MaxKeychainFees array too long");
+       }
+       assembly {
+           // Get the pointer to the free memory
+           let ptr := mload(0x40)
+           // Copy the array to memory
+           calldatacopy(ptr, maxKeychainFees.offset, mul(maxKeychainFees.length, 0x20))
+           // Update the free memory pointer
+           mstore(0x40, add(ptr, mul(maxKeychainFees.length, 0x20)))
+       }

Likely invalid or redundant comment.


96-106: ⚠️ Potential issue

Add validation for gas-related parameters

The execute function should validate gas-related parameters to prevent potential issues with transaction execution.

+       if (gas == 0) {
+           revert("Invalid gas value");
+       }
+       if (maxFeePerGas > 0 && gasPrice > 0) {
+           revert("Cannot specify both gasPrice and maxFeePerGas");
+       }
+       if (maxFeePerGas < maxPriorityFeePerGas) {
+           revert("Invalid fee values");
+       }

Likely invalid or redundant comment.

solidity/orders/test/BasicOrder.t.sol (4)

133-133: ⚠️ Potential issue

Initialize path to prevent potential issues

The path array is declared but not initialized. An empty path may cause issues when used in swaps. Ensure that path is properly initialized with the required token addresses.

Apply this diff to initialize path:

-            address[] memory path;
+            address[] memory path = new address[](2);
+            path[0] = address(/* Token A address */);
+            path[1] = address(/* Token B address */);

Likely invalid or redundant comment.


203-203: ⚠️ Potential issue

Avoid using address(0) with vm.broadcast

Using address(0) as the sender in vm.broadcast is inappropriate and can lead to unexpected behavior. Use a valid address to simulate unauthorized access.

Apply this diff to use a valid unauthorized address:

-            vm.broadcast(address(0));
+            address unauthorizedUser = address(0xDEADBEEF);
+            vm.broadcast(unauthorizedUser);

Likely invalid or redundant comment.


129-131: 🛠️ Refactor suggestion

Enhance condition validation in test_BasicOrder_Create

The condition check if (condition > 1) silently defaults to 0 for invalid values. It's better to validate the input and revert if an invalid condition is provided to catch unintended misuse.

Apply this diff to improve the validation:

-            if (condition > 1) {
-                condition = 0;
-            }
+            require(condition <= uint8(Types.PriceCondition.GTE), "Invalid condition");

Likely invalid or redundant comment.


154-173: Validate uninitialized parameters in OrderData

Parameters like analyzers, encryptionKey, and path are declared but not initialized. Ensure that passing empty arrays or uninitialized values is acceptable, or initialize them appropriately to prevent unexpected behavior.

Run the following script to check for usage of uninitialized parameters:

✅ Verification successful

Empty arrays are acceptable for analyzers, encryptionKey, and path parameters

Based on the code analysis:

  • The OrderData struct definition in Types.sol shows these fields are part of the structure
  • The BasicOrder constructor only validates swapData.amountIn must be non-zero and checks for a valid scheduler
  • No explicit validation exists requiring non-empty arrays for analyzers, encryptionKey, or path
  • The test file's usage of empty values appears to be intentional and valid
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for constructors or functions that require non-empty arrays.

# Find all instances where OrderData is used and check requirements.
rg 'OrderData\s*memory' -A 10 | rg 'require.*analyzers|require.*encryptionKey|require.*path'

Length of output: 94


Script:

#!/bin/bash
# Let's search for any validation or requirements on these fields in the contract code
# First, find all files that might contain OrderData struct definition and its usage
fd -e sol | xargs rg -l "OrderData"

# Then let's examine the struct definition and any validation logic
fd -e sol | xargs rg -A 5 "struct\s+OrderData"

# Also search for any validation in functions accepting OrderData
fd -e sol | xargs rg -B 2 -A 10 "function.*OrderData.*memory"

Length of output: 673


Script:

#!/bin/bash
# Let's check the BasicOrder contract for any validation of these fields
rg -B 2 -A 10 "constructor.*OrderData|function.*OrderData" solidity/orders/src/BasicOrder.sol

# Also check OrderFactory for any validation during order creation
rg -B 2 -A 10 "constructor.*OrderData|function.*OrderData" solidity/orders/src/OrderFactory.sol

# Let's also check if there are any require statements related to these fields
rg "require.*(\b(analyzers|encryptionKey|path)\b)" solidity/orders/src/

Length of output: 719

Comment on lines +46 to +61
function createOrder(
Types.OrderData calldata _orderData,
CommonTypes.Coin[] calldata maxKeychainFees,
OrderType orderType
)
public
returns (address order)
{
if (orderType == OrderType.Basic) {
return _createBasicOrder(_orderData, maxKeychainFees, scheduler);
} else if (orderType == OrderType.Advanced) {
return _createAdvancedOrder(_orderData, maxKeychainFees);
} else {
revert UnsupportedOrder();
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add reentrancy protection to createOrder

The createOrder function makes external contract calls through _createBasicOrder but doesn't follow the checks-effects-interactions pattern. Consider adding the nonReentrant modifier from OpenZeppelin's ReentrancyGuard.

Apply this diff:

-import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
+import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
+import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";

-contract OrderFactory is Ownable {
+contract OrderFactory is Ownable, ReentrancyGuard {

     function createOrder(
         Types.OrderData calldata _orderData,
         CommonTypes.Coin[] calldata maxKeychainFees,
         OrderType orderType
     )
         public
+        nonReentrant
         returns (address order)
📝 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. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function createOrder(
Types.OrderData calldata _orderData,
CommonTypes.Coin[] calldata maxKeychainFees,
OrderType orderType
)
public
returns (address order)
{
if (orderType == OrderType.Basic) {
return _createBasicOrder(_orderData, maxKeychainFees, scheduler);
} else if (orderType == OrderType.Advanced) {
return _createAdvancedOrder(_orderData, maxKeychainFees);
} else {
revert UnsupportedOrder();
}
}
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract OrderFactory is Ownable, ReentrancyGuard {
function createOrder(
Types.OrderData calldata _orderData,
CommonTypes.Coin[] calldata maxKeychainFees,
OrderType orderType
)
public
nonReentrant
returns (address order)
{
if (orderType == OrderType.Basic) {
return _createBasicOrder(_orderData, maxKeychainFees, scheduler);
} else if (orderType == OrderType.Advanced) {
return _createAdvancedOrder(_orderData, maxKeychainFees);
} else {
revert UnsupportedOrder();
}
}

Comment on lines +71 to +77
WARDEN_PRECOMPILE = IWarden(IWARDEN_PRECOMPILE_ADDRESS);
KeyResponse memory keyResponse = WARDEN_PRECOMPILE.keyById(_orderData.signRequestData.keyId, new int32[](0));
_keyAddress = address(bytes20(keccak256(keyResponse.key.publicKey)));

SLINKY_PRECOMPILE = ISlinky(ISLINKY_PRECOMPILE_ADDRESS);
SLINKY_PRECOMPILE.getPrice(_orderData.pricePair.base, _orderData.pricePair.quote);

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add error handling for precompile calls

The calls to WARDEN_PRECOMPILE and SLINKY_PRECOMPILE could fail. Consider adding try-catch blocks.

-       KeyResponse memory keyResponse = WARDEN_PRECOMPILE.keyById(_orderData.signRequestData.keyId, new int32[](0));
+       try WARDEN_PRECOMPILE.keyById(_orderData.signRequestData.keyId, new int32[](0)) returns (KeyResponse memory keyResponse) {
+           _keyAddress = address(bytes20(keccak256(keyResponse.key.publicKey)));
+       } catch {
+           revert("Failed to retrieve key");
+       }

Committable suggestion skipped: line range outside the PR's diff.

@mn13 mn13 merged commit 387c1e6 into main Nov 15, 2024
13 checks passed
@mn13 mn13 deleted the feat/basic-order-contract branch November 15, 2024 10:40
This was referenced Nov 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Basic][Evmos]: Factory contract [Basic][Evmos]: Order contract
2 participants