تشخیص این که یک آدرس، آدرس یک قرارداد هوشمند هست یا نه با استفاده از سالیدیتی

امروز موقع نوشتن یه کانترکت نیاز داشتم چک کنم یه آدرسی که به اون قراره توکنی رو انتقال بدم، حتما آدرس یک قرارداد هوشمند باشه

تو سرچ هام به opcode زیر رسیدم:
EXTCODESIZE

کار این آپکد این هستش که میره سایزی که کد اجرایی یه آدرس تو مرکل تری (Merkle tree)استیت (state) اتریوم گرفته رو میخونه و برمیگرده

خب معلومه اگه اون آدرس EOA باشه کدی ذخیره نکرده و سایزی که این آپ کد برمیگردونه صفر هستش

و اما الان به یه آپکد دسترسی داریم و ویژگی ایش رو میشناسیم ولی مسئله ما این بودش که با استفاده از سالیدتی بتونیم این کار رو بکنیم

اگه زبان سی کار کرده باشید ممکنه همچین عبارتی رو تو متن ها دیده باشید
Inline assembly

این ویژگی به برنامه نویس های سی اجازه میداد که وسط کد های سی ای که مینویسن بتونن اگه نیاز داشتن از opcode های خود cpu به صورت مستقیم استفاده کنن
https://en.cppreference.com/w/c/language/asm

توی سالیدیتی هم مفهوم مشابه ای وجود داره و به ما این اجازه رو میده که مستقیما بتونیم آپ کدی های EVM ای رو صدا بزنیم
https://docs.soliditylang.org/en/v0.8.3/assembly.html

حالا با دونستن این دوتا میتونیم یه فانکشن بنویسیم که چک کنه یه آدرس کانترکت هست یا نه

و با کمی سرچ درست تر فهمیدم این رو openzeppelin توی بخش کتابخونه Address پیاده سازی کرده

8 پسندیده

دو تا نکته‌ای که خیلی مهم هست:

۱. پیشبینی آدرس قرارداد‌هوشند قبل از دیپلوی

شما قبل از اینکه یک قرارداد رو دیپلوی کنید میتونید آدرس رو پیشبینی کنید. مثلا به این صورت

def mk_contract_address(sender, nonce):
    return sha3(rlp.encode([normalize_address(sender), nonce]))[12:]
# code sample from https://ethereum.stackexchange.com/questions/760/how-is-the-address-of-an-ethereum-contract-computed

و این فرایند با استفاده از CREATE2 حتی ساده تر هم هست.

آدرس قرارداد‌هوشندی که هنوز کدش دیپلوی نشده با آدرس معمولی قابل تشخیص نیست. این باعث میشه که کسی بتونه شرط isContractی که در بالا چک می کنید رو دور بزنه.

۲. سایز کد قرارداد هوشمند در زمان دیپلوی و اجرای Constructor صفر است.

در زمانی که شما قرارداد‌هوشمند رو دیپلوی می کنید در اولین مرحله تابع Constructor اجرا میشه. در این زمان کد هنوز روی بلاکچین به ثبت نرسیده و سایزش صفر است.

حالا اگر قراردادی در این تابع٫ قرارداد شما رو صدا بزنه٫ قرارداد شما نمی فهمه که از طرف یک قرارداد کال شده و میشه شرط isContract رو باز دور زد.

5 پسندیده

مرسی شایان بابت نکته هات :ok_hand: :ok_hand:

خیلی ریز و حیاتی بودن

من از این استفاده میکردم که تشخیص بدم، آدرسی که داره یه تابع رو صدا میزنه حتما خودش به قرار داد هوشمند باشه (برام مهم این بود که یه EOA اون تابع رو نتونه صدا بزنه)

و طبق نکته هات اگه این تابع رو یکی تو Constructor قرارداد خودش صدا بزنه با قراردادی که من نوشتم به مشکل میخوره که حالا باید حلش کنم

دمت گرم که گفتی :grin: :v: :v: :beers:

1 پسندیده