harness-writing
ファジングハーネスを各種プログラミング言語で効果的に記述するためのテクニックを提供します。新しいファズターゲットの作成や、既存のハーネスコードの改善が必要な際に使用してください。
description の原文を見る
> Techniques for writing effective fuzzing harnesses across languages. Use when creating new fuzz targets or improving existing harness code.
SKILL.md 本文
ファジング・ハーネスの書き方
ファジング・ハーネスは、ファザーからランダムデータを受け取り、テスト対象のシステム (SUT) にルーティングするエントリーポイント関数です。ハーネスの品質は、どのコードパスが実行されるか、また重大なバグが見つかるかどうかを直接左右します。不適切に書かれたハーネスは、システム全体またはサブシステムを見落としたり、再現不可能なクラッシュを引き起こしたりする可能性があります。
概要
ハーネスはファザーのランダムバイト生成とアプリケーション API の間の橋です。生バイトを意味のある入力に解析し、ターゲット関数を呼び出し、エッジケースを適切に処理する必要があります。ファジング・セットアップで最も重要な部分はハーネスであり、不適切に書かれた場合、アプリケーションの重要な部分がカバーされないことがあります。
主要な概念
| 概念 | 説明 |
|---|---|
| Harness | ファザー入力を受け取りテスト対象のコードを呼び出す関数 |
| SUT | System Under Test (テスト対象システム) — ファジングされるコード |
| Entry point | ファザーが要求する関数シグネチャ (例: LLVMFuzzerTestOneInput) |
| FuzzedDataProvider | 生バイトから型付きデータを構造化抽出するためのヘルパークラス |
| Determinism | 同じ入力が常に同じ動作を生成することを保証するプロパティ |
| Interleaved fuzzing | 入力に基づいて複数の操作を実行する単一ハーネス |
いつ使用するか
以下の場合にこのテクニックを適用してください:
- 初めてファジ・ターゲットを作成する
- ファジ・キャンペーンのコード・カバレッジが低いか、バグを見つけていない
- ファジング中に見つかったクラッシュが再現不可能である
- ターゲット API が複雑または構造化された入力を必要とする
- 複数の関連機能を一緒にテストする必要がある
以下の場合はこのテクニックをスキップしてください:
- プロジェクトからの既にテスト済みのハーネスを使用している
- 自動ハーネス生成ツールがニーズを満たしている
- ターゲットが既に包括的なファジング・インフラを備えている
クイック・リファレンス
| タスク | パターン |
|---|---|
| 最小限の C++ ハーネス | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) |
| 最小限の Rust ハーネス | `fuzz_target!( |
| サイズ検証 | if (size < MIN_SIZE) return 0; |
| 整数へのキャスト | uint32_t val = *(uint32_t*)(data); |
| FuzzedDataProvider を使用 | FuzzedDataProvider fuzzed_data(data, size); |
| 型付きデータの抽出 (C++) | auto val = fuzzed_data.ConsumeIntegral<uint32_t>(); |
| 文字列の抽出 (C++) | auto str = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF); |
ステップバイステップ
ステップ 1: エントリーポイントの特定
以下の条件を満たすコードベース内の関数を見つけます:
- 外部入力を受け入れる (パーサー、バリデータ、プロトコル・ハンドラ)
- 複雑なデータ形式を解析する (JSON, XML, バイナリ・プロトコル)
- セキュリティ上重要な操作を実行する (認証、暗号化)
- 高いサイクロマティック複雑度または多くのブランチを持つ
優れたターゲットは通常:
- プロトコル・パーサー
- ファイル形式パーサー
- シリアル化/デシリアル化関数
- 入力検証ルーチン
ステップ 2: 最小限のハーネスを作成
ターゲット関数を呼び出す最もシンプルなハーネスから始めます:
C/C++:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
target_function(data, size);
return 0;
}
Rust:
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
target_function(data);
});
ステップ 3: 入力検証を追加
意味のないには小さすぎる、または大きすぎる入力を拒否します:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 意味のある入力に必要な最小サイズを確認
if (size < MIN_INPUT_SIZE || size > MAX_INPUT_SIZE) {
return 0;
}
target_function(data, size);
return 0;
}
根拠: ファザーはあらゆるサイズのランダム入力を生成します。ハーネスは空、極小、巨大、または不正な形式の入力を、ハーネス自体で予期しない問題を引き起こさないように処理する必要があります (SUT でのクラッシュは問題ありません — それが私たちが探しているものです)。
ステップ 4: 入力を構造化
整数や文字列などの型付きデータを必要とする API に対しては、キャストまたは FuzzedDataProvider などのヘルパーを使用します:
シンプルなキャスト:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size != 2 * sizeof(uint32_t)) {
return 0;
}
uint32_t numerator = *(uint32_t*)(data);
uint32_t denominator = *(uint32_t*)(data + sizeof(uint32_t));
divide(numerator, denominator);
return 0;
}
FuzzedDataProvider の使用:
#include "FuzzedDataProvider.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
size_t allocation_size = fuzzed_data.ConsumeIntegral<size_t>();
std::vector<char> str1 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
std::vector<char> str2 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
concat(&str1[0], str1.size(), &str2[0], str2.size(), allocation_size);
return 0;
}
ステップ 5: テストと反復
ファザーを実行し、以下をモニタリングします:
- コード・カバレッジ (すべての興味深いパスに到達しているか?)
- 実行数/秒 (十分に高速か?)
- クラッシュ再現性 (保存された入力でクラッシュを再現できるか?)
これらのメトリックスを改善するようにハーネスを反復します。
一般的なパターン
パターン: バイト配列を超えて — 整数へのキャスト
ユースケース: ターゲットが整数やフロートのようなプリミティブ型を期待する場合
実装:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 正確に 2 つの 4 バイト数であることを確認
if (size != 2 * sizeof(uint32_t)) {
return 0;
}
// 入力を 2 つの整数に分割
uint32_t numerator = *(uint32_t*)(data);
uint32_t denominator = *(uint32_t*)(data + sizeof(uint32_t));
divide(numerator, denominator);
return 0;
}
Rust の同等の実装:
fuzz_target!(|data: &[u8]| {
if data.len() != 2 * std::mem::size_of::<i32>() {
return;
}
let numerator = i32::from_ne_bytes([data[0], data[1], data[2], data[3]]);
let denominator = i32::from_ne_bytes([data[4], data[5], data[6], data[7]]);
divide(numerator, denominator);
});
動作する理由: あらゆる 8 バイト入力が有効です。ファザーは入力が正確に 8 バイトである必要があることを学び、すべてのビット反転が新しく、潜在的に興味深い入力を生成します。
パターン: 複雑な入力用の FuzzedDataProvider
ユースケース: ターゲットが複数の文字列、整数、または可変長データを必要とする場合
実装:
#include "FuzzedDataProvider.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
FuzzedDataProvider fuzzed_data(data, size);
// さまざまなタイプのデータを抽出
size_t allocation_size = fuzzed_data.ConsumeIntegral<size_t>();
// ターミネータ付きの可変長文字列を消費
std::vector<char> str1 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
std::vector<char> str2 = fuzzed_data.ConsumeBytesWithTerminator<char>(32, 0xFF);
char* result = concat(&str1[0], str1.size(), &str2[0], str2.size(), allocation_size);
if (result != NULL) {
free(result);
}
return 0;
}
役に立つ理由: FuzzedDataProvider はバイトストリームから構造化データを抽出する複雑さを処理します。異なる型の複数のパラメータが必要な API に特に有用です。
パターン: インターリーブ・ファジング
ユースケース: 複数の関連操作を単一ハーネスでテストすべき場合
実装:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
if (size < 1 + 2 * sizeof(int32_t)) {
return 0;
}
// 最初のバイトが操作を選択
uint8_t mode = data[0];
// 次のバイトはオペランド
int32_t numbers[2];
memcpy(numbers, data + 1, 2 * sizeof(int32_t));
int32_t result = 0;
switch (mode % 4) {
case 0:
result = add(numbers[0], numbers[1]);
break;
case 1:
result = subtract(numbers[0], numbers[1]);
break;
case 2:
result = multiply(numbers[0], numbers[1]);
break;
case 3:
result = divide(numbers[0], numbers[1]);
break;
}
// コンパイラが呼び出しを最適化して削除するのを防ぐ
printf("%d", result);
return 0;
}
利点:
- 複数の個別ハーネスを書くより 1 つのハーネスを書く方が高速
- 共有コーパスは、1 つの操作に興味深い入力が他の操作にも興味深いかもしれない
- 操作間の相互作用でバグを発見できる
使用時期:
- 操作が類似の入力タイプを共有する
- 操作が論理的に関連している (算術演算、CRUD 操作など)
- 単一コーパスがすべての操作を通じて意味をなす
パターン: Rust の Arbitrary による構造認識ファジング
ユースケース: カスタム構造を使用する Rust コードをファジングする場合
実装:
use arbitrary::Arbitrary;
#[derive(Debug, Arbitrary)]
pub struct Name {
data: String
}
impl Name {
pub fn check_buf(&self) {
let data = self.data.as_bytes();
if data.len() > 0 && data[0] == b'a' {
if data.len() > 1 && data[1] == b'b' {
if data.len() > 2 && data[2] == b'c' {
process::abort();
}
}
}
}
}
arbitrary を使用したハーネス:
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: your_project::Name| {
data.check_buf();
});
Cargo.toml に追加:
[dependencies]
arbitrary = { version = "1", features = ["derive"] }
役に立つ理由: arbitrary クレートは生バイトから Rust 構造体への逆シリアル化を自動的に処理し、ボイラープレートを削減し、有効な構造体構築を保証します。
制限: arbitrary クレートは逆シリアル化を提供しないため、特定の構造にマップするバイト配列を手動で構築することはできません。これは空のコーパスから開始するときに最適に機能します (libFuzzer の場合は問題ありませんが、AFL++ の場合は問題があります)。
高度な使用法
ヒントとコツ
| ヒント | 役に立つ理由 |
|---|---|
| パーサーから始める | バグ密度が高く、明確なエントリーポイント、ハーネスが容易 |
| I/O 操作をモック | ブロッキング I/O からのハング防止、決定性を実現 |
| FuzzedDataProvider を使用 | 生バイトからの構造化データ抽出を簡潔化 |
| グローバル状態をリセット | 各イテレーションが独立し再現可能であることを保証 |
| ハーネスでリソースを解放 | 長いキャンペーン中のメモリ枯渇防止 |
| ハーネスでのログを回避 | ログは遅い — ファジングは 100s-1000s exec/sec が必要 |
| ハーネスを手動でテスト | キャンペーン開始前に既知入力でハーネスを実行 |
| カバレッジを早期にチェック | ハーネスが期待されるコードパスに到達することを確認 |
Protocol Buffers を使用した構造認識ファジング
高度に構造化された入力形式の場合、Protocol Buffers をカスタム・ミューテータで中間形式として使用することを検討してください:
// .proto ファイルで入力形式を定義
// libprotobuf-mutator を使用して有効なミューテーションを生成
// これにより、ファザーがプロトバフ・エンコーディングではなくメッセージコンテンツをミューテートすることを保証
このアプローチはセットアップが多くなりますが、ファザーが解析不可能な入力で時間を浪費するのを防ぎます。詳細については structure-aware fuzzing documentation を参照してください。
非決定性の処理
問題: ランダム値またはタイミング依存のため、再現不可能なクラッシュが発生します。
解決策:
rand()をファザー入力からシードされた決定的 PRNG に置き換えます:uint32_t seed = fuzzed_data.ConsumeIntegral<uint32_t>(); srand(seed);- 時間、PID、またはランダムデータを返すシステムコールをモック
/dev/randomまたは/dev/urandomから読み込むことを回避
グローバル状態のリセット
SUT がグローバル状態 (シングルトン、静的変数) を使用する場合、イテレーション間でリセットします:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// 各イテレーション前にグローバル状態をリセット
global_reset();
target_function(data, size);
// リソースをクリーンアップ
global_cleanup();
return 0;
}
根拠: グローバル状態により、特定の入力ではなく N イテレーション後にクラッシュが発生する可能性があり、バグが再現不可能になります。
実用的なハーネス・ルール
効果的なファジング・ハーネスを保証するためにこれらのルールに従います:
| ルール | 根拠 |
|---|---|
| すべての入力サイズを処理 | ファザーは空、極小、巨大な入力を生成 — ハーネスは適切に処理する必要がある |
exit() を呼び出さない | exit() を呼び出すとファザープロセスが停止します。必要に応じて SUT で abort() を使用 |
| すべてのスレッドに参加 | 各イテレーションは次のイテレーションが開始される前に完了する必要がある |
| 高速であること | 100s-1000s executions/sec を目指します。ログ、高い複雑度、過剰なメモリを回避 |
| 決定性を維持 | 同じ入力は常に同じ動作を生成する必要があります (再現性のため) |
| グローバル状態を回避 | グローバル状態は再現性を低下させます — 避けられない場合はイテレーション間でリセット |
| 狭いターゲットを使用 | PNG と TCP を同じハーネスでファジングしない — 異なる形式は個別のターゲットが必要 |
| リソースを解放 | 長いキャンペーン中のリソース枯渇の原因となるメモリリークを防止 |
注: これらのガイドラインはハーネス・コードだけでなく、SUT 全体に適用されます。SUT がこれらのルールに違反する場合、パッチを当てることを検討してください (ファジング・オブスタクル・テクニックを参照)。
アンチパターン
| アンチパターン | 問題 | 正しいアプローチ |
|---|---|---|
| リセットなしのグローバル状態 | 非決定的なクラッシュ | ハーネス開始時にすべてのグローバルをリセット |
| ブロッキング I/O またはネットワーク呼び出し | ファザーをハング、時間を浪費 | I/O をモック、メモリ内バッファを使用 |
| ハーネスのメモリリーク | リソース枯渇がキャンペーンを停止 | 返す前にすべての割り当てを解放 |
SUT で exit() を呼び出し | ファジング・プロセス全体を停止 | abort() またはエラーコードを返す |
| ハーネスでの大量のログ | exec/sec を数桁削減 | ファジング中にログを無効化 |
| イテレーションごとの操作が多すぎる | ファザーを遅くする | イテレーションを高速で集中させる |
| 無関連の入力形式を混合 | コーパス エントリが形式間で有用でない | 異なる形式に対して個別のハーネス |
| 入力サイズを検証しない | エッジケースでハーネスがクラッシュ | data にアクセスする前に size をチェック |
ツール固有のガイダンス
libFuzzer
ハーネス・シグネチャ:
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// コードをここに記述
return 0; // 0 以外の戻り値は将来の使用のために予約されている
}
コンパイル:
clang++ -fsanitize=fuzzer,address -g harness.cc -o fuzz_target
統合のヒント:
- 構造化入力抽出に
FuzzedDataProvider.hを使用 - ファジング・ランタイムをリンクするために
-fsanitize=fuzzerでコンパイル - より多くのバグを検出するにはサニタイザーを追加 (
-fsanitize=address,undefined) - クラッシュ発生時のスタック・トレースを改善するために
-gを使用 - libFuzzer は空のコーパスから開始可能 — シード入力は不要
実行:
./fuzz_target corpus_dir/
リソース:
AFL++
AFL++ は複数のハーネス・スタイルをサポートしています。最高のパフォーマンスのため、永続モードを使用してください:
永続モード・ハーネス:
#include <unistd.h>
int main(int argc, char **argv) {
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
#endif
unsigned char buf[MAX_SIZE];
while (__AFL_LOOP(10000)) {
// stdin から入力を読み込み
ssize_t len = read(0, buf, sizeof(buf));
if (len <= 0) break;
// ターゲット関数を呼び出し
target_function(buf, len);
}
return 0;
}
コンパイル:
afl-clang-fast++ -g harness.cc -o fuzz_target
統合のヒント:
- 永続モード (
__AFL_LOOP) を使用して 10-100 倍のスピードアップ - デferred initialization (
__AFL_INIT()) を検討してセットアップオーバーヘッドをスキップ - AFL++ はコーパス・ディレクトリに少なくとも 1 つのシード入力が必要
- サニタイザー・ビルドには
AFL_USE_ASAN=1またはAFL_USE_UBSAN=1を使用
実行:
afl-fuzz -i seeds/ -o findings/ -- ./fuzz_target
cargo-fuzz (Rust)
ハーネス・シグネチャ:
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
// コードをここに記述
});
構造化入力を使用した場合 (arbitrary クレート):
#![no_main]
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: YourStruct| {
data.check();
});
ハーネスの作成:
cargo fuzz init
cargo fuzz add my_target
統合のヒント:
- 自動構造体逆シリアル化に
arbitraryクレートを使用 - cargo-fuzz は libFuzzer をラップしているため、すべての libFuzzer 機能が機能します
- cargo-fuzz を介して自動的にサニタイザーでコンパイル
- ハーネスは
fuzz/fuzz_targets/ディレクトリに配置
実行:
cargo +nightly fuzz run my_target
リソース:
go-fuzz
ハーネス・シグネチャ:
// +build gofuzz
package mypackage
func Fuzz(data []byte) int {
// ターゲット関数を呼び出し
target(data)
// 戻りコード:
// -1 入力が無効な場合
// 0 入力は有効だが興味深くない場合
// 1 入力が興味深い場合 (例: 新しいカバレッジを追加)
return 0
}
ビルド:
go-fuzz-build
統合のヒント:
- カバレッジを追加する入力に対して 1 を返します (オプション — ファザーは自動的に検出可能)
- 無効な入力に対して -1 を返して、類似のミューテーションを優先度下げ
- go-fuzz は永続性を自動的に処理します
実行:
go-fuzz -bin=./mypackage-fuzz.zip -workdir=fuzz
トラブルシューティング
| 問題 | 原因 | 解決策 |
|---|---|---|
| executions/sec が低い | ハーネスが遅い (ログ、I/O、複雑度) | ハーネスをプロファイル、ボトルネックを削除、I/O をモック |
| クラッシュが見つからない | カバレッジがバグコードに到達していない | カバレッジを確認、ハーネスを改善してパスを増やす |
| 再現不可能なクラッシュ | 非決定性またはグローバル状態 | ランダム性を削除、グローバルをイテレーション間でリセット |
| ファザーが直ちに終了 | ハーネスが exit() を呼び出し | exit() を abort() またはエラーで置き換え |
| メモリ不足エラー | ハーネスまたは SUT でのメモリリーク | 割り当てを解放、リーク・サニタイザーを使用してリークを検出 |
| 空入力でのクラッシュ | ハーネスがサイズを検証していない | if (size < MIN_SIZE) return 0; を追加 |
| コーパスが増えない | 入力が制約されすぎるまたは形式が厳格 | FuzzedDataProvider または構造認識ファジングを使用 |
関連スキル
このテクニックを使用するツール
| スキル | 適用方法 |
|---|---|
| libfuzzer | FuzzedDataProvider を使用した LLVMFuzzerTestOneInput ハーネス・シグネチャを使用 |
| aflpp | パフォーマンス向上のために __AFL_LOOP で永続モード・ハーネスをサポート |
| cargo-fuzz | arbitrary クレート統合で Rust 固有の fuzz_target! マクロを使用 |
| atheris | Python ハーネスはバイトを取得し、Python 関数を呼び出す |
| ossfuzz | クラウド・ファジング向けに特定ディレクトリ構造でハーネスが必要 |
関連テクニック
| スキル | 関係 |
|---|---|
| coverage-analysis | ハーネス有効性を測定 — ターゲット・コードに到達しているか? |
| address-sanitizer | ハーネスが見つけたバグを検出 (バッファオーバーフロー、use-after-free) |
| fuzzing-dictionary | ハーネスのフォーマット・チェック合格を支援するトークンを提供 |
| fuzzing-obstacles | SUT がハーネス・ルール違反時にパッチ (終了、非決定性) |
リソース
重要な外部リソース
Split Inputs in libFuzzer - Google Fuzzing Docs 単一ファジング・ハーネスで複数の入力パラメータを処理するためのテクニックを説明しており、マジック・セパレータと FuzzedDataProvider の使用を含みます。
Structure-Aware Fuzzing with Protocol Buffers プロトバフを中間形式およびカスタム・ミューテータと使用する高度なテクニック。ファザーがフォーマット・エンコーディングではなくメッセージコンテンツをミューテートすることを保証します。
libFuzzer Documentation ハーネス要件、ベストプラクティス、高度な機能をカバーする LLVM 公式ドキュメント。
cargo-fuzz Book cargo-fuzz および arbitrary クレートを使用した Rust ファジング・ハーネス作成への包括的なガイド。
ビデオリソース
- Effective File Format Fuzzing - ファイル形式パーサーのハーネス作成に関するカンファレンス・トーク
- Modern Fuzzing of C/C++ Projects - ハーネス設計パターンをカバーするチュートリアル
ライセンス: CC-BY-SA-4.0(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- trailofbits
- リポジトリ
- trailofbits/skills
- ライセンス
- CC-BY-SA-4.0
- 最終更新
- 不明
Source: https://github.com/trailofbits/skills / ライセンス: CC-BY-SA-4.0
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。