Skip to content

Conversation

@aarmoa
Copy link
Collaborator

@aarmoa aarmoa commented Dec 22, 2025

  • Adds support for the new Chainlink Data Streams oracle messages

Solves C-655

Summary by CodeRabbit

  • New Features

    • Chainlink Data Streams integration: relay message, verifier settings, new oracle queries and params.
    • Major Exchange v2 additions: improved matching engine, VWAP tracking, spot & derivative batch execution, fee-discount staking, and market param toggles for disabling minimal protocol fees.
    • Permissions extended: wasm + EVM contract hook support; new stake-grants messages.
  • Bug Fixes

    • Improved event/error handling across exchange and oracle flows.
  • Chores

    • Protocol/codec and protobuf updates; OFAC list extended.

✏️ Tip: You can customize this high-level summary in your review settings.

…71. Includes support for the new Chainlink oracle messages.
@aarmoa aarmoa requested a review from Copilot December 22, 2025 17:17
@coderabbitai
Copy link

coderabbitai bot commented Dec 22, 2025

Walkthrough

This PR adds Chainlink Data Streams support to the oracle, extensive Exchange v2 features (derivative matching, VWAP, fee-discounts, new messages/validators), upgrades protobufs and protos for markets/proposals/permissions, modifies EVM precompile bindings to include Failure events, and refactors EVM log decoding and various APIs.

Changes

Cohort / File(s) Summary
Makefile version updates
Makefile
Updated clone targets: clone-injective-indexer now uses v1.17.71; clone-injective-core now uses branch c-655/add_chainlink_data_streams_oracle.
EVM precompile event bindings
chain/evm/precompiles/bank/fixed_supply_bank_erc20.abigen.go, chain/evm/precompiles/bank/mint_burn_bank_erc20.abigen.go
Added Failure event support: event structs, iterators (Next/Error/Close), Filter/Watch/Parse methods, and updated ABI/Bin metadata to include Failure.
EVM precompile ABI updates
chain/evm/precompiles/bank/i_bank_module.abigen.go, chain/evm/precompiles/exchange/i_exchange_module.abigen.go, chain/evm/precompiles/staking/i_staking_module.abigen.go
Reformatted/expanded ABI JSON literals; Exchange ABI changed numeric fields to ExchangeTypes.UFixed256x18 for order structures.
EVM log decoding refactor
chain/evm/types/events.go, chain/evm/types/utils.go
Removed constants EventTypeTxLog and AttributeKeyTxLog; refactored DecodeMsgLogs and DecodeTxLogs signatures to drop events-based fallback and decode directly from tx responses; removed related helpers.
Exchange module codec and errors
chain/exchange/types/codec.go, chain/exchange/types/errors.go, chain/exchange/types/expected_keepers.go
Registered new Amino/interface types (MsgDecreasePositionMargin, MsgEmergencySettleMarket, MsgAuthorizeStakeGrants, MsgActivateStakeGrant); added errors ErrOpenNotionalCapBreached, ErrNoOffsettingPositionsFound; updated OracleKeeper method signatures (scaling options, cumulative price returns) and added GetProviderPriceState.
Exchange message & proposal validation
chain/exchange/types/msgs.go, chain/exchange/types/proposal.go
Added duplicate-grantee detection in MsgAuthorizeStakeGrants.ValidateBasic; introduced centralized AdminInfo.ValidateBasic() and used it across multiple proposal ValidateBasic implementations; extended OracleParams validation to accept ChainlinkDataStreams oracle type.
Exchange v2 codec & message validators
chain/exchange/types/v2/codec.go, chain/exchange/types/v2/msgs.go, chain/exchange/types/v2/proposal.go
Registered new v2 messages and oneof implementations; added validators ValidateSpotMarketOrder, ValidateDerivativeMarketOrder, ValidateBinaryOptionsMarketOrder; added has_disabled_minimal_protocol_fee handling to market param update proposals and constructors.
Exchange v2 authz logic
chain/exchange/types/v2/authz_exchange_generic.go
Simplified Accept() flow for spend limits: early-return when no limit, single-pass hold validation and in-place SpendLimit updates.
Exchange v2 derivative matching system
chain/exchange/types/v2/derivative.go
New comprehensive derivative matching/VWAP subsystem: ordering logic, cancellation helpers, trackers/caches (ReduceOnlyOrdersTracker, ModifiedPositionCache), expansion data types, batch execution assembly, VWAP computation, and position-state utilities.
Exchange v2 fee discount system
chain/exchange/types/v2/fee_discounts.go
Introduced fee-discount staking subsystem: FeeDiscountConfig, FeeDiscountStakingInfo, ValidatorCache, contribution tracking, grant checkpoints, concurrency-safe maps and sorting/accessor helpers.
Exchange v2 market structures
chain/exchange/types/v2/market.go
Added MarketIDQuoteDenomMakerFee type; DerivativeMarketInfo.Funding field; new MarketI/DerivativeMarketI interfaces; IsMarketSolvent and GetMarketBalanceDelta utilities; GetDisabledMinimalProtocolFee methods added to market types.
Exchange v2 spot market system
chain/exchange/types/v2/spot.go
Added spot v2 types: OrderFillType, OrderbookFills, SpotOrderbookMatchingResults, SpotOrderStateExpansion, SpotBatchExecutionData, Spot VWAP types and batch event assembly helpers.
Exchange v2 subaccount aggregation
chain/exchange/types/v2/subaccount.go
Added SubaccountOrderMetadata, SubaccountOrderResults, accumulation methods, and accessors for cumulative vanilla/reduce-only/better-reduce-only quantities.
Exchange v2 trade fee data
chain/exchange/types/v2/trade.go
Added TradeFeeData struct and NewEmptyTradeFeeData constructor for fee/reward accounting.
Oracle: Chainlink Data Streams additions
chain/oracle/types/errors.go, chain/oracle/types/msgs.go, chain/oracle/types/oracle.go, chain/oracle/types/params.go
Added ErrChainlinkVerificationFailed; added MsgRelayChainlinkPrices message and methods; extended OracleType with ChainlinkDataStreams; added Params fields ChainlinkVerifierProxyContract, AcceptUnverifiedChainlinkDataStreamsReports, ChainlinkDataStreamsVerificationGasLimit; added ValidateChainlinkVerifierProxyContract.
Proto: oracle CRDs & RPCs
proto/injective/oracle/v1beta1/events.proto, proto/injective/oracle/v1beta1/genesis.proto, proto/injective/oracle/v1beta1/oracle.proto, proto/injective/oracle/v1beta1/query.proto, proto/injective/oracle/v1beta1/tx.proto
Added EventSetChainlinkDataStreamsPrices; added genesis field for chainlink price states; added ChainlinkDataStreamsPriceState and ChainlinkReport messages; added ChainlinkDataStreamsPriceStates query RPC and RelayChainlinkPrices Msg RPC and messages.
Proto: exchange market & proposals changes
proto/injective/exchange/v1beta1/exchange.proto, proto/injective/exchange/v1beta1/query.proto, proto/injective/exchange/v2/market.proto, proto/injective/exchange/v2/query.proto, proto/injective/exchange/v2/proposal.proto
Updated OpenNotionalCap amino oneof names to fully-qualified names; changed HTTP paths for SubaccountPositions/PositionsInMarket queries; added has_disabled_minimal_protocol_fee fields to Spot/BinaryOptions/Derivative market protos; deprecated combined expiration_twap_start_price_cumulative and added separate base/quote cumulative fields; added DisableMinimalProtocolFeeUpdate enum and proposal fields.
Proto: permissions restructure
proto/injective/permissions/v1beta1/params.proto, proto/injective/permissions/v1beta1/permissions.proto, proto/injective/permissions/v1beta1/tx.proto
Renamed wasm_hook_query_max_gascontract_hook_max_gas in Params; renamed contract_hookwasm_hook in Namespace and added evm_hook; updated MsgUpdateNamespace to use wasm_hook and new evm_hook.
Examples & SDK usage updates
examples/chain/permissions/1_MsgCreateNamespace/example.go, examples/chain/permissions/2_MsgUpdateNamespace/example.go
Updated examples to use Namespace.WasmHook and added Namespace.EvmHook; replaced ContractHook usage.
Dependency & data updates
go.mod, injective_data/chain_messages_list.json, injective_data/ofac.json
Downgraded cometbft/cometbft replace to v1.0.1-inj.3; added injective.oracle.v1beta1.MsgRelayChainlinkPrices to chain messages list; appended three addresses to injective_data/ofac.json.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes

  • Areas requiring extra attention:
    • chain/exchange/types/v2/derivative.go — complex matching, VWAP, batch execution and state transitions.
    • chain/exchange/types/v2/fee_discounts.go — concurrency (RWMutex) correctness and volume/tier calculations.
    • chain/evm/types/utils.go — changed log-decoding signatures and removed fallback paths; verify all call sites and integration.
    • chain/exchange/types/expected_keepers.go — keeper interface signature changes; update implementations and mocks.
    • proto changes (exchange/oracle/permissions) — regenerations (gogo/proto) and downstream consumers; field renames/additions may be breaking.
    • chain/oracle/types/params.go — new params, validation and Ethereum address parsing.

Poem

🐇 I nibble bytes and hop through streams,
Chainlink whispers in ledger dreams,
VWAP and fees in careful measure,
Hooks split to wasm and EVM treasure,
Hoppity builds — a rabbit's code-of-pleasure 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.25% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[C-655] add chainlink data streams oracle' clearly summarizes the main objective—adding support for Chainlink Data Streams oracle functionality. It is specific, concise, and directly reflects the primary changes across the codebase.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch c-655/add_chainlink_data_streams_oracle

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 31af78e and 5d03de9.

📒 Files selected for processing (2)
  • examples/chain/permissions/1_MsgCreateNamespace/example.go
  • examples/chain/permissions/2_MsgUpdateNamespace/example.go
🧰 Additional context used
🧬 Code graph analysis (1)
examples/chain/permissions/2_MsgUpdateNamespace/example.go (1)
chain/permissions/types/tx.pb.go (3)
  • MsgUpdateNamespace_SetContractHook (326-328)
  • MsgUpdateNamespace_SetContractHook (332-332)
  • MsgUpdateNamespace_SetContractHook (333-335)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: lint
  • GitHub Check: run-tests
🔇 Additional comments (2)
examples/chain/permissions/1_MsgCreateNamespace/example.go (1)

122-122: Field updates properly completed for WasmHook.

The rename from ContractHook to WasmHook has been successfully applied—no remaining ContractHook field references exist in the Namespace struct. The WasmHook field is in use as shown in the codebase.

Note: The underlying protobuf message type still references SetContractHook in its name (e.g., MsgUpdateNamespace_SetContractHook), which appears intentional for backward compatibility. Verify that the EvmHook mentioned in the comment is fully implemented and available in the Namespace struct definition, as no usage was found in the codebase search.

examples/chain/permissions/2_MsgUpdateNamespace/example.go (1)

106-106: Field rename is correct and complete.

Verification confirms all references to the ContractHook field in MsgUpdateNamespace have been updated to WasmHook. The proto changes are properly reflected throughout the codebase, including the example file at line 106 and the generated tx.pb.go protobuf definitions.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

The pull request adds support for Chainlink Data Streams oracle messages to the Injective chain. This integration extends the existing oracle module to handle a new oracle type alongside existing providers like Pyth and Stork.

Key changes:

  • Introduces ChainlinkDataStreams oracle type with price state management
  • Adds RPC methods for relaying Chainlink prices and querying price states
  • Implements permissions module enhancements to support separate WASM and EVM contract hooks
  • Updates market parameters to support minimal protocol fee disabling
  • Adds validation for Chainlink verifier proxy contract addresses

Reviewed changes

Copilot reviewed 61 out of 63 changed files in this pull request and generated no comments.

Show a summary per file
File Description
proto/injective/oracle/v1beta1/* Defines Chainlink Data Streams messages, events, and query endpoints
proto/injective/permissions/v1beta1/* Separates contract hooks into wasm_hook and evm_hook fields
proto/injective/exchange/v2/* Adds has_disabled_minimal_protocol_fee field to market proposals
chain/oracle/types/params.go Adds Chainlink verifier proxy contract validation
chain/oracle/types/oracle.go Registers ChainlinkDataStreams oracle type
go.mod Downgrades cometbft dependency version
exchange//pb/.go Generated protobuf code updates
Comments suppressed due to low confidence (6)

proto/injective/oracle/v1beta1/tx.proto:1

  • The comment incorrectly states this message is for updating Pyth prices, but the message is named MsgRelayChainlinkPrices. Update the comment to reference Chainlink Data Streams instead of Pyth.
    proto/injective/oracle/v1beta1/query.proto:1
  • Missing space between 'Streams' and 'price' in the comment.
    go.mod:1
  • The cometbft dependency is being downgraded from v1.0.1-inj.4 to v1.0.1-inj.3. Verify this version downgrade is intentional and won't introduce compatibility issues or missing features needed by this PR.
    proto/injective/exchange/v2/proposal.proto:1
  • The enum name DisableMinimalProtocolFeeUpdate is confusing because the values False and True suggest a boolean state rather than an update operation. Consider renaming to MinimalProtocolFeeStatus or using more descriptive value names like KEEP_CURRENT, ENABLE, DISABLE.
    proto/injective/exchange/v2/market.proto:1
  • The amino.oneof_name values include the full package prefix. Verify this is the intended format for amino encoding, as the previous version used simpler names like 'uncapped' and 'capped'. This change could affect serialization compatibility.
    proto/injective/exchange/v2/market.proto:1
  • The deprecation comment provides good context. Ensure migration guides or release notes document this breaking change and guide users to update their code to use the new fields.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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

🧹 Nitpick comments (12)
proto/injective/permissions/v1beta1/params.proto (1)

15-16: Consider naming consistency and gas limit granularity.

Two observations:

  1. Naming inconsistency: This field is named contract_hook_max_gas, while permissions.proto and tx.proto now use explicit wasm_hook/evm_hook naming. Consider whether this should be renamed for consistency (e.g., to a more generic name) or if separate limits are needed.

  2. Single gas limit: With distinct WASM and EVM hooks now supported, verify whether a single shared gas limit is intentional. EVM and CosmWasm have different gas semantics, so separate limits (wasm_hook_max_gas / evm_hook_max_gas) might provide finer control.

Makefile (1)

7-7: Verify that the feature branch reference is intentional.

The clone-injective-core target now references a feature branch (c-655/add_chainlink_data_streams_oracle) instead of a tagged release. While this is appropriate during development, consider:

  1. Before merging this PR, the core dependency should likely point to a stable release tag
  2. Feature branches can be rebased or force-pushed, leading to non-reproducible builds
  3. If this is intentional for coordinated development across repositories, document the dependency relationship
chain/exchange/types/v2/subaccount.go (1)

77-85: Consider adding nil guard for defensive coding.

AddSubaccountOrder assumes d and d.Order are non-nil. If called with a nil argument, this will panic. If callers are guaranteed to pass valid data, this is fine; otherwise, consider adding a nil check.

🔎 Optional defensive nil check
 func (r *SubaccountOrderResults) AddSubaccountOrder(d *SubaccountOrderData) {
+	if d == nil || d.Order == nil {
+		return
+	}
 	if d.Order.IsReduceOnly {
 		r.ReduceOnlyOrders = append(r.ReduceOnlyOrders, d)
chain/exchange/types/v2/spot.go (2)

22-35: Silent fallthrough for unknown OrderFillType may mask bugs.

The default return of TransientSellOrderbookFills for unknown fill types could hide programming errors. Consider returning nil to make unhandled cases explicit, or panic if this represents an invariant violation.

🔎 Suggested fix
 func (r *SpotOrderbookMatchingResults) GetOrderbookFills(fillType OrderFillType) *OrderbookFills {
 	switch fillType {
 	case RestingLimitBuy:
 		return r.RestingBuyOrderbookFills
 	case RestingLimitSell:
 		return r.RestingSellOrderbookFills
 	case TransientLimitBuy:
 		return r.TransientBuyOrderbookFills
 	case TransientLimitSell:
 		return r.TransientSellOrderbookFills
+	default:
+		return nil
 	}
-
-	return r.TransientSellOrderbookFills
 }

228-240: Minor: simplify variable declaration.

The existingVwapData declaration and immediate assignment can be combined.

🔎 Simplified variable initialization
 func (p *SpotVwapInfo) ApplyVwap(marketID common.Hash, newVwapData *SpotVwapData) {
-	var existingVwapData *SpotVwapData
-
-	existingVwapData = (*p)[marketID]
+	existingVwapData := (*p)[marketID]
 	if existingVwapData == nil {
 		existingVwapData = NewSpotVwapData()
 		(*p)[marketID] = existingVwapData
 	}
chain/exchange/types/v2/fee_discounts.go (1)

274-321: Incorrect slice capacity and inefficient sort comparison.

  1. Line 278 uses len(info.AccountFeeTiers) as capacity for subaccountVolumes, but iterates over the nested SubaccountMarketVolumeContributions map.

  2. Lines 301-305 use append inside the sort comparison function, which creates temporary allocations on every comparison call. Consider pre-computing the concatenated keys.

🔎 Proposed optimization
 func (info *FeeDiscountStakingInfo) GetSortedSubaccountAndMarketVolumes() (
 	[]*SubaccountVolumeContribution,
 	[]*MarketVolumeContribution,
 ) {
-	subaccountVolumes := make([]*SubaccountVolumeContribution, 0, len(info.AccountFeeTiers))
+	subaccountVolumes := make([]*SubaccountVolumeContribution, 0)
 	marketVolumeTracker := make(map[common.Hash]VolumeRecord)
 
 	// ... iteration code unchanged ...
 
 	info.AccountVolumesMux.RUnlock()
 
+	// Pre-compute sort keys to avoid allocations in comparison
+	type sortKey struct {
+		idx int
+		key []byte
+	}
+	keys := make([]sortKey, len(subaccountVolumes))
+	for i, sv := range subaccountVolumes {
+		keys[i] = sortKey{idx: i, key: append(sv.SubaccountID.Bytes(), sv.MarketID.Bytes()...)}
+	}
+	sort.SliceStable(keys, func(i, j int) bool {
+		return bytes.Compare(keys[i].key, keys[j].key) < 0
+	})
+	sorted := make([]*SubaccountVolumeContribution, len(subaccountVolumes))
+	for i, k := range keys {
+		sorted[i] = subaccountVolumes[k.idx]
+	}
+	subaccountVolumes = sorted
-	sort.SliceStable(subaccountVolumes, func(i, j int) bool {
-		return bytes.Compare(
-			append(subaccountVolumes[i].SubaccountID.Bytes(), subaccountVolumes[i].MarketID.Bytes()...),
-			append(subaccountVolumes[j].SubaccountID.Bytes(), subaccountVolumes[j].MarketID.Bytes()...),
-		) < 0
-	})
proto/injective/exchange/v2/proposal.proto (1)

82-86: Consider clarifying field naming for readability.

The field has_disabled_minimal_protocol_fee uses a double-negative construction ("disabled" + negative enum values). While functionally correct and likely matching the market type's field name, it can be confusing:

  • True means "fee is disabled" (no fee)
  • False means "fee is not disabled" (fee applies)

If this naming is intentional to match the market state field, consider adding a brief comment to clarify the semantics. Otherwise, a positive framing like minimal_protocol_fee_enabled with inverted enum values might be clearer.

Also applies to: 490-493, 590-593

proto/injective/oracle/v1beta1/tx.proto (1)

167-181: Fix stale comment above MsgRelayChainlinkPrices

The comment still references Pyth instead of Chainlink, which can confuse readers.

Proposed comment fix
-// MsgRelayPythPrices defines a SDK message for updating Pyth prices
+// MsgRelayChainlinkPrices defines a SDK message for relaying Chainlink prices
 message MsgRelayChainlinkPrices {
chain/oracle/types/msgs.go (1)

406-433: MsgRelayChainlinkPrices wiring mirrors existing Pyth relay semantics

Route, Type, GetSignBytes, and GetSigners are implemented consistently with the other oracle messages, and ValidateBasic correctly enforces a valid bech32 sender address.

If the handler relies on at least one reports entry, you may optionally enforce len(msg.Reports) > 0 here to fail fast on obviously empty relays; otherwise, current behaviour matches the Pyth relay pattern.

chain/exchange/types/v2/msgs.go (1)

965-973: Centralized validation for market orders; post‑only now rejected for market messages

The new helpers and their wiring introduce a clear, consistent validation policy:

  • ValidateSpotMarketOrder / ValidateDerivativeMarketOrder / ValidateBinaryOptionsMarketOrder:
    • Reject BUY_PO / SELL_PO for all market orders, which aligns with “post‑only” being a limit‑order concept.
    • For binary options, additionally reject conditional types for market orders and reuse the existing binary band validation via order.ValidateBasic(senderAddr, true).
  • MsgCreateSpotMarketOrder, MsgCreateDerivativeMarketOrder, and MsgCreateBinaryOptionsMarketOrder now delegate to these helpers.
  • MsgBatchUpdateOrders.ValidateBasic now applies the same helpers to SpotMarketOrdersToCreate, DerivativeMarketOrdersToCreate, and BinaryOptionsMarketOrdersToCreate, ensuring single and batched flows share identical rules.

Net effect: any client that previously sent post‑only market orders will now receive ErrInvalidOrderTypeForMessage. That looks intentional but is a behavioural change worth being aware of.

As a minor defensive improvement, you could also nil‑check the order pointer in each helper before dereferencing, in case a malformed batch ever contained a nil entry.

Also applies to: 2110-2126, 2727-2752

chain/exchange/types/v2/derivative.go (2)

906-908: Remove commented-out debug code.

This commented-out debug statement should be removed before merging.

🔎 Proposed fix
 		if position.Position != nil {
 			positions = append(positions, position.Position)
 			nonNilPositionSubaccountIDs = append(nonNilPositionSubaccountIDs, subaccountID)
 		}
-
-		// else {
-		// 	fmt.Println("❌ position is nil for subaccount", subaccountID.Hex())
-		// }
 	}

134-146: Consider documenting the nil position indicator pattern.

SetPosition silently returns when position is nil, while SetPositionIndicator explicitly sets a nil position. This asymmetry could lead to confusion. Consider adding a brief comment explaining the intended usage pattern for position indicators.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9bfddd and 31af78e.

⛔ Files ignored due to path filters (20)
  • chain/exchange/types/exchange.pb.go is excluded by !**/*.pb.go
  • chain/exchange/types/query.pb.go is excluded by !**/*.pb.go
  • chain/exchange/types/v2/market.pb.go is excluded by !**/*.pb.go
  • chain/exchange/types/v2/proposal.pb.go is excluded by !**/*.pb.go
  • chain/exchange/types/v2/query.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/events.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/genesis.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/oracle.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/query.pb.go is excluded by !**/*.pb.go
  • chain/oracle/types/tx.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/params.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/permissions.pb.go is excluded by !**/*.pb.go
  • chain/permissions/types/tx.pb.go is excluded by !**/*.pb.go
  • exchange/auction_rpc/pb/goadesign_goagen_injective_auction_rpc.pb.go is excluded by !**/*.pb.go
  • exchange/auction_rpc/pb/goadesign_goagen_injective_auction_rpc_grpc.pb.go is excluded by !**/*.pb.go
  • exchange/derivative_exchange_rpc/pb/goadesign_goagen_injective_derivative_exchange_rpc.pb.go is excluded by !**/*.pb.go
  • exchange/event_provider_api/pb/goadesign_goagen_event_provider_api.pb.go is excluded by !**/*.pb.go
  • exchange/oracle_rpc/pb/goadesign_goagen_injective_oracle_rpc.pb.go is excluded by !**/*.pb.go
  • exchange/portfolio_rpc/pb/goadesign_goagen_injective_portfolio_rpc.pb.go is excluded by !**/*.pb.go
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (43)
  • Makefile
  • chain/evm/precompiles/bank/fixed_supply_bank_erc20.abigen.go
  • chain/evm/precompiles/bank/i_bank_module.abigen.go
  • chain/evm/precompiles/bank/mint_burn_bank_erc20.abigen.go
  • chain/evm/precompiles/exchange/i_exchange_module.abigen.go
  • chain/evm/precompiles/staking/i_staking_module.abigen.go
  • chain/evm/types/events.go
  • chain/evm/types/utils.go
  • chain/exchange/types/codec.go
  • chain/exchange/types/errors.go
  • chain/exchange/types/expected_keepers.go
  • chain/exchange/types/msgs.go
  • chain/exchange/types/proposal.go
  • chain/exchange/types/v2/authz_exchange_generic.go
  • chain/exchange/types/v2/codec.go
  • chain/exchange/types/v2/derivative.go
  • chain/exchange/types/v2/fee_discounts.go
  • chain/exchange/types/v2/market.go
  • chain/exchange/types/v2/msgs.go
  • chain/exchange/types/v2/proposal.go
  • chain/exchange/types/v2/spot.go
  • chain/exchange/types/v2/subaccount.go
  • chain/exchange/types/v2/trade.go
  • chain/oracle/types/errors.go
  • chain/oracle/types/msgs.go
  • chain/oracle/types/oracle.go
  • chain/oracle/types/params.go
  • go.mod
  • injective_data/chain_messages_list.json
  • injective_data/ofac.json
  • proto/injective/exchange/v1beta1/exchange.proto
  • proto/injective/exchange/v1beta1/query.proto
  • proto/injective/exchange/v2/market.proto
  • proto/injective/exchange/v2/proposal.proto
  • proto/injective/exchange/v2/query.proto
  • proto/injective/oracle/v1beta1/events.proto
  • proto/injective/oracle/v1beta1/genesis.proto
  • proto/injective/oracle/v1beta1/oracle.proto
  • proto/injective/oracle/v1beta1/query.proto
  • proto/injective/oracle/v1beta1/tx.proto
  • proto/injective/permissions/v1beta1/params.proto
  • proto/injective/permissions/v1beta1/permissions.proto
  • proto/injective/permissions/v1beta1/tx.proto
🧰 Additional context used
🧬 Code graph analysis (16)
chain/oracle/types/errors.go (1)
chain/oracle/types/key.go (1)
  • ModuleName (12-12)
chain/exchange/types/msgs.go (1)
chain/exchange/types/errors.go (2)
  • ErrInvalidAddress (91-91)
  • ErrInvalidStakeGrant (110-110)
chain/exchange/types/v2/trade.go (1)
chain/exchange/types/trading_rewards.go (1)
  • TradingRewardPoints (9-9)
chain/exchange/types/errors.go (6)
chain/exchange/types/key.go (1)
  • ModuleName (17-17)
chain/peggy/types/key.go (1)
  • ModuleName (10-10)
chain/permissions/types/codec.go (1)
  • ModuleName (12-12)
chain/oracle/types/key.go (1)
  • ModuleName (12-12)
chain/wasmx/types/key.go (1)
  • ModuleName (10-10)
chain/ocr/types/key.go (1)
  • ModuleName (12-12)
chain/exchange/types/codec.go (4)
chain/exchange/types/tx.pb.go (15)
  • MsgDecreasePositionMargin (2899-2911)
  • MsgDecreasePositionMargin (2915-2915)
  • MsgDecreasePositionMargin (2916-2918)
  • MsgLiquidatePosition (2573-2582)
  • MsgLiquidatePosition (2586-2586)
  • MsgLiquidatePosition (2587-2589)
  • MsgEmergencySettleMarket (2683-2690)
  • MsgEmergencySettleMarket (2694-2694)
  • MsgEmergencySettleMarket (2695-2697)
  • MsgAuthorizeStakeGrants (3504-3507)
  • MsgAuthorizeStakeGrants (3511-3511)
  • MsgAuthorizeStakeGrants (3512-3514)
  • MsgActivateStakeGrant (3593-3596)
  • MsgActivateStakeGrant (3600-3600)
  • MsgActivateStakeGrant (3601-3603)
chain/exchange/types/v2/tx.pb.go (15)
  • MsgDecreasePositionMargin (3050-3062)
  • MsgDecreasePositionMargin (3066-3066)
  • MsgDecreasePositionMargin (3067-3069)
  • MsgLiquidatePosition (2617-2626)
  • MsgLiquidatePosition (2630-2630)
  • MsgLiquidatePosition (2631-2633)
  • MsgEmergencySettleMarket (2834-2841)
  • MsgEmergencySettleMarket (2845-2845)
  • MsgEmergencySettleMarket (2846-2848)
  • MsgAuthorizeStakeGrants (3658-3663)
  • MsgAuthorizeStakeGrants (3667-3667)
  • MsgAuthorizeStakeGrants (3668-3670)
  • MsgActivateStakeGrant (3749-3754)
  • MsgActivateStakeGrant (3758-3758)
  • MsgActivateStakeGrant (3759-3761)
chain/exchange/types/v2/market.pb.go (4)
  • OpenNotionalCap_Uncapped (109-111)
  • OpenNotionalCap_Uncapped (116-116)
  • OpenNotionalCap_Capped (112-114)
  • OpenNotionalCap_Capped (117-117)
chain/exchange/types/v2/query.pb.go (4)
  • FullDerivativeMarket_PerpetualInfo (3321-3323)
  • FullDerivativeMarket_PerpetualInfo (3328-3328)
  • FullDerivativeMarket_FuturesInfo (3324-3326)
  • FullDerivativeMarket_FuturesInfo (3329-3329)
chain/exchange/types/expected_keepers.go (2)
chain/oracle/types/oracle.pb.go (5)
  • OracleType (32-32)
  • OracleType (89-91)
  • PriceRecords (1304-1308)
  • PriceRecords (1312-1312)
  • PriceRecords (1313-1315)
chain/oracle/types/query.pb.go (6)
  • ScalingOptions (1604-1607)
  • ScalingOptions (1611-1611)
  • ScalingOptions (1612-1614)
  • PricePairState (1726-1734)
  • PricePairState (1738-1738)
  • PricePairState (1739-1741)
chain/exchange/types/v2/msgs.go (1)
chain/exchange/types/errors.go (4)
  • ErrInvalidAddress (91-91)
  • ErrInvalidStakeGrant (110-110)
  • ErrInvalidOrderTypeForMessage (68-68)
  • ErrUnrecognizedOrderType (15-15)
chain/exchange/types/v2/subaccount.go (1)
chain/exchange/types/exchange.pb.go (3)
  • SubaccountOrderData (1812-1815)
  • SubaccountOrderData (1819-1819)
  • SubaccountOrderData (1820-1822)
chain/exchange/types/v2/codec.go (4)
chain/exchange/types/v2/tx.pb.go (12)
  • MsgDecreasePositionMargin (3050-3062)
  • MsgDecreasePositionMargin (3066-3066)
  • MsgDecreasePositionMargin (3067-3069)
  • MsgEmergencySettleMarket (2834-2841)
  • MsgEmergencySettleMarket (2845-2845)
  • MsgEmergencySettleMarket (2846-2848)
  • MsgAuthorizeStakeGrants (3658-3663)
  • MsgAuthorizeStakeGrants (3667-3667)
  • MsgAuthorizeStakeGrants (3668-3670)
  • MsgActivateStakeGrant (3749-3754)
  • MsgActivateStakeGrant (3758-3758)
  • MsgActivateStakeGrant (3759-3761)
chain/exchange/types/v2/proposal.pb.go (3)
  • DenomMinNotionalProposal (1260-1264)
  • DenomMinNotionalProposal (1268-1268)
  • DenomMinNotionalProposal (1269-1271)
chain/exchange/types/v2/market.pb.go (4)
  • OpenNotionalCap_Uncapped (109-111)
  • OpenNotionalCap_Uncapped (116-116)
  • OpenNotionalCap_Capped (112-114)
  • OpenNotionalCap_Capped (117-117)
chain/exchange/types/v2/query.pb.go (4)
  • FullDerivativeMarket_PerpetualInfo (3321-3323)
  • FullDerivativeMarket_PerpetualInfo (3328-3328)
  • FullDerivativeMarket_FuturesInfo (3324-3326)
  • FullDerivativeMarket_FuturesInfo (3329-3329)
chain/oracle/types/oracle.go (1)
chain/oracle/types/oracle.pb.go (1)
  • OracleType_ChainlinkDataStreams (48-48)
chain/exchange/types/proposal.go (5)
chain/exchange/types/v2/proposal.pb.go (3)
  • AdminInfo (614-617)
  • AdminInfo (621-621)
  • AdminInfo (622-624)
chain/exchange/types/proposal.pb.go (3)
  • AdminInfo (566-569)
  • AdminInfo (573-573)
  • AdminInfo (574-576)
chain/oracle/types/oracle.pb.go (2)
  • OracleType_Stork (47-47)
  • OracleType_ChainlinkDataStreams (48-48)
chain/exchange/types/errors.go (2)
  • ErrInvalidAddress (91-91)
  • ErrInvalidPermissions (112-112)
chain/exchange/types/market_admin.go (1)
  • MaxPerm (13-14)
chain/oracle/types/params.go (1)
chain/oracle/types/oracle.pb.go (3)
  • Params (93-98)
  • Params (102-102)
  • Params (103-105)
chain/evm/precompiles/bank/mint_burn_bank_erc20.abigen.go (1)
ethereum/util/contract.go (1)
  • BoundContract (27-35)
chain/exchange/types/v2/proposal.go (4)
chain/exchange/types/v2/proposal.pb.go (6)
  • DisableMinimalProtocolFeeUpdate (33-33)
  • DisableMinimalProtocolFeeUpdate (57-59)
  • DisableMinimalProtocolFeeUpdate_NoUpdate (36-36)
  • AdminInfo (614-617)
  • AdminInfo (621-621)
  • AdminInfo (622-624)
chain/oracle/types/oracle.pb.go (4)
  • OracleType_BandIBC (45-45)
  • OracleType_Provider (46-46)
  • OracleType_Stork (47-47)
  • OracleType_ChainlinkDataStreams (48-48)
chain/exchange/types/errors.go (2)
  • ErrInvalidAddress (91-91)
  • ErrInvalidPermissions (112-112)
chain/exchange/types/market_admin.go (1)
  • MaxPerm (13-14)
chain/exchange/types/v2/derivative.go (6)
chain/exchange/types/v2/market.go (2)
  • DerivativeMarket (211-213)
  • DerivativeMarket (223-225)
chain/exchange/types/deposit.go (3)
  • NewDepositDeltas (42-44)
  • DepositDeltas (40-40)
  • DepositDelta (11-14)
chain/exchange/types/trading_rewards.go (2)
  • NewTradingRewardPoints (11-15)
  • TradingRewardPoints (9-9)
chain/exchange/types/market.go (1)
  • NotionalToChainFormat (130-136)
chain/exchange/types/v2/common_utils.go (2)
  • DerivativeLimitOrderDelta (15-19)
  • DerivativeMarketOrderDelta (21-24)
exchange/portfolio_rpc/pb/goadesign_goagen_injective_portfolio_rpc.pb.go (3)
  • DerivativePosition (635-672)
  • DerivativePosition (687-687)
  • DerivativePosition (702-704)
chain/evm/precompiles/bank/fixed_supply_bank_erc20.abigen.go (1)
ethereum/util/contract.go (1)
  • BoundContract (27-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Socket Security: Pull Request Alerts
  • GitHub Check: run-tests
  • GitHub Check: lint
🔇 Additional comments (69)
proto/injective/permissions/v1beta1/permissions.proto (1)

13-14: LGTM – EVM hook support added correctly.

The field renaming from contract_hook to wasm_hook (field 2) and addition of evm_hook (field 8) are well-structured. Field numbers are preserved, ensuring protobuf wire compatibility.

Note: Renaming contract_hookwasm_hook changes the JSON field name, which could be a breaking change for clients using JSON encoding. Ensure downstream consumers are updated accordingly.

Also applies to: 26-28

proto/injective/permissions/v1beta1/tx.proto (1)

65-77: LGTM – Consistent with permissions.proto changes.

The SetContractHook type is appropriately reused for both wasm_hook (field 3) and evm_hook (field 8). Field numbers are preserved, maintaining wire compatibility.

Same consideration as noted in permissions.proto: the JSON field name change from contract_hook to wasm_hook may affect JSON-based clients.

go.mod (1)

256-256: No action required. The cometbft version change is part of the coordinated C-655 PR that updates proto definitions to chain v1.18.0 and indexer v1.17.71 and adds Chainlink oracle support, as evidenced by the oracle.proto file changes showing new ChainlinkDataStreams enum and Chainlink-related configuration parameters.

chain/oracle/types/errors.go (1)

51-51: LGTM!

The new error definition follows the existing error registration pattern and provides a clear message for Chainlink report verification failures. The error code (44) is sequential and appropriate.

chain/evm/precompiles/staking/i_staking_module.abigen.go (1)

40-40: LGTM - Generated code with improved ABI format.

The ABI string has been reformatted to use explicit field names (type, name, internalType), which improves readability while maintaining functional equivalence. Since this is generated code (as indicated by the file header), the change results from regenerating the bindings with an updated toolchain.

chain/evm/precompiles/bank/i_bank_module.abigen.go (1)

34-34: LGTM - Generated code with improved ABI format.

Consistent with the staking module binding, the ABI string has been reformatted to use explicit field names. This is generated code with improved readability and no functional changes.

chain/exchange/types/errors.go (1)

120-121: LGTM!

The two new error definitions follow the established error registration pattern and use sequential error codes (112, 113). The error messages clearly describe the failure conditions related to open notional cap validation and offsetting position requirements.

chain/evm/types/events.go (1)

15-15: No internal references to removed constants found.

The constants EventTypeTxLog and AttributeKeyTxLog are not referenced elsewhere in the codebase, so the removal does not break internal dependencies. If these constants are part of a public API, ensure external consumers are notified of the deprecation or provide migration documentation separately.

proto/injective/exchange/v1beta1/exchange.proto (1)

23-28: Update amino.oneof_name changes to use fully qualified names for JSON encoding consistency.

The amino.oneof_name attributes have been updated to fully qualified names (injective.exchange.v1beta1.OpenNotionalCapUncapped and injective.exchange.v1beta1.OpenNotionalCapCapped). This improves naming consistency in amino JSON output but does not affect protobuf wire format compatibility (field numbers remain unchanged). No migration strategy is required unless downstream systems explicitly depend on parsing the old short-form strings from amino JSON output.

proto/injective/exchange/v2/query.proto (1)

265-265: The HTTP endpoint paths in the v2 proto file show version prefixes consistent with the v2 API structure. However, PositionsInMarket is a new endpoint introduced in V2 (not present in v1beta1), and SubaccountPositions maintained its endpoint structure with only the version prefix updated from v1beta1 to v2. These are not breaking changes to existing REST API endpoints but rather additions and version-specific routing, which is the expected behavior for versioned APIs.

Likely an incorrect or invalid review comment.

chain/exchange/types/proposal.go (3)

1655-1665: LGTM! Clean validation implementation for AdminInfo.

The ValidateBasic method correctly:

  • Validates the Admin address using sdk.AccAddressFromBech32 only when non-empty
  • Validates AdminPermissions against MaxPerm to ensure no invalid permission bits are set
  • Uses appropriate error types from the errors registry (ErrInvalidAddress, ErrInvalidPermissions)

679-686: LGTM! New oracle type correctly added to validation.

The OracleType_ChainlinkDataStreams is properly included in the valid oracle types switch case, consistent with its definition in the oracle protobuf (OracleType_ChainlinkDataStreams = 13).


290-294: LGTM! Consistent AdminInfo validation integration across proposals.

The AdminInfo.ValidateBasic() call is consistently integrated into all relevant proposal types with proper nil-check and early error return. This centralizes admin validation logic and maintains consistency.

Also applies to: 428-432, 535-539, 802-807, 903-908

chain/oracle/types/params.go (3)

55-59: Verify the default AcceptUnverifiedChainlinkDataStreamsReports = true.

Setting this to true by default means unverified Chainlink Data Streams reports will be accepted when no verifier proxy contract is configured. This may be intentional for initial rollout or testing, but please confirm this is the desired security posture for production.


116-132: LGTM! Proper Ethereum address validation.

The ValidateChainlinkVerifierProxyContract function correctly:

  • Accepts interface{} for compatibility with param validation patterns
  • Allows empty string for optional configuration
  • Uses common.IsHexAddress from go-ethereum for robust hex address validation

72-81: LGTM! Validation properly extended for new params.

The Validate() method correctly validates both contract addresses with descriptive error wrapping to identify which field failed.

chain/evm/types/utils.go (2)

87-97: LGTM! Simplified API with proper bounds checking.

The DecodeMsgLogs function now has a cleaner signature and includes proper bounds validation for msgIndex (lines 93-95) to prevent out-of-range access. The function correctly returns an error for invalid indices rather than panicking.


99-110: LGTM! Clean aggregation of logs across all responses.

The DecodeTxLogs function correctly iterates through all transaction responses and aggregates logs using the logsFromTxResponse helper, maintaining consistency with the single-message variant.

proto/injective/oracle/v1beta1/oracle.proto (3)

157-163: Verify intentional type difference for feed_id between messages.

ChainlinkDataStreamsPriceState.feed_id is defined as string (line 158), while ChainlinkReport.feed_id is defined as bytes (line 314).

This may be intentional (e.g., ChainlinkReport holds raw data from the report while ChainlinkDataStreamsPriceState stores a hex-encoded or readable version), but please confirm this is the intended design.

Also applies to: 313-318


11-19: LGTM! Params extended with proper field numbering.

The new Chainlink-related fields are added with sequential field numbers (2, 3, 4), maintaining protobuf wire compatibility. The field types are appropriate:

  • string for the contract address
  • bool for the feature flag
  • uint64 for the gas limit

21-36: LGTM! New oracle type properly added to enum.

ChainlinkDataStreams = 13 is correctly added following the existing sequence and maintains backward compatibility with existing enum values.

chain/exchange/types/expected_keepers.go (1)

31-59: Breaking interface changes require all external implementations to be updated.

The OracleKeeper interface in this SDK has breaking changes that affect any code implementing these methods:

  • GetPricePairState now requires scalingOptions *oracletypes.ScalingOptions parameter
  • GetCumulativePrice returns two values: (baseCumulative, quoteCumulative *sdkmath.LegacyDec)
  • GetHistoricalPriceRecords returns (entry *oracletypes.PriceRecords, omitted bool)
  • GetMixedHistoricalPriceRecords returns (mixed *oracletypes.PriceRecords, ok bool)

Any consumer of this SDK that implements the OracleKeeper interface must update their implementations to match these signatures.

chain/oracle/types/oracle.go (1)

40-41: LGTM!

The new chainlinkdatastreams case follows the established pattern of other oracle types in the switch statement.

proto/injective/oracle/v1beta1/genesis.proto (1)

45-47: LGTM!

The new chainlink_data_streams_price_states field follows the established pattern and uses the next sequential field number.

chain/exchange/types/v2/subaccount.go (1)

47-67: LGTM!

The constructor functions properly initialize all LegacyDec fields to zero and pre-allocate slices, following good initialization patterns.

proto/injective/exchange/v2/market.proto (3)

335-344: Well-documented deprecation.

The deprecation includes clear rationale and points to the new replacement fields. Retaining the field number ensures backward compatibility with existing data.


351-364: LGTM!

The new expiration_twap_start_base_cumulative_price and expiration_twap_start_quote_cumulative_price fields properly address the limitation of the deprecated field by tracking base and quote cumulative prices separately.


109-111: Consistent addition of has_disabled_minimal_protocol_fee across market types.

The field is added uniformly to SpotMarket, BinaryOptionsMarket, and DerivativeMarket with consistent naming and documentation.

Also applies to: 187-190, 278-281

chain/exchange/types/v2/spot.go (3)

204-219: LGTM on VWAP calculation logic.

The ApplyExecution method correctly handles nil receivers by creating a new instance, and guards against nil/zero quantity inputs. The weighted average calculation (oldPrice * oldQty + newPrice * newQty) / totalQty is mathematically correct for VWAP.


93-124: LGTM on deposit delta handling.

The UpdateFromDepositDeltas method correctly handles:

  • Positive change amounts being added to available balance
  • Zero subaccount fallback to auction subaccount for fee recipients
  • Proper application of trader and fee recipient deltas

126-190: LGTM on batch execution event construction.

The function properly:

  • Preallocates slices with appropriate capacity
  • Skips zero-fill trades to avoid empty entries
  • Handles self-relayed trade fee calculation correctly
  • Returns nil event when no trades occurred
chain/exchange/types/v2/fee_discounts.go (5)

84-95: LGTM - ValidatorCache type and NewFeeDiscountConfig constructor.

The defensive nil check for stakingInfo and setting isQualified = false is appropriate.


97-121: LGTM - FeeDiscountConfig struct and GetFeeDiscountRate method.

Proper nil receiver check and correct RLock/RUnlock pattern for concurrent access.


123-162: LGTM - IncrementAccountVolumeContribution implementation.

Defensive check for negative amounts, proper mutex locking, and correct map update patterns.


164-217: LGTM - FeeDiscountStakingInfo struct and constructor.

All maps and mutexes are properly initialized.


323-383: LGTM - Remaining getter/setter methods.

Proper mutex usage throughout. SetAccountTierInfo, SetNewAccountTierTTL, AddCheckpoint, and AddInvalidGrant all correctly use Lock/Unlock.

injective_data/chain_messages_list.json (1)

128-128: LGTM - New Chainlink message type registration.

The new MsgRelayChainlinkPrices message type is correctly added and properly positioned alphabetically within the oracle module namespace. This aligns with the PR objective of adding Chainlink data streams oracle support.

proto/injective/oracle/v1beta1/events.proto (1)

90-93: LGTM - New Chainlink data streams event.

The EventSetChainlinkDataStreamsPrices message follows the established pattern used by similar events (EventSetStorkPrices, EventSetPythPrices) and correctly references the ChainlinkDataStreamsPriceState type from the imported oracle.proto.

chain/exchange/types/msgs.go (1)

2099-2111: LGTM - Duplicate grantee validation.

The implementation correctly detects and rejects duplicate grantees within a single MsgAuthorizeStakeGrants message. The error message includes the duplicate grantee address for debugging, and the validation is performed before the amount validation.

chain/exchange/types/v2/trade.go (1)

1-23: LGTM - TradeFeeData struct and constructor.

Clean implementation with proper initialization using math.LegacyZeroDec(). The struct provides a clear model for trade fee-related data, and the constructor correctly accepts the discounted rate while initializing other fields to zero.

chain/evm/precompiles/exchange/i_exchange_module.abigen.go (1)

1-2: Generated file - verify ABI source consistency.

This is an auto-generated binding file. The ABI update on line 206 (changing uint256 to ExchangeTypes.UFixed256x18 for price, quantity, margin, and related fields) appears consistent with the PR's goal of updating proto definitions for chain v1.18.0.

Ensure the Solidity interface source (IExchangeModule.sol or equivalent) was updated first, and this file was regenerated using abigen rather than manually edited.

Also applies to: 206-206

chain/exchange/types/v2/authz_exchange_generic.go (2)

115-118: Verify intended behavior when hold is missing from context.

When getHold returns ok = false (context key not set or value is nil), the method returns Accept: false. This means authorization will be denied if the caller forgets to set the hold in context.

Is this the intended behavior? Consider whether:

  1. Missing hold should be treated as zero spend (accept with unchanged limit), or
  2. Missing hold should explicitly reject (current behavior)

If the current strict behavior is intentional, consider adding a comment explaining why missing hold results in rejection.


110-131: LGTM - Clean spend limit enforcement logic.

The refactored Accept method implements a clear flow:

  1. No-limit case returns early (line 111-113)
  2. Missing hold context rejects authorization (line 115-118)
  3. Single-pass validation and deduction of spend limits (line 120-130)

The logic correctly handles the case where a hold denom isn't in the spend limit (returns false since AmountOf returns zero for missing denoms).

proto/injective/oracle/v1beta1/query.proto (1)

226-234: LGTM - New Chainlink query messages.

The new request/response message definitions follow the established patterns in this file (empty request for retrieving all states, response with repeated price state field).

chain/exchange/types/codec.go (3)

18-20: LGTM - Oneof interface registration for Amino.

Registering oneof interfaces (isOpenNotionalCap_Cap and isFullDerivativeMarket_Info) is necessary for proper Amino JSON serialization of protobuf oneof fields. This follows the correct pattern for handling oneofs in the Cosmos SDK legacy Amino codec.


41-45: LGTM - New message type registrations.

The new messages (MsgDecreasePositionMargin, MsgEmergencySettleMarket, MsgAuthorizeStakeGrants, MsgActivateStakeGrant) are correctly registered in both:

  • Legacy Amino codec (lines 41-45) for JSON serialization
  • Interface registry (lines 122-126) for protobuf/gRPC

Registration names follow the established exchange/MsgX convention.

Also applies to: 122-126


92-98: LGTM - Oneof implementation registrations.

Concrete oneof types are registered with clear, descriptive names that distinguish between the variants:

  • exchange/OpenNotionalCapUncapped and exchange/OpenNotionalCapCapped
  • exchange/FullDerivativeMarketPerpetualInfo and exchange/FullDerivativeMarketFuturesInfo

This enables proper Amino serialization/deserialization of these polymorphic types.

proto/injective/exchange/v2/proposal.proto (1)

17-21: LGTM - Tri-state enum for optional updates.

The DisableMinimalProtocolFeeUpdate enum correctly implements a tri-state pattern:

  • NoUpdate (0): Don't modify the existing value
  • False (1): Set the flag to false (enable minimal protocol fee)
  • True (2): Set the flag to true (disable minimal protocol fee)

This is the appropriate pattern for optional fields in update proposals where you need to distinguish between "don't change" and "set to false".

chain/evm/precompiles/bank/fixed_supply_bank_erc20.abigen.go (2)

34-35: Generated ABI/Bin update – no manual review needed

These large ABI/Bin string literals are generated and appear consistent with the added Failure event bindings; no manual changes suggested.


608-741: Failure event bindings mirror existing iterator/watch patterns correctly

The FixedSupplyBankERC20FailureIterator, FixedSupplyBankERC20Failure struct, and the FilterFailure/WatchFailure/ParseFailure methods follow the same patterns as the existing Approval/Transfer bindings and correctly use FilterLogs/WatchLogs without indexed topics. Looks good.

proto/injective/oracle/v1beta1/tx.proto (1)

46-50: Chainlink RPC wiring matches existing oracle Msg patterns

RelayChainlinkPrices is added consistently with other RPCs (Pyth, Stork, etc.) and uses the expected request/response message types. No issues here.

chain/oracle/types/msgs.go (1)

27-27: Chainlink relay type and sdk.Msg registration are consistent

TypeMsgRelayChainlinkPrices and the _ sdk.Msg = &MsgRelayChainlinkPrices{} registration align with the existing oracle message conventions.

Also applies to: 39-39

chain/evm/precompiles/bank/mint_burn_bank_erc20.abigen.go (2)

34-35: Generated ABI/Bin update – treated as codegen

The updated ABI/Bin literals reflect the new Failure event; assuming these came from regenerating bindings, there’s nothing to adjust manually.


744-877: MintBurn Failure event bindings are correct and consistent

The MintBurnBankERC20FailureIterator, MintBurnBankERC20Failure struct, and associated FilterFailure/WatchFailure/ParseFailure methods follow the established iterator and subscription patterns and correctly omit indexed topics for this event. All good.

chain/exchange/types/v2/msgs.go (2)

346-360: Stork timestamp comment accurately documents existing behaviour

The new comment about converting timestamps to nanoseconds matches the surrounding code and improves readability without changing semantics.


2227-2243: Duplicate grantee detection in MsgAuthorizeStakeGrants

The new seenGrantees map cleanly prevents duplicate Grantee entries within a single MsgAuthorizeStakeGrants, using validated bech32 strings as keys and returning ErrInvalidStakeGrant on duplicates. This is a sensible tightening of validation with minimal overhead.

chain/exchange/types/v2/codec.go (2)

38-40: LGTM! Oneof interface and concrete type registrations are properly structured.

The registration of oneof interfaces (isOpenNotionalCap_Cap, isFullDerivativeMarket_Info) and their concrete implementations (OpenNotionalCap_Uncapped, OpenNotionalCap_Capped, FullDerivativeMarket_PerpetualInfo, FullDerivativeMarket_FuturesInfo) follows the correct pattern for Amino codec compatibility with protobuf oneof fields.

Also applies to: 120-127


61-77: LGTM! New message types are properly registered.

The new messages (MsgDecreasePositionMargin, MsgEmergencySettleMarket, MsgAuthorizeStakeGrants, MsgActivateStakeGrant) are correctly registered in both RegisterLegacyAminoCodec and RegisterInterfaces, ensuring proper serialization and interface compliance.

Also applies to: 151-167

chain/exchange/types/v2/market.go (3)

107-110: LGTM! Maturation start condition correctly updated.

The IsStartingMaturation method now properly checks ExpirationTwapStartBaseCumulativePrice to determine if maturation is starting, which aligns with the TWAP-based calculation approach for expiry futures markets.


371-394: LGTM! Market solvency and balance delta utilities are well-implemented.

IsMarketSolvent provides a clear check for market fund adequacy. GetMarketBalanceDelta correctly handles the reduce-only case by adding the trade fee back before computing the delta, as reduce-only orders have fees deducted from payout rather than held separately.


12-16: LGTM! New MarketIDQuoteDenomMakerFee struct is well-defined.

The struct provides a clean grouping of market identification and maker fee information for fee-related operations.

chain/exchange/types/v2/proposal.go (4)

771-772: LGTM! Chainlink Data Streams oracle type support added.

The addition of oracletypes.OracleType_ChainlinkDataStreams to the valid oracle types in OracleParams.ValidateBasic() enables support for the new Chainlink Data Streams oracle, which is the core objective of this PR.


1894-1903: LGTM! AdminInfo.ValidateBasic() implementation is correct.

The validation properly:

  1. Validates the admin address using sdk.AccAddressFromBech32 only when non-empty
  2. Checks AdminPermissions against types.MaxPerm to ensure valid permission flags
  3. Uses appropriate error types from the exchange module

452-456: LGTM! Consistent AdminInfo.ValidateBasic() integration across proposals.

The AdminInfo validation is now consistently applied across SpotMarketLaunchProposal, PerpetualMarketLaunchProposal, and ExpiryFuturesMarketLaunchProposal, ensuring proper admin address and permission validation when provided.

Also applies to: 918-922, 1031-1035


1686-1706: LGTM! Constructor properly initializes all fields.

The NewBinaryOptionsMarketParamUpdateProposal constructor correctly accepts and assigns the hasDisabledMinimalProtocolFee parameter along with all other fields.

chain/exchange/types/v2/derivative.go (3)

14-41: LGTM! Order comparison logic is correct.

GetIsOrderLess correctly computes the distance from reference price for both buy and sell orders, and the sorting direction is properly controlled by isSortingFromWorstToBest.


749-765: LGTM! VWAP calculation handles edge cases properly.

ApplyExecution correctly guards against nil values and zero quantity, preventing division by zero when computing the weighted average price.


978-1064: LGTM! Batch event construction with proper delta application.

ApplyDeltasAndGetDerivativeOrderBatchEvent correctly applies deposit deltas, trading reward points, and constructs trade logs with proper fee calculations including self-relayed trade handling.

injective_data/ofac.json (1)

36-36: Verify OFAC addresses against official SDN list.

Three new Ethereum addresses have been added (lines 36, 62, 72). The addresses are validly formatted and the JSON structure is correct. However, confirm these addresses are from the official OFAC SDN (Specially Designated Nationals) list, as sanctions lists are compliance-critical.

Also applies to: 62-62, 72-72

"exchange/v2/AtomicMarketOrderFeeMultiplierScheduleProposal",
nil,
)
cdc.RegisterConcrete(&DenomMinNotionalProposal{}, "exchange/v2/DenomMinNotionalProposal", nil)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "codec.go" -path "*/exchange/types/v2/*" 2>/dev/null | head -20

Repository: InjectiveLabs/sdk-go

Length of output: 98


🏁 Script executed:

cat -n ./chain/exchange/types/v2/codec.go | sed -n '1,220p'

Repository: InjectiveLabs/sdk-go

Length of output: 13410


Register DenomMinNotionalProposal in govtypes.Content interface registry.

DenomMinNotionalProposal is registered in the Amino codec (line 104) but missing from the govtypes.Content interface implementations in RegisterInterfaces (lines 183-202). All other proposal types are consistently registered in both registries. Add it to maintain pattern consistency.

🤖 Prompt for AI Agents
In chain/exchange/types/v2/codec.go around line 104 and in the
RegisterInterfaces block at lines ~183-202, the DenomMinNotionalProposal type is
registered in the Amino codec but not added to the govtypes.Content interface
registrations; add DenomMinNotionalProposal to the RegisterInterfaces call so it
implements govtypes.Content alongside the other proposal types (place it with
the other proposal registrations in the same slice/map used for
govtypes.Content).

Comment on lines +77 to +80
notional := order.Fillable.Mul(order.Price)
fee := notional.Mul(positiveMakerFeePart)
remainingMargin := order.Margin.Mul(order.Fillable).Quo(order.Quantity)
cumulativeQuoteAmount = cumulativeQuoteAmount.Add(remainingMargin).Add(fee)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential division by zero when order.Quantity is zero.

If order.Quantity is zero, the calculation order.Margin.Mul(order.Fillable).Quo(order.Quantity) will panic. Consider adding a guard or ensuring orders with zero quantity are filtered upstream.

🔎 Proposed fix
+		if order.Quantity.IsZero() {
+			continue
+		}
+
 		notional := order.Fillable.Mul(order.Price)
 		fee := notional.Mul(positiveMakerFeePart)
 		remainingMargin := order.Margin.Mul(order.Fillable).Quo(order.Quantity)
📝 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
notional := order.Fillable.Mul(order.Price)
fee := notional.Mul(positiveMakerFeePart)
remainingMargin := order.Margin.Mul(order.Fillable).Quo(order.Quantity)
cumulativeQuoteAmount = cumulativeQuoteAmount.Add(remainingMargin).Add(fee)
if order.Quantity.IsZero() {
continue
}
notional := order.Fillable.Mul(order.Price)
fee := notional.Mul(positiveMakerFeePart)
remainingMargin := order.Margin.Mul(order.Fillable).Quo(order.Quantity)
cumulativeQuoteAmount = cumulativeQuoteAmount.Add(remainingMargin).Add(fee)
🤖 Prompt for AI Agents
In chain/exchange/types/v2/derivative.go around lines 77-80, the expression
order.Margin.Mul(order.Fillable).Quo(order.Quantity) can panic if order.Quantity
is zero; add a guard before performing the division (e.g., if
order.Quantity.IsZero() then handle by skipping this order, setting
remainingMargin to zero, or returning an error), or validate/filter out
zero-quantity orders upstream and document the assumption; ensure the chosen
behavior is explicit and covered by a unit test.

Comment on lines +859 to +863
// ComputeSyntheticVwapUnitDelta returns (price - markPrice) / markPrice
func (p *DerivativeVwapInfo) ComputeSyntheticVwapUnitDelta(marketID common.Hash) math.LegacyDec {
vwapInfo := p.PerpetualVwapInfo[marketID]
return vwapInfo.VwapData.Price.Sub(*vwapInfo.MarkPrice).Quo(*vwapInfo.MarkPrice)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Potential division by zero in ComputeSyntheticVwapUnitDelta.

If MarkPrice is nil or zero, the division vwapInfo.VwapData.Price.Sub(*vwapInfo.MarkPrice).Quo(*vwapInfo.MarkPrice) will panic. Additionally, if the marketID is not found in PerpetualVwapInfo, dereferencing vwapInfo will cause a nil pointer dereference.

🔎 Proposed fix with nil and zero checks
 func (p *DerivativeVwapInfo) ComputeSyntheticVwapUnitDelta(marketID common.Hash) math.LegacyDec {
 	vwapInfo := p.PerpetualVwapInfo[marketID]
+	if vwapInfo == nil || vwapInfo.MarkPrice == nil || vwapInfo.MarkPrice.IsZero() {
+		return math.LegacyZeroDec()
+	}
 	return vwapInfo.VwapData.Price.Sub(*vwapInfo.MarkPrice).Quo(*vwapInfo.MarkPrice)
 }

Comment on lines +240 to +254
func (info *FeeDiscountStakingInfo) GetSortedNewFeeDiscountAccountTiers() []*AccountTierTTL {
accountTiers := make([]*AccountTierTTL, 0, len(info.AccountFeeTiers))
info.NewAccountsMux.RLock()
for k, v := range info.NewAccounts {
accountTiers = append(accountTiers, &AccountTierTTL{
Account: sdk.AccAddress([]byte(string(k[:]))),
TierTTL: v,
})
}
info.NewAccountsMux.RUnlock()
sort.SliceStable(accountTiers, func(i, j int) bool {
return bytes.Compare(accountTiers[i].Account.Bytes(), accountTiers[j].Account.Bytes()) < 0
})
return accountTiers
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect slice capacity pre-allocation.

Line 241 uses len(info.AccountFeeTiers) as capacity, but the loop iterates over info.NewAccounts. This may cause unnecessary reallocations if the maps have different sizes.

🔎 Proposed fix
 func (info *FeeDiscountStakingInfo) GetSortedNewFeeDiscountAccountTiers() []*AccountTierTTL {
-	accountTiers := make([]*AccountTierTTL, 0, len(info.AccountFeeTiers))
+	accountTiers := make([]*AccountTierTTL, 0, len(info.NewAccounts))
 	info.NewAccountsMux.RLock()
 	for k, v := range info.NewAccounts {
🤖 Prompt for AI Agents
In chain/exchange/types/v2/fee_discounts.go around lines 240 to 254, the slice
capacity is preallocated with len(info.AccountFeeTiers) but the loop iterates
over info.NewAccounts; change the capacity to len(info.NewAccounts) (or 0 if you
prefer letting append grow) so the slice is pre-sized correctly, keep the
lock/unlock and rest of logic unchanged.

Comment on lines +256 to +272
func (info *FeeDiscountStakingInfo) GetSortedAccountVolumeContributions() []*AccountContribution {
accountContributions := make([]*AccountContribution, 0, len(info.AccountFeeTiers))
info.AccountVolumesMux.RLock()
for k, v := range info.AccountVolumeContributions {
accountContributions = append(accountContributions, &AccountContribution{
// use copy of value in closure, since the memory is not copied, it's reused.
// So if your closure captures it, instead of copying via call args, you'll get same index in all goroutines
Account: sdk.AccAddress([]byte(string(k[:]))),
Amount: v,
})
}
info.AccountVolumesMux.RUnlock()
sort.SliceStable(accountContributions, func(i, j int) bool {
return bytes.Compare(accountContributions[i].Account.Bytes(), accountContributions[j].Account.Bytes()) < 0
})
return accountContributions
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Incorrect slice capacity pre-allocation.

Line 257 uses len(info.AccountFeeTiers) as capacity, but the loop iterates over info.AccountVolumeContributions.

🔎 Proposed fix
 func (info *FeeDiscountStakingInfo) GetSortedAccountVolumeContributions() []*AccountContribution {
-	accountContributions := make([]*AccountContribution, 0, len(info.AccountFeeTiers))
+	accountContributions := make([]*AccountContribution, 0, len(info.AccountVolumeContributions))
 	info.AccountVolumesMux.RLock()
 	for k, v := range info.AccountVolumeContributions {
📝 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
func (info *FeeDiscountStakingInfo) GetSortedAccountVolumeContributions() []*AccountContribution {
accountContributions := make([]*AccountContribution, 0, len(info.AccountFeeTiers))
info.AccountVolumesMux.RLock()
for k, v := range info.AccountVolumeContributions {
accountContributions = append(accountContributions, &AccountContribution{
// use copy of value in closure, since the memory is not copied, it's reused.
// So if your closure captures it, instead of copying via call args, you'll get same index in all goroutines
Account: sdk.AccAddress([]byte(string(k[:]))),
Amount: v,
})
}
info.AccountVolumesMux.RUnlock()
sort.SliceStable(accountContributions, func(i, j int) bool {
return bytes.Compare(accountContributions[i].Account.Bytes(), accountContributions[j].Account.Bytes()) < 0
})
return accountContributions
}
func (info *FeeDiscountStakingInfo) GetSortedAccountVolumeContributions() []*AccountContribution {
accountContributions := make([]*AccountContribution, 0, len(info.AccountVolumeContributions))
info.AccountVolumesMux.RLock()
for k, v := range info.AccountVolumeContributions {
accountContributions = append(accountContributions, &AccountContribution{
// use copy of value in closure, since the memory is not copied, it's reused.
// So if your closure captures it, instead of copying via call args, you'll get same index in all goroutines
Account: sdk.AccAddress([]byte(string(k[:]))),
Amount: v,
})
}
info.AccountVolumesMux.RUnlock()
sort.SliceStable(accountContributions, func(i, j int) bool {
return bytes.Compare(accountContributions[i].Account.Bytes(), accountContributions[j].Account.Bytes()) < 0
})
return accountContributions
}
🤖 Prompt for AI Agents
In chain/exchange/types/v2/fee_discounts.go around lines 256-272, the slice is
preallocated with len(info.AccountFeeTiers) but the loop iterates over
info.AccountVolumeContributions; change the capacity to
len(info.AccountVolumeContributions) when calling make so the slice is correctly
sized for the data being appended.

Comment on lines 259 to 263
rpc SubaccountPositions(QuerySubaccountPositionsRequest)
returns (QuerySubaccountPositionsResponse) {
option (google.api.http).get =
"/injective/exchange/v1beta1/positions/{subaccount_id}";
"/injective/exchange/v1beta1/subaccount_positions/{subaccount_id}";
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for references to the old HTTP path pattern

echo "=== Searching for old path pattern (positions/{subaccount_id}) ==="
rg "positions/\{subaccount_id\}" -C2

echo -e "\n=== Searching for alternative path patterns ==="
rg "positions.*subaccount_id" -C2

echo -e "\n=== Searching for SubaccountPositions references ==="
rg "SubaccountPositions" -C3

echo -e "\n=== Checking for HTTP path definitions in query.proto ==="
rg "google.api.http" proto/injective/exchange/v1beta1/query.proto -C2

Repository: InjectiveLabs/sdk-go

Length of output: 50376


API endpoint path clarified, but breaking change for REST API clients.

The updated path /injective/exchange/v1beta1/subaccount_positions/{subaccount_id} is more explicit and aligns better with the SubaccountPositions method name, distinguishing it from the general Positions endpoint.

This is a breaking change for external REST API clients directly calling this endpoint. However, SDK users relying on the generated gRPC client method (FetchChainSubaccountPositions) are unaffected since they use the RPC layer, not hardcoded HTTP paths.

Ensure that REST API clients and downstream services relying on direct HTTP calls are updated with the new path.

🤖 Prompt for AI Agents
In proto/injective/exchange/v1beta1/query.proto around lines 259-263, the HTTP
path for SubaccountPositions was changed to
/injective/exchange/v1beta1/subaccount_positions/{subaccount_id}, which breaks
existing REST clients; to fix this without breaking clients, add an additional
HTTP binding that preserves the old path (using
google.api.http.additional_bindings) mapping the previous endpoint to the same
RPC, or if you intend to break compatibility, update the API docs/changelog and
notify downstreams and SDK maintainers to replace the old REST URL with the new
one.

Comment on lines +79 to +85
// Retrieves the state for all Chainlink Data Streamsprice feeds
rpc ChainlinkDataStreamsPriceStates(
QueryChainlinkDataStreamsPriceStatesRequest)
returns (QueryChainlinkDataStreamsPriceStatesResponse) {
option (google.api.http).get =
"/injective/oracle/v1beta1/chainlink_data_stream_price_states";
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Minor typo in comment and HTTP path inconsistency.

  1. Line 79: "Streamsprice" should be "Streams price" (missing space)
  2. HTTP path uses singular chainlink_data_stream_price_states while the RPC/message names use plural ChainlinkDataStreams - consider aligning for consistency (e.g., chainlink_data_streams_price_states)
🔎 Suggested fix
-  // Retrieves the state for all Chainlink Data Streamsprice feeds
+  // Retrieves the state for all Chainlink Data Streams price feeds
   rpc ChainlinkDataStreamsPriceStates(
       QueryChainlinkDataStreamsPriceStatesRequest)
       returns (QueryChainlinkDataStreamsPriceStatesResponse) {
     option (google.api.http).get =
-        "/injective/oracle/v1beta1/chainlink_data_stream_price_states";
+        "/injective/oracle/v1beta1/chainlink_data_streams_price_states";
   }
🤖 Prompt for AI Agents
In proto/injective/oracle/v1beta1/query.proto around lines 79 to 85, fix the
comment typo by changing "Streamsprice" to "Streams price" and make the HTTP
path consistent with the RPC/message pluralization by renaming the option path
from "/injective/oracle/v1beta1/chainlink_data_stream_price_states" to
"/injective/oracle/v1beta1/chainlink_data_streams_price_states"; also search for
and update any other references to the old singular path to avoid mismatches.

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