Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

`encode_int192` zero-pads negative values, corrupting them on `abi_encode`

オープン 初心者向け
#82 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
2/5
見積もり時間
1〜3時間
初心者へのやさしさ
76/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
rust
領域
api, backend

調査の方向性

ReportBase::encode_int192 と ReportBase::encode_int64 の実装を読み、その後、既存の test_decode_report_data_v12 テストを確認してください。負の値のラウンドトリップテストを追加し、エンコードされた ABI ワードが符号拡張を使用していることを確認してください。負のフィールドが元の値にデコードされ、両方のエンコーダーが正規形のワードを出力すれば完了です。

索引モデルが issue の本文から書いたものです。

説明

encode_int192 zero-pads negative values, so abi_encode corrupts them and emits non-canonical ABI words.

ReportBase::encode_int192 right-aligns BigInt::to_signed_bytes_be() — the minimal two's-complement form — into a zero-filled 32-byte buffer. For a negative value that minimal form is shorter than 24 bytes, and the leading bytes are left 0x00 instead of 0xFF, so the sign is lost.

ReportBase::encode_int64 has the same zero-fill, but because i64::to_be_bytes() is always 8 bytes and read_int64 reads exactly those 8 bytes back, the value survives a round-trip through this crate. The word it emits is still not what an ABI encoder would produce.

Affects 1.2.0, 1.2.2 and 1.3.0 (current). decode is correct — it reads the low 24 bytes as signed — so bodies returned by a real verifier are unaffected. What breaks is anything that builds a report with abi_encode.

Reproduction

use chainlink_data_streams_report::{feed_id::ID, report::v12::ReportDataV12};
use num_bigint::BigInt;

let report = ReportDataV12 {
    feed_id: ID([0u8; 32]),
    valid_from_timestamp: 1,
    observations_timestamp: 1,
    native_fee: BigInt::ZERO,
    link_fee: BigInt::ZERO,
    expires_at: 2,
    nav_per_share: BigInt::from(-1),
    next_nav_per_share: BigInt::from(-1_000_000),
    nav_date: -1,
    ripcord: 0,
};
let decoded = ReportDataV12::decode(&report.abi_encode().unwrap()).unwrap();
assert_eq!(decoded.nav_per_share, BigInt::from(-1)); // fails: 255

Output:

nav_per_share      in: -1         out: 255
next_nav_per_share in: -1000000   out: 15777216
nav_date           in: -1         out: -1

The navPerShare word:

actual:   00000000000000000000000000000000000000000000000000000000000000ff
expected: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Impact

Any code that builds a report body with abi_encode gets a different value back than it put in, whenever a field is negative. This is easy to miss in a test: a case that encodes a negative value to prove the consumer rejects it still passes, because what reaches the consumer is a large positive number rejected for an unrelated reason.

The emitted word is also not valid ABI, so a body built with abi_encode and read by Solidity's abi.decode disagrees with this crate.

Suggested fix

Fill the buffer according to the sign before copying, in both encode_int192 and encode_int64:

pub(crate) fn encode_int192(value: &BigInt) -> Result<[u8; 32], ReportError> {
    let bytes_value = value.to_signed_bytes_be();
    let len = bytes_value.len();
    if len > 24 {
        return Err(ReportError::InvalidLength("int192"));
    }
    let fill = if value.sign() == Sign::Minus { 0xFF } else { 0x00 };
    let mut buffer = [fill; 32];
    buffer[32 - len..32].copy_from_slice(&bytes_value);
    Ok(buffer)
}

A round-trip test over negative values would catch both. The existing test_decode_report_data_v12 uses only positive mocks, which is why this is not caught today.

主要言語
TypeScript
スター
11
フォーク
16
平均マージ
1日 20時間
マージ済み PR(30日)
4

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

smartcontractkit/data-streams-sdk のほかの issue

smartcontractkit/data-streams-sdk の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。