﻿---
title: "ความเสี่ยงต่อพื้นที่จัดเก็บจาก delegatecall"
description: "Delegatecall เรียกใช้โค้ดของสัญญาอื่นกับพื้นที่จัดเก็บของสัญญาผู้เรียก เรียนรู้ว่าการชนกันของพื้นที่จัดเก็บ อำนาจในการอัปเกรด และเป้าหมายที่ไม่น่าเชื่อถืออาจทำให้พร็อกซีหรือกระเป๋าเงินอัจฉริยะถูกโจมตีได้อย่างไร"
image: "https://wiki.fcontext.com/og.png"
---

> Documentation Index
> Fetch the complete documentation index at: https://wiki.fcontext.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ความเสี่ยงต่อพื้นที่จัดเก็บจาก delegatecall

> จัดทำขึ้นเพื่อการศึกษาเท่านั้น ไม่ใช่คำแนะนำการลงทุน การลงทุนอาจทำให้ขาดทุนได้

<a id="answer"></a>

## คำตอบโดยตรง

`delegatecall` เรียกใช้โค้ดจากสัญญาเป้าหมายภายในบริบทของสัญญาผู้เรียก สัญญาผู้เรียกยังคงใช้พื้นที่จัดเก็บ ยอดคงเหลือ และ `address(this)` ของตนเอง ส่วน `msg.sender` และ `msg.value` ยังคงมีค่าจากการเรียกครั้งแรก

พฤติกรรมนี้ทำให้สร้างพร็อกซี ไลบรารี และโมดูลกระเป๋าเงินอัจฉริยะได้ แต่ก็ทำให้โค้ดที่ได้รับมอบสิทธิ์มีอำนาจโดยพฤตินัยของสัญญาผู้เรียกด้วย การเขียนข้อมูลลงพื้นที่จัดเก็บ การโอนสินทรัพย์ การอนุมัติ หรือการเรียกสัญญาภายนอกจะดำเนินการในนามของสัญญาผู้เรียก ไม่ใช่เป้าหมายที่ให้โค้ดมา

ให้ถือว่าทุกเป้าหมายที่เข้าถึงได้ผ่าน `delegatecall` เป็นโค้ดที่มีสิทธิ์ระดับสูง ความปลอดภัยขึ้นอยู่กับกฎการเลือกเป้าหมาย ความเข้ากันได้ของโครงสร้างพื้นที่จัดเก็บ สถานะการเริ่มต้นใช้งาน การควบคุมการอัปเกรด และอิมพลีเมนเทชันที่ทำงานจริงสำหรับธุรกรรมนั้น

<a id="mechanism"></a>

## วิธีการทำงาน

ในการเรียกสัญญาภายนอกตามปกติ สัญญาที่ถูกเรียกจะอ่านและเขียนพื้นที่จัดเก็บของตนเอง แต่เมื่อใช้ `delegatecall` ไบต์โค้ดของเป้าหมายจะทำงานกับพื้นที่จัดเก็บของสัญญาผู้เรียก กล่าวคือ คำสั่ง `SSTORE` จะเปลี่ยนสล็อตของสัญญาผู้เรียก ชื่อตัวแปรของเป้าหมายไม่มีผลขณะรันไทม์ มีเพียงตำแหน่งสล็อตที่คำนวณได้เท่านั้นที่สำคัญ

จึงมีขอบเขตสี่ด้านที่ต้องตรวจสอบ:

- **การควบคุมเป้าหมาย:** ตรวจสอบว่าปลายทางถูกกำหนดตายตัว เลือกโดยผู้ใช้ ค้นหาผ่านรีจิสทรี หรือเปลี่ยนแปลงได้โดยผู้ดูแลระบบ
- **ความเข้ากันได้ของพื้นที่จัดเก็บ:** เปรียบเทียบลำดับและชนิดของตัวแปร การสืบทอด ช่องว่างสำรองในพื้นที่จัดเก็บ รวมถึงสล็อตแบบตั้งชื่อหรือแบบมาตรฐานในอิมพลีเมนเทชันทุกเวอร์ชัน
- **การเริ่มต้นใช้งานและการอนุญาต:** ยืนยันว่าไม่สามารถเรียก initializer ซ้ำได้ และฟังก์ชันอัปเกรดหรือจัดการโมดูลบังคับใช้ผู้เรียกและระยะเวลาหน่วงของการกำกับดูแลตามที่กำหนด
- **การจัดการค่าที่ส่งกลับ:** ตรวจสอบว่าข้อผิดพลาดถูกส่งต่อ และข้อมูลที่ส่งกลับถูกถอดรหัสเป็นชนิดที่คาดไว้ การเรียกระดับต่ำไม่มีการตรวจสอบชนิดสัญญาตามปกติของ Solidity

ERC-1967 ลดการชนกันในพร็อกซีด้วยการเก็บที่อยู่ของอิมพลีเมนเทชัน beacon และผู้ดูแลระบบไว้ในสล็อตมาตรฐานที่อยู่นอกการจัดสรรตามปกติของคอมไพเลอร์ แต่ไม่ได้พิสูจน์ว่าอิมพลีเมนเทชันปลอดภัยหรือการอัปเกรดที่ได้รับอนุญาตไม่มีอันตราย

<a id="example"></a>

## ตัวอย่าง

สมมติว่ากระเป๋าเงินเก็บ `owner` ไว้ใน `slot 0` ปลั๊กอินที่คอมไพล์โดยมี `counter` อยู่ใน `slot 0` จะเพิ่มค่าตัวนับเมื่อกระเป๋าเงินเข้าถึงปลั๊กอินผ่าน `delegatecall`

การเขียนข้อมูลนี้เปลี่ยนค่า `owner` ของกระเป๋าเงิน เพราะพื้นที่จัดเก็บเป็นของกระเป๋าเงิน หากค่าที่ได้เข้ารหัสที่อยู่ซึ่งผู้โจมตีควบคุม การตรวจสอบสิทธิ์ในภายหลังอาจยอมรับผู้โจมตีเป็นเจ้าของ แม้ว่าปลั๊กอินจะไม่เคยถือครองสินทรัพย์ของกระเป๋าเงินเลย

ใบรับธุรกรรมที่สำเร็จไม่ได้แยกความแตกต่างระหว่างการเปลี่ยนสถานะตามเจตนากับการเปลี่ยนแปลงที่เป็นอันตราย ดังนั้นการจำลองธุรกรรมควรตรวจสอบผลต่างของพื้นที่จัดเก็บ การเปลี่ยนแปลงสินทรัพย์และการอนุมัติ อีเวนต์ที่ถูกปล่อย และการเรียกที่ตามมา โดยอ้างอิงที่อยู่พร็อกซีและอิมพลีเมนเทชันที่ถูกต้องตรงกัน

<a id="risks"></a>

## ความเสี่ยง

- **การเรียกใช้เป้าหมายใดก็ได้:** เป้าหมายที่ผู้ใช้ควบคุมหรือผ่านการตรวจสอบไม่รัดกุมอาจเรียกใช้โค้ดอันตรายด้วยสิทธิ์ของสัญญาผู้เรียก
- **การชนกันของพื้นที่จัดเก็บ:** อิมพลีเมนเทชันอาจเขียนทับข้อมูลเจ้าของ ยอดคงเหลือ สถานะหยุดชั่วคราว หรือแม้แต่สล็อตที่ใช้เลือกอิมพลีเมนเทชันถัดไป
- **การอัปเกรดที่ไม่ปลอดภัย:** ผู้ดูแลระบบหรือกระบวนการกำกับดูแลที่ถูกเจาะระบบอาจแทนที่โค้ดที่เคยผ่านการตรวจสอบแล้ว หลังจากผู้ใช้ฝากสินทรัพย์หรือให้สิทธิ์อนุมัติ
- **การเริ่มต้นใช้งานล้มเหลว:** พร็อกซีหรืออิมพลีเมนเทชันที่ยังไม่ได้เริ่มต้นใช้งานอาจเปิดทางให้บัญชีอื่นยึดบทบาทที่มีสิทธิ์ระดับสูงหรือกำหนดค่าการพึ่งพาที่เป็นอันตราย
- **การตรวจสอบที่ทำให้เข้าใจผิด:** การตรวจสอบเฉพาะซอร์สของพร็อกซี อิมพลีเมนเทชันปัจจุบัน หรืออินเทอร์เฟซ อาจพลาด beacon การอัปเกรดที่รอดำเนินการ รีจิสทรีโมดูล หรือเส้นทางการทำงานอื่น

ก่อนลงนาม ให้ระบุอิมพลีเมนเทชัน ณ บล็อกล่าสุด ตรวจสอบว่าใครเปลี่ยนได้และต้องรอนานเท่าใด ตรวจสอบไบต์โค้ดที่ยืนยันแล้วและโครงสร้างพื้นที่จัดเก็บของเป้าหมาย จำลอง calldata ทั้งหมด และเปรียบเทียบพื้นที่จัดเก็บที่ละเอียดอ่อนกับการอนุมัติโทเค็นก่อนและหลังการดำเนินการ สำหรับกระเป๋าเงินอัจฉริยะ ให้ตรวจสอบด้วยว่าโมดูลถูกเปิดใช้ ปิดใช้ และได้รับอนุญาตให้เลือกเป้าหมายอย่างไร

<a id="misconceptions"></a>

## ความเข้าใจผิดที่พบบ่อย

- **“เป้าหมายไม่สามารถแตะต้องสินทรัพย์ของสัญญาผู้เรียกได้”** โค้ดที่ได้รับมอบสิทธิ์ทำงานในนามของสัญญาผู้เรียก และสามารถเรียกสัญญาภายนอก โอนสินทรัพย์ หรือสร้างการอนุมัติได้ หากสัญญาผู้เรียกมีความสามารถเหล่านั้น
- **“ชื่อตัวแปรที่ตรงกันป้องกันการชนกันได้”** EVM ใช้สล็อตพื้นที่จัดเก็บ ไม่ใช่ชื่อในซอร์สโค้ด ลำดับโครงสร้าง การสืบทอด และชนิดต้องเข้ากันได้เสมอ
- **“โค้ดพร็อกซีที่ได้รับการยืนยันหมายความว่าทั้งระบบได้รับการยืนยันแล้ว”** อิมพลีเมนเทชันที่ทำงานอยู่ beacon ผู้ดูแลการอัปเกรด สถานะการเริ่มต้นใช้งาน และสิทธิ์ของโมดูล ล้วนเป็นส่วนแยกกันของขอบเขตความไว้วางใจ

<a id="related"></a>

## หัวข้อที่เกี่ยวข้อง

- [ความปลอดภัยทางเศรษฐศาสตร์คริปโต](/th/crypto/crypto-economic-security/)
- [RPC สำหรับธุรกรรมส่วนตัว](/th/crypto/private-transaction-rpc/)
- [สัญญาพร็อกซี](/th/crypto/proxy-contract/)
- [สัญญาอัจฉริยะ](/th/crypto/smart-contract/)
- [การจำลองธุรกรรม](/th/crypto/transaction-simulation/)

<a id="sources"></a>

## แหล่งที่มา

- [Introduction to Smart Contracts](https://docs.soliditylang.org/en/latest/introduction-to-smart-contracts.html) - Solidity Documentation (เข้าถึงเมื่อ: 2026-08-20)
- [Units and Globally Available Variables](https://docs.soliditylang.org/en/latest/units-and-global-variables.html) - Solidity Documentation (เข้าถึงเมื่อ: 2026-08-20)
- [ERC-1967: Proxy Storage Slots](https://eips.ethereum.org/EIPS/eip-1967) - Ethereum Improvement Proposals (เข้าถึงเมื่อ: 2026-08-20)

Source: https://wiki.fcontext.com/th/crypto/delegatecall-storage-risk/index.mdx
