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: jsonutils precompiles for wrap contract memo construction #148

Merged
merged 3 commits into from
Jan 27, 2025

Conversation

beer-1
Copy link
Member

@beer-1 beer-1 commented Jan 26, 2025

Description

  1. Introduce json precompile for the following features

    • json merge
    • stringify
  2. Update wrapper contract to use json precompile at memo construction


Author Checklist

All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.

I have...

  • included the correct type prefix in the PR title, you can find examples of the prefixes below:
  • confirmed ! in the type prefix if API or client breaking change
  • targeted the correct branch
  • provided a link to the relevant issue or specification
  • reviewed "Files changed" and left comments if necessary
  • included the necessary unit and integration tests
  • updated the relevant documentation or specification, including comments for documenting Go code
  • confirmed all CI checks have passed

Reviewers Checklist

All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.

I have...

  • confirmed the correct type prefix in the PR title
  • confirmed all author checklist items have been addressed
  • reviewed state machine logic, API design and naming, documentation is accurate, tests and test coverage

Summary by CodeRabbit

Release Notes

  • New Features

    • Added JSON utility precompile for EVM, enabling advanced JSON manipulation.
    • Introduced merge_json and stringify_json functions for smart contract interactions.
    • Enhanced IBC transfer memo handling with new JSON utility methods.
  • Improvements

    • Renamed parameter move_memo to memo for improved clarity.
    • Updated ERC20 wrapper contract to support more flexible memo construction.
    • Added support for JSON merging with conflict resolution.
  • Technical Updates

    • Implemented new precompiled contract for JSON operations.
    • Added comprehensive test coverage for JSON utility functions.
    • Introduced interface and implementation for JSON manipulation.
    • Updated upgrade version to "0.6.10".

@beer-1 beer-1 requested a review from djm07073 January 26, 2025 16:30
@beer-1 beer-1 self-assigned this Jan 26, 2025
@beer-1 beer-1 requested a review from a team as a code owner January 26, 2025 16:30
Copy link

coderabbitai bot commented Jan 26, 2025

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 golangci-lint (1.62.2)

level=warning msg="[runner] Can't run linter goanalysis_metalinter: buildir: failed to load package injective: could not load export data: no export data for "github.com/cosmos/relayer/v2/relayer/codecs/injective""
level=error msg="Running error: can't run linter goanalysis_metalinter\nbuildir: failed to load package injective: could not load export data: no export data for "github.com/cosmos/relayer/v2/relayer/codecs/injective""

Walkthrough

This pull request introduces a comprehensive JSON utility system for the Ethereum Virtual Machine (EVM) precompiles. The changes include creating a new IJSONUtils interface and implementation, adding JSON merging and stringification capabilities, and integrating these utilities into the ERC20 wrapper contract. The modifications enhance the contract's ability to handle complex JSON operations during IBC transfers by introducing new precompiled contract methods for JSON manipulation.

Changes

File Change Summary
x/evm/contracts/erc20_wrapper/ERC20Wrapper.go Updated ABI and method signatures, renaming move_memo to memo
x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol Added IJSONUtils import, renamed parameters, modified _ibc_transfer to use JSON utilities
x/evm/contracts/i_jsonutils/* New package with JSON utility implementations, including merging, stringification, and precompiled contract support
x/evm/types/address.go Added JSONUtilsPrecompileAddress
x/evm/keeper/precompiles.go Added JSONUtils precompile instantiation
x/evm/keeper/precompiles_test.go Added tests for JSON merging functionality
x/evm/precompiles/jsonutils/common_test.go Introduced mock StateDB for testing
x/evm/precompiles/jsonutils/contract.go Implemented JSONUtilsPrecompile struct for JSON operations
x/evm/precompiles/jsonutils/contract_test.go Added tests for JSON utilities precompile
x/evm/precompiles/jsonutils/merge.go Implemented MergeJSON function for merging JSON strings
x/evm/precompiles/jsonutils/merge_test.go Added tests for MergeJSON functionality
x/evm/precompiles/jsonutils/types.go Defined types and constants for JSON operations
app/upgrade.go Updated upgrade version from "0.6.9" to "0.6.10"

Sequence Diagram

sequenceDiagram
    participant Contract as ERC20 Wrapper
    participant JSONUtils as JSON Utilities Precompile
    participant IBC as IBC Transfer

    Contract->>JSONUtils: merge_json(dst_json, src_json)
    JSONUtils-->>Contract: Merged JSON
    Contract->>JSONUtils: stringify_json(merged_json)
    JSONUtils-->>Contract: Stringified JSON
    Contract->>IBC: Transfer with enhanced memo
Loading

Possibly related PRs

Suggested reviewers

  • djm07073

Poem

🐰 JSON dancing, bits in flight,
Merging objects with rabbit's might!
Precompiles weave their magic spell,
Transforming data, doing it well
Hop, hop, hooray for code so bright! 🌟

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 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 generate docstrings to generate docstrings for this PR. (Beta)
  • @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.

CodeRabbit Configuration File (.coderabbit.yaml)

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

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.

Copy link

codecov bot commented Jan 26, 2025

Codecov Report

Attention: Patch coverage is 59.54198% with 53 lines in your changes missing coverage. Please review.

Project coverage is 57.20%. Comparing base (c607d21) to head (5671ef9).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
x/evm/precompiles/jsonutils/contract.go 58.44% 24 Missing and 8 partials ⚠️
x/evm/precompiles/jsonutils/merge.go 63.26% 12 Missing and 6 partials ⚠️
x/evm/keeper/precompiles.go 40.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #148      +/-   ##
==========================================
+ Coverage   57.17%   57.20%   +0.02%     
==========================================
  Files         110      112       +2     
  Lines       10242    10373     +131     
==========================================
+ Hits         5856     5934      +78     
- Misses       3540     3578      +38     
- Partials      846      861      +15     
Files with missing lines Coverage Δ
app/upgrade.go 3.84% <ø> (ø)
x/evm/types/address.go 66.66% <ø> (ø)
x/evm/keeper/precompiles.go 71.87% <40.00%> (-5.91%) ⬇️
x/evm/precompiles/jsonutils/merge.go 63.26% <63.26%> (ø)
x/evm/precompiles/jsonutils/contract.go 58.44% <58.44%> (ø)

Copy link

@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

🧹 Nitpick comments (11)
x/evm/precompiles/jsonutils/contract.go (3)

22-28: Consider returning an error instead of panicking on ABI loading failures.
Relying on panic here can be disruptive. For improved resilience in production environments, consider returning an error from the initialization logic and handling it during module setup or contract registration.


49-60: Graceful handling of unexpected panics.
The recover block ensures Cosmos SDK errors are converted into EVM-compatible ones, but be cautious about other unexpected panics. Consider adding logging here to avoid silently dropping important context from the error.


116-119: Remove or replace the debug printing statement.
Using fmt.Println in production code can clutter logs. Consider using a structured logger or removing this statement if no longer needed.

- fmt.Println("err", err)
+ // log.Debug("jsonutils stringify_json error", "error", err)
x/evm/precompiles/jsonutils/types.go (2)

7-14: Consider validating or constraining JSON strings.
Although these struct fields are only used for passing parameters, you might consider adding optional validation or checks to ensure the JSON data is well-formed before processing in the precompile.


16-23: Document the rationale behind gas constants and MaxDepth.
Adding comments to explain why MERGE_GAS, STRINGIFY_JSON_GAS, and MaxDepth are set to their current values can help future contributors maintain consistency or adjust these constants.

x/evm/contracts/i_jsonutils/IJSONUtils.sol (1)

10-22: Enhance interface documentation with examples and parameter descriptions.

While the interface is well-structured, it would benefit from more detailed documentation:

  • Add @param and @return descriptions
  • Include example JSON inputs and outputs
  • Document any size limitations or error conditions

Example documentation format:

/// @notice Recursively merges two JSON strings
/// @param dst_json The destination JSON string to merge into
/// @param src_json The source JSON string that takes precedence
/// @return The merged JSON string
/// @dev Example:
///      dst_json: {"a": 1, "b": {"c": 2}}
///      src_json: {"b": {"d": 3}, "e": 4}
///      returns:  {"a": 1, "b": {"c": 2, "d": 3}, "e": 4}
x/evm/precompiles/jsonutils/merge.go (1)

37-58: Document merge strategy and add array handling.

The merge function needs:

  1. Documentation of the merge strategy for conflicts
  2. Explicit handling of array values
  3. Definition of MaxDepth constant

Consider this implementation:

+// MaxDepth defines the maximum recursion depth for JSON merging
+const MaxDepth = 32
+
+// merge recursively merges src into dst.
+// For conflicts:
+// - Objects are merged recursively
+// - Arrays from src replace arrays in dst
+// - Other values from src replace values in dst
 func merge(dst, src map[string]interface{}, depth int) (map[string]interface{}, error) {
     if depth > MaxDepth {
         return nil, errors.New("max recursion depth reached")
     }
 
     for key, srcVal := range src {
         if dstVal, ok := dst[key]; ok {
+            // Handle arrays explicitly
+            if srcArr, srcIsArr := srcVal.([]interface{}); srcIsArr {
+                dst[key] = srcArr
+                continue
+            }
             srcMap, srcMapOk := mapify(srcVal)
             dstMap, dstMapOk := mapify(dstVal)
             if srcMapOk && dstMapOk {
x/evm/precompiles/jsonutils/contract_test.go (2)

49-119: Add test cases for edge cases.

Consider adding test cases for:

  1. Empty strings
  2. Large JSON objects approaching size limits
  3. JSON arrays
  4. Non-object JSON values (numbers, strings, null)
  5. Maximum nesting depth

Example test cases to add:

     {
         name:        "invalid src json",
         dst:         `{"a": 1, "b": 2}`,
         src:         `{"b": 3, "c": 4`,
         expectedErr: true,
     },
+    {
+        name:        "empty strings",
+        dst:         "",
+        src:         "",
+        expectedErr: true,
+    },
+    {
+        name:        "non-object json",
+        dst:         `42`,
+        src:         `{"a": 1}`,
+        expectedErr: true,
+    },
+    {
+        name:        "array in json",
+        dst:         `{"a": [1,2]}`,
+        src:         `{"a": [3,4]}`,
+        expected:    `{"a":[3,4]}`,
+    },

121-169: Add test cases for special characters and empty structures.

Consider adding test cases for:

  1. Empty objects and arrays
  2. Special characters (quotes, backslashes)
  3. Unicode characters
  4. Null values

Example test cases to add:

     {
         name:     "slice",
         input:    `[1,2,3]`,
         expected: `"[1,2,3]"`,
     },
+    {
+        name:     "empty structures",
+        input:    `{"a":{},"b":[]}`,
+        expected: `"{\"a\": {}, \"b\": []}"`,
+    },
+    {
+        name:     "special characters",
+        input:    `{"a":"quote\"here","b":"back\\slash"}`,
+        expected: `"{\"a\": \"quote\\\"here\", \"b\": \"back\\\\slash\"}"`,
+    },
+    {
+        name:     "unicode",
+        input:    `{"a":"🚀","b":"世界"}`,
+        expected: `"{\"a\": \"🚀\", \"b\": \"世界\"}"`,
+    },
x/evm/keeper/precompiles_test.go (1)

209-227: Add more comprehensive integration test cases.

The integration test should cover:

  1. Error cases (invalid JSON, insufficient gas)
  2. Complex JSON structures (nested objects, arrays)
  3. Edge cases (empty objects, maximum nesting)

Example test cases to add:

 func Test_JSONMerge(t *testing.T) {
     testCases := []struct {
+        name        string
+        dst         string
+        src         string
+        gasLimit    uint64
+        expectErr   bool
+        expected    string
+    }{
+        {
+            name:     "simple merge",
+            dst:      `{"a": 1, "b": 2}`,
+            src:      `{"b": 3, "c": 4}`,
+            gasLimit: types.JSONUtilsPrecompileGasCost,
+            expected: `{"a":1,"b":3,"c":4}`,
+        },
+        {
+            name:      "insufficient gas",
+            dst:       `{"a": 1}`,
+            src:       `{"b": 2}`,
+            gasLimit:  100,
+            expectErr: true,
+        },
+        {
+            name:     "complex nested",
+            dst:      `{"a":{"b":{"c":1}}}`,
+            src:      `{"a":{"b":{"d":2}}}`,
+            gasLimit: types.JSONUtilsPrecompileGasCost,
+            expected: `{"a":{"b":{"c":1,"d":2}}}`,
+        },
+    }
+
+    for _, tc := range testCases {
+        t.Run(tc.name, func(t *testing.T) {
             ctx, input := createDefaultTestInput(t)
             _, _, addr := keyPubAddr()
             evmAddr := common.BytesToAddress(addr.Bytes())
x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol (1)

212-224: Consider using a more robust JSON construction approach.

While the current implementation works, constructing JSON through string concatenation can be error-prone and harder to maintain. Consider using a structured approach:

  1. Define a struct for the callback data
  2. Use a JSON encoding library to convert the struct to JSON
  3. Then merge with the user memo

This would provide better type safety and maintainability.

Example approach:

+struct AsyncCallback {
+    uint64 id;
+    address contract_address;
+}
+
+struct CallbackWrapper {
+    AsyncCallback async_callback;
+}
+
+struct MemoWrapper {
+    CallbackWrapper evm;
+}

 function _ibc_transfer(...) internal returns (string memory message) {
-    string memory callback_memo = string(
-        abi.encodePacked(
-            '{"evm": {"async_callback": {"id": ',
-            Strings.toString(callBackId),
-            ',"contract_address":"',
-            Strings.toHexString(address(this)),
-            '"}}}'
-        )
-    );
+    MemoWrapper memory wrapper = MemoWrapper({
+        evm: CallbackWrapper({
+            async_callback: AsyncCallback({
+                id: callBackId,
+                contract_address: address(this)
+            })
+        })
+    });
+    string memory callback_memo = JSONUTILS_CONTRACT.encode_json(wrapper);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c607d21 and 07b499d.

📒 Files selected for processing (13)
  • x/evm/contracts/erc20_wrapper/ERC20Wrapper.go (2 hunks)
  • x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol (5 hunks)
  • x/evm/contracts/i_jsonutils/IJSONUtils.go (1 hunks)
  • x/evm/contracts/i_jsonutils/IJSONUtils.sol (1 hunks)
  • x/evm/keeper/precompiles.go (2 hunks)
  • x/evm/keeper/precompiles_test.go (2 hunks)
  • x/evm/precompiles/jsonutils/common_test.go (1 hunks)
  • x/evm/precompiles/jsonutils/contract.go (1 hunks)
  • x/evm/precompiles/jsonutils/contract_test.go (1 hunks)
  • x/evm/precompiles/jsonutils/merge.go (1 hunks)
  • x/evm/precompiles/jsonutils/merge_test.go (1 hunks)
  • x/evm/precompiles/jsonutils/types.go (1 hunks)
  • x/evm/types/address.go (1 hunks)
🔇 Additional comments (13)
x/evm/precompiles/jsonutils/contract.go (2)

130-132: Confirm the zero gas cost in RequiredGas.
While gas is consumed in ExtendedRun, returning zero here might cause confusion or incorrect assumptions for tools expecting non-zero costs. Double-check if a nominal value or an explanatory comment is preferred.


135-137: Method clarity on Run usage.
The comment clarifies that Run is not intended for this precompile. The implementation is consistent with the rest of the design.

x/evm/contracts/i_jsonutils/IJSONUtils.go (1)

1-3: No manual changes are recommended for auto-generated code.
This file is auto-generated from the Solidity contract. If any changes are needed, consider updating the Solidity interface or the code generator configuration instead.

x/evm/contracts/i_jsonutils/IJSONUtils.sol (1)

4-8: LGTM! Well-structured precompile address definition.

The constant address definition and contract instance are properly defined at the module level.

x/evm/precompiles/jsonutils/merge_test.go (1)

38-44: LGTM! Well-structured test implementation.

The test implementation follows good practices:

  • Table-driven tests with clear structure
  • Proper error handling and assertions
  • Clear test case names
x/evm/types/address.go (1)

25-27: LGTM! Consistent precompile address allocation.

The JSONUtils precompile address is properly allocated and follows the established pattern for precompile addresses.

x/evm/keeper/precompiles.go (1)

38-42: LGTM! Clean precompile integration.

The JSONUtils precompile is properly initialized and integrated into the precompiles map, following the established pattern.

Also applies to: 47-47

x/evm/precompiles/jsonutils/merge.go (1)

60-72: LGTM!

The mapify function safely handles map type conversion using reflection.

x/evm/precompiles/jsonutils/common_test.go (1)

20-252: LGTM!

The MockStateDB implementation correctly handles the required functionality for testing (context and snapshots) while appropriately marking other methods as unimplemented.

x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol (3)

11-11: LGTM: Import added for JSON utilities.

The import statement for IJSONUtils is correctly added to support the new JSON manipulation functionality.


67-67: LGTM: Parameter renamed for better clarity.

The parameter rename from move_memo to memo better reflects its general purpose usage.


250-252: LGTM: Proper integration of processed memo.

The stringified memo is correctly integrated into the final IBC transfer message structure.

x/evm/contracts/erc20_wrapper/ERC20Wrapper.go (1)

478-494: LGTM: Go bindings correctly updated.

The auto-generated Go bindings are properly updated to reflect the Solidity contract changes, with correct parameter renaming from move_memo to memo.

x/evm/precompiles/jsonutils/merge_test.go Outdated Show resolved Hide resolved
x/evm/precompiles/jsonutils/merge.go Outdated Show resolved Hide resolved
Copy link
Contributor

@djm07073 djm07073 left a comment

Choose a reason for hiding this comment

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

LGTM

@beer-1 beer-1 merged commit af9d976 into main Jan 27, 2025
9 of 10 checks passed
@beer-1 beer-1 deleted the feat/wrap-memo branch January 27, 2025 13:03
Copy link

@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: 0

🧹 Nitpick comments (6)
x/evm/precompiles/jsonutils/types.go (2)

7-10: Consider adding input validation and using more idiomatic field names.

  1. Field naming could be more Go-idiomatic (e.g., DestJSON instead of DstJSON).
  2. Consider adding size validation using MaxJSONSize constant.
 type MergeJSONArguments struct {
-	DstJSON string `abi:"dst_json"`
-	SrcJSON string `abi:"src_json"`
+	DestJSON string `abi:"dst_json"`
+	SourceJSON string `abi:"src_json"`
 }

12-14: Consider adding input validation.

The JSON input should be validated against MaxJSONSize to prevent processing of oversized inputs.

x/evm/precompiles/jsonutils/merge_test.go (1)

56-62: Consider adding error test cases.

While the happy path is well tested, consider adding test cases for error scenarios:

  • Invalid JSON syntax
  • Exceeding MaxJSONSize
  • Exceeding MaxDepth with deeply nested objects

Example additional test cases:

{
    name: "invalid json syntax",
    dst:  `{"a": 1`,
    src:  `{"b": 2}`,
    err:  "unexpected end of JSON input",
},
{
    name: "max depth exceeded",
    dst:  `{"a": {"b": {"c": {"d": {"e": 1}}}}}`,
    src:  `{"a": {"b": {"c": {"d": {"e": 2}}}}}`,
    err:  "max recursion depth reached",
}
x/evm/precompiles/jsonutils/merge.go (2)

44-65: Consider optimizing the merge function.

The current implementation has a few potential improvements:

  1. Memory efficiency: Consider pre-allocating the result map with capacity hints
  2. Performance: Avoid unnecessary map conversions for non-map values
 func merge(dst, src map[string]interface{}, depth int) (map[string]interface{}, error) {
     if depth > MaxDepth {
         return nil, errors.New("max recursion depth reached")
     }
 
+    // Pre-allocate result map with capacity hint
+    result := make(map[string]interface{}, len(dst)+len(src))
+    
+    // Copy dst to result first
+    for k, v := range dst {
+        result[k] = v
+    }
+
     for key, srcVal := range src {
-        if dstVal, ok := dst[key]; ok {
+        if dstVal, ok := result[key]; ok {
+            // Quick check if either value is not a map
+            if reflect.TypeOf(srcVal).Kind() != reflect.Map ||
+               reflect.TypeOf(dstVal).Kind() != reflect.Map {
+                result[key] = srcVal
+                continue
+            }
             srcMap, srcMapOk := mapify(srcVal)
             dstMap, dstMapOk := mapify(dstVal)
             if srcMapOk && dstMapOk {
                 var err error
                 if srcVal, err = merge(dstMap, srcMap, depth+1); err != nil {
                     return nil, err
                 }
+                result[key] = srcVal
+                continue
             }
         }
-        dst[key] = srcVal
+        result[key] = srcVal
     }
 
-    return dst, nil
+    return result, nil
 }

67-79: Consider adding type assertion optimization.

The mapify function could be optimized by attempting a direct type assertion before using reflection.

 func mapify(i interface{}) (map[string]interface{}, bool) {
+    // Try direct type assertion first
+    if m, ok := i.(map[string]interface{}); ok {
+        return m, true
+    }
+
     value := reflect.ValueOf(i)
     if value.Kind() == reflect.Map {
         m := map[string]interface{}{}
         for _, k := range value.MapKeys() {
             m[k.String()] = value.MapIndex(k).Interface()
         }
         return m, true
     }
     return map[string]interface{}{}, false
 }
app/upgrade.go (1)

Line range hint 1-119: Consider documenting upgrade requirements.

While the upgrade implementation is solid, consider adding documentation comments that outline:

  1. The new JSON precompile feature being introduced
  2. Any state migrations or updates required
  3. Dependencies between the ERC20 wrapper contract updates and JSON precompile

This will help maintainers understand the upgrade's scope and requirements.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07b499d and 5671ef9.

📒 Files selected for processing (4)
  • app/upgrade.go (1 hunks)
  • x/evm/precompiles/jsonutils/merge.go (1 hunks)
  • x/evm/precompiles/jsonutils/merge_test.go (1 hunks)
  • x/evm/precompiles/jsonutils/types.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Run test and upload codecov
🔇 Additional comments (9)
x/evm/precompiles/jsonutils/types.go (2)

1-5: LGTM!

Package name and import are well-structured.


16-24: 🛠️ Refactor suggestion

Review gas costs and constant naming conventions.

Several considerations for the constants:

  1. Gas costs seem low for complex JSON operations:

    • MERGE_GAS and STRINGIFY_JSON_GAS are set to 100, which might not be sufficient for complex JSON structures
    • Consider factoring in JSON depth in gas calculation
  2. Naming conventions:

    • Use Go-style naming for constants (e.g., MergeGas instead of MERGE_GAS)
    • Consider more descriptive names (e.g., StringifyGas instead of STRINGIFY_JSON_GAS)
  3. Security considerations:

    • Evaluate if 10KB (MaxJSONSize) is an appropriate limit for your use case
    • Consider adding a minimum depth limit alongside MaxDepth
 const (
-	MERGE_GAS          storetypes.Gas = 100
-	STRINGIFY_JSON_GAS storetypes.Gas = 100
+	MergeGas      storetypes.Gas = 100
+	StringifyGas  storetypes.Gas = 100
 
-	GAS_PER_BYTE storetypes.Gas = 1
+	GasPerByte   storetypes.Gas = 1
 
-	MaxDepth    = 16
-	MaxJSONSize = 10 * 1024
+	MinDepth    = 1
+	MaxDepth    = 16
+	MaxJSONSize = 10 * 1024  // 10KB
 )

Let's verify the gas costs against similar operations in other precompiles:

x/evm/precompiles/jsonutils/merge_test.go (1)

12-54: LGTM! Comprehensive test coverage with good edge cases.

The test cases cover essential scenarios including:

  • Simple merges
  • Nested object handling
  • Conflict resolution
  • Empty objects
  • Null values
  • Array handling
x/evm/precompiles/jsonutils/merge.go (2)

10-42: LGTM! Good input validation and error handling.

The implementation includes proper validation for:

  • Empty strings
  • Size limits
  • JSON unmarshaling errors

16-16: Verify MaxJSONSize constant is defined.

The code references MaxJSONSize but its definition is not visible in the provided files.

✅ Verification successful

MaxJSONSize constant is properly defined

The constant is defined in x/evm/precompiles/jsonutils/types.go with a value of 10KB (10 * 1024).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for MaxJSONSize constant definition
rg -l "MaxJSONSize.*=.*\d+" 

Length of output: 66


Script:

#!/bin/bash
# View the MaxJSONSize definition
rg "MaxJSONSize.*=.*\d+" -A 2 x/evm/precompiles/jsonutils/types.go

Length of output: 95


Script:

#!/bin/bash
# View the complete constant declaration block
rg "const.*\(|MaxJSONSize.*=.*\d+" -B 2 -A 2 x/evm/precompiles/jsonutils/types.go

Length of output: 225

app/upgrade.go (4)

25-25: LGTM! Version increment follows semantic versioning.

The patch version increment from "0.6.9" to "0.6.10" aligns with the introduction of new features (JSON precompile) mentioned in the PR objectives.


Line range hint 71-119: LGTM! Comprehensive contract update process.

The update process thoroughly handles all aspects of contract state:

  • Contract code replacement
  • Code hash updates
  • Code size updates
  • Account state management

The error handling is robust, and the walker pattern ensures all contracts are processed.


Line range hint 49-67: Verify integration with new JSON precompile.

Since this PR introduces JSON precompile features for memo construction, ensure that:

  1. The ERC20 wrapper contract deployment includes the new JSON precompile address.
  2. The wrapper contract's bytecode is updated to use the new JSON utilities.
✅ Verification successful

JSON precompile integration verified successfully

The ERC20Wrapper contract correctly integrates with the JSON precompile:

  • Imports and uses IJSONUtils interface
  • Properly utilizes JSON utilities for memo handling in IBC transfers
  • Precompile address (0xf3) is automatically available through the EVM system
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the wrapper contract uses the JSON precompile
ast-grep --pattern 'contract ERC20Wrapper {
  $$$
  JSONUtils $_ = JSONUtils($_);
  $$$
}'

# Search for JSON precompile address configuration
rg -A 2 'JSONUtilsPrecompileAddress|PrecompileAddress' --type go

Length of output: 2743


Script:

#!/bin/bash
# Find ERC20Wrapper contract
fd -e sol "ERC20Wrapper"

# Check deployment implementation
rg -A 5 "DeployERC20Wrapper" --type go

# Look for JSON precompile integration in deployment
rg -A 5 "JSONUtilsPrecompileAddress.*wrapper" --type go

Length of output: 1487


Script:

#!/bin/bash
# View ERC20Wrapper contract content
cat x/evm/contracts/erc20_wrapper/ERC20Wrapper.sol

# Check deployment implementation details
rg -B 5 -A 15 "func \(k Keeper\) DeployERC20Wrapper" --type go

Length of output: 9492


Line range hint 38-45: Verify the default gas value for hooks.

The code defensively sets HookMaxGas to DefaultHookMaxGas if it's zero. Please ensure this default value is sufficient for the new JSON precompile operations that will be used in hooks.

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.

2 participants