میهن بلاکچین
  • اخبار
    • همه
    • رمزارز در ایران
    • اخبار بیت کوین
    • اخبار اتریوم
    • اخبار آلتکوین
    • اخبار بلاکچین
    • اخبار عمومی
    • اطلاعیه صرافی‌های داخلی
  • تحلیل
    • همه
    • تحلیل آنچین
    • تحلیل اقتصادی
    • تحلیل تکنیکال
    • تحلیل فاندامنتال
  • آموزش
    • همه
    • کریپتو پدیا
    • کریپتو کده
    • دیفای
    • سرمایه گذاری
    • آموزش همه صرافی های ارز دیجیتال
    • ترید
    • کیف پول
    • بازی
    • استخراج
    • NFT
    • مقالات عمومی
  • ایردراپ
  • هک و کلاهبرداری
  • قیمت ارزهای دیجیتال
  • ماشین حساب ارزهای دیجیتال
  • مقایسه قیمت در صرافی
No Result
مشاهده همه‌ی نتایج
  • اخبار
    • همه
    • رمزارز در ایران
    • اخبار بیت کوین
    • اخبار اتریوم
    • اخبار آلتکوین
    • اخبار بلاکچین
    • اخبار عمومی
    • اطلاعیه صرافی‌های داخلی
  • تحلیل
    • همه
    • تحلیل آنچین
    • تحلیل اقتصادی
    • تحلیل تکنیکال
    • تحلیل فاندامنتال
  • آموزش
    • همه
    • کریپتو پدیا
    • کریپتو کده
    • دیفای
    • سرمایه گذاری
    • آموزش همه صرافی های ارز دیجیتال
    • ترید
    • کیف پول
    • بازی
    • استخراج
    • NFT
    • مقالات عمومی
  • ایردراپ
  • هک و کلاهبرداری
  • قیمت ارزهای دیجیتال
  • ماشین حساب ارزهای دیجیتال
  • مقایسه قیمت در صرافی
No Result
مشاهده همه‌ی نتایج
میهن بلاکچین
No Result
مشاهده همه‌ی نتایج
میهن بلاکچین آموزش کریپتو پدیا

آموزش ساخت یک قرارداد هوشمند اتریوم برای قرعه کشی

نگارش:‌ایوب کریمی
11 تیر 1401 - 14:55
در کریپتو پدیا
زمان مطالعه: 4 دقیقه
0
قرارداد هوشمند اتریوم

تصادفی بودن کامل در شبکه اتریوم تقریبا غیر ممکن است. دلیل این امر این است که لازم است که تراکنش‌ها توسط نود‌های مختلفی روی شبکه تایید شوند. اگر یک تابع قرارداد هوشمند کاملا تصادفی باشد، هر نودی که تراکنش را با استفاده از آن تابع تایید کند، منجر به ایجاد نتایج مختلفی خواهد شد و این یعنی تراکنش هرگز روی بلاکچین اتریوم تایید نمی‌شود. اخیرا اعلامیه‌ای در این زمینه توسط یکی از بزرگترین بازیگران اکوسیستم اتریوم بیرون داده شد که موجب شور و هیجان زیادی پیرامون این مشکل شد. با استفاده از یک سیستم بنام عملکرد تصادفی قابل تایید (VRF)، قرارداد‌های هوشمند اتریوم حالا می‌توانند اعداد تصادفی ایجاد کنند. این یعنی مفاهیمی که قبلا برای قرارداد هوشمند بسیار مناسب بودند و تنها به دلیل نیاز به اعداد تصادفی قابل اجرا نبودند، اینک در عمل قابل اجرا هستند. یکی از چنین مفاهیمی مفهوم قرعه‌کشی (Lottery) در اتریوم است که اینجا مورد بحث قرار می‌گیرد. برای آشنایی با لاتاری در اتریوم با میهن بلاکچین همراه باشید.

قرارداد هوشمند چیست ؟ با کاربردهای Smart Contract آشنا شوید
این مقاله در تاریخ ۱۰ تیر ۱۴۰۱ به‌روزرسانی شده است.

آنچه در این مطلب می‌خوانید

Toggle
  • ساخت یک قرارداد هوشمند اتریوم برای قرعه کشی
  • تعریف مراحل
  • ارائه اعداد
  • طراحی عدد
  • پرسش و پاسخ (FAQ)
  • جمع‌بندی

ساخت یک قرارداد هوشمند اتریوم برای قرعه کشی

قرعه کشی در اتریوم
Source: morioh.com

قرعه‌ کشی در اتریوم سه مرحله خواهد داشت. مرحله اول مرحله باز کردن (Open) است که هر کس می‌تواند اعداد جدید را در قبال کارمزدی کم ارائه دهد. مرحله دوم مرحله بستن (Closed) است که هیچ عدد جدیدی را نمی‌توان ارائه داد و عدد تصادفی در حال ایجاد شدن است. مرحله سوم مرحله خاتمه است که عدد ایجاد شده است و به برنده پرداخت شده است. اگر کسی برنده نشود، قرارداد قرعه‌کشی متوقف می‌شود و جایزه افزایش پیدا می‌کند.

تعریف مراحل

مراحل ساخت قرارداد هوشمند قرعه کشی در اتریوم باید اقدامات را محدود کنند، بنابراین تنها فعالیت‌های مجاز را می‌توان اجرا کرد. به عنوان مثال، تنها مرحله‌ای که باید ارائه جدید را اجازه دهد، مرحله افتتاح است. اگر قرعه‌کشی بسته یا تمام شود، قرارداد هوشمند باید ارائه‌های جدید را ممنوع کند.

با استفاده از enum، می‌توانیم هر چقدر که بخواهیم مرحله تعریف کنیم. اجازه دهید آن را LotteryState بنامیم. در متغیر‌های وضعیت، ما مورد زیر را تعریف می‌کنیم:

enum LotteryState { Open, Closed, Finished }
LotteryState public state;

حال که شمارش تعریف شد، می‌توان قوانین را در توابع تنظیم کرد و اطمینان حاصل کرد که وضعیت حال حاضر این قرارداد هوشمند اتریوم همان چیزی است که ما انتظار داریم.

این وضعیت‌های require احتمالا در سراسر قرارداد مشابه هستند، اجازه دهید آن را به حداقل برسانیم. ما می‌توانیم تعدیل‌کننده‌ای را تعریف کنیم که اظهار require را اجرا کند. و در نهایت می‌توانیم آن را برای هر تابعی که بخواهیم تعیین کنیم.

modifier isState(LotteryState _state) {
    require(state == _state, "Wrong state for this action");
    _;
}

حال وقتی که ما توابع را تعریف می‌کنیم، می‌توانیم این تعدیل‌کننده را اضافه کنیم تا از وضعیت حال حاضر قرعه‌کشی اطمینان حاصل کنیم و مطابق انتظار ما باشد.

ارائه اعداد

تا زمانی که کارمزد ورود پرداخت شده باشد، هر کسی باید اجازه ارائه یک عدد داشته باشد. البته هر وارد‌شونده نمی‌تواند همان عدد را بیش از یک بار ارائه دهد. تنها وضعیتی که باید ارائه‌های جدید اجازه داده شود، وضعیت یا مرحله افتتاح است. تابع SubmitNumber ما به صورت زیر است: function submitNumber(uint _number) public payable isState(LotteryState.Open) { require(msg.value >= entryFee, “Minimum entry fee required”); require(entries[_number].add(msg.sender), “Cannot submit the same number more than once”); numbers.push(_number); numberOfEntries++; payable(owner()).transfer(ownerCut); emit NewEntry(msg.sender, _number); } view rawsubmitNumber.sol hosted with ❤ by GitHub

خط اول نام، پارامتر خاص _number و این حقیقت که آن public و payable است را تعریف می‌کند. آن همچنین تعدیل‌کننده isState را اضافه می‌کند تا از باز بودن قرعه‌کشی اطمینان حاصل شود.

خط ۲ اطمینان حاصل می‌کند که کارمزد صحیح ورود پرداخت شده است و خط ۳ اطمینان حاصل می‌کند که فرستنده آن پیام از قبل آن عدد را ارائه نداده است و آن را به ورودی‌های فرآیند اضافه می‌کند.

توسعه دهنده قرارداد هوشمند اتریوم هستید؟ این اصولی امنیتی را در نظر بگیرید!

متغیر entries به نوعی طرح‌بندی اشاره دارد که عدد حدس زده شده و مجموعه‌ای از آدرس‌هایی که داخل عدد شده‌اند را تعریف می‌کند. آن به صورت زیر تعریف می‌شود:

mapping(uint => EnumerableSet.AddressSet) entries;

AdressSet به قرارداد هوشمند EnumerableSet اشاره دارد که عملکرد اضافی را برای تایپ‌های اولیه فراهم می‌آورد. زمانی که بررسی‌ها کامل شد، چهار خط بعدی، شماره را به حدس‌ها اضافه می‌کنند و درصد کوچکی از کات (cut) مالک را پرداخت کرده و یک واقعه NewEntry صادر می‌کنند.

طراحی عدد

اگر شما نحوه استفاده از VRF را بدانید، می‌دانید که ایجاد یک عدد تصادفی تنهایی به این سادگی نیست که یک تابع خاص را فراخوانی کنید. برای ایجاد یک عدد تصادفی، باید تصادفی بودن را از VRF تقاضا کنید و تابعی را اعمال کنید که VRF بتواند با پاسخ فراخوانی کند. به همین خاطر، لازم است که یک مصرف‌کننده VRF تعریف کنیم که آن را در شکل دوم RandomNumberGenerator می‌نامیم. pragma solidity ^0.6.2; import “./VRFConsumerBase.sol”; import “./Lottery.sol”; contract RandomNumberGenerator is VRFConsumerBase { address requester; bytes32 keyHash; uint256 fee; constructor(address _vrfCoordinator, address _link, bytes32 _keyHash, uint256 _fee) VRFConsumerBase(_vrfCoordinator, _link) public { keyHash = _keyHash; fee = _fee; } function fulfillRandomness(bytes32 _requestId, uint256 _randomness) external override { Lottery(requester).numberDrawn(_requestId, _randomness); } function request(uint256 _seed) public returns(bytes32 requestId) { require(keyHash != bytes32(0), “Must have valid key hash”); requester = msg.sender; return this.requestRandomness(keyHash, fee, _seed); } } view rawRandomNumberGenerator.sol hosted with ❤ by GitHub

قرعه‌کشی ما آدرس این قرارداد هوشمند اتریوم را به عنوان یک پارامتر به این ساخت وارد می‌کند. وقتی که عدد را طراحی می‌کنیم، آن تابع request نامیده خواهد شد. این تصادفی بودن را از VRF تقاضا می‌کند که در عوض جواب را برای filfullRandomness در خط ۱۸ فراهم می‌آورد. شما در فراخوانی‌های شکل ۲ می‌بینید که این به قرارداد Lottery ما با numberDrawn برگشت داده می‌شود. اجازه دهید آن توابع را تعریف کنیم: function drawNumber(uint256 _seed) public onlyOwner isState(LotteryState.Open) { _changeState(LotteryState.Closed); randomNumberRequestId = RandomNumberGenerator(randomNumberGenerator).request(_seed); emit NumberRequested(randomNumberRequestId); } function numberDrawn(bytes32 _randomNumberRequestId, uint _randomNumber) public onlyRandomGenerator isState(LotteryState.Closed) { if (_randomNumberRequestId == randomNumberRequestId) { winningNumber = _randomNumber; emit NumberDrawn(_randomNumberRequestId, _randomNumber); _payout(entries[_randomNumber]); _changeState(LotteryState.Finished); } } view rawdrawingNumbers.sol hosted with ❤ by GitHub

drawNumber در تعریف ما، تنها می‌تواند توسط مالک قرعه‌کشی فراخوانی شود و تنها وقتی می‌تواند فراخوانی شود که قرعه‌کشی در وضعیت افتتاح باشد. numberDrawn در خط ۷، تابعی است که زمانی که عدد تصادفی توسط VRF دریافت شد، توسط fulfillRandomness فراخوانی می‌شود. آن اطمینان حاصل می‌کند که request-id، آی دی (ID) بازگشت داده شده از درخواست است که رویداد را صادر می‌کند، به برنده پرداخت انجام می‌دهد و وضعیت قرعه‌کشی را به finished تغییر می‌دهد. و در نهایت کد نود کامل به صورت زیر خواهد بود:


pragma solidity >=0.6.2;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/EnumerableSet.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "./RandomNumberGenerator.sol";

contract Lottery is Ownable{

	using EnumerableSet for EnumerableSet.AddressSet;
	using Address for address;
	using SafeMath for uint;

	enum LotteryState { Open, Closed, Finished }

	mapping(uint => EnumerableSet.AddressSet) entries;
	uint[] numbers;
	LotteryState public state;
	uint public numberOfEntries;
	uint public entryFee;
	uint public ownerCut;
	uint public winningNumber;
	address randomNumberGenerator;
	bytes32 randomNumberRequestId;

	event LotteryStateChanged(LotteryState newState);
	event NewEntry(address player, uint number);
	event NumberRequested(bytes32 requestId);
	event NumberDrawn(bytes32 requestId, uint winningNumber);

	// modifiers
	modifier isState(LotteryState _state) {
		require(state == _state, "Wrong state for this action");
		_;
	}

	modifier onlyRandomGenerator {
		require(msg.sender == randomNumberGenerator, "Must be correct generator");
		_;
	}

	//constructor
	constructor (uint _entryFee, uint _ownerCut, address _randomNumberGenerator) public Ownable() {
		require(_entryFee > 0, "Entry fee must be greater than 0");
		require(_ownerCut < _entryFee, "Entry fee must be greater than owner cut");
		require(_randomNumberGenerator != address(0), "Random number generator must be valid address");
		require(_randomNumberGenerator.isContract(), "Random number generator must be smart contract");
		entryFee = _entryFee;
		ownerCut = _ownerCut;
		randomNumberGenerator = _randomNumberGenerator;
		_changeState(LotteryState.Open);
	}

	//functions
	function submitNumber(uint _number) public payable isState(LotteryState.Open) {
		require(msg.value >= entryFee, "Minimum entry fee required");
		require(entries[_number].add(msg.sender), "Cannot submit the same number more than once");
		numbers.push(_number);
		numberOfEntries++;
		payable(owner()).transfer(ownerCut);
		emit NewEntry(msg.sender, _number);
	}

	function drawNumber(uint256 _seed) public onlyOwner isState(LotteryState.Open) {
		_changeState(LotteryState.Closed);
		randomNumberRequestId = RandomNumberGenerator(randomNumberGenerator).request(_seed);
		emit NumberRequested(randomNumberRequestId);
	}

	function rollover() public onlyOwner isState(LotteryState.Finished) {
		//rollover new lottery
	}

	function numberDrawn(bytes32 _randomNumberRequestId, uint _randomNumber) public onlyRandomGenerator isState(LotteryState.Closed) {
		if (_randomNumberRequestId == randomNumberRequestId) {
			winningNumber = _randomNumber;
			emit NumberDrawn(_randomNumberRequestId, _randomNumber);
			_payout(entries[_randomNumber]);
			_changeState(LotteryState.Finished);
		}
	}

	function _payout(EnumerableSet.AddressSet storage winners) private {
		uint balance = address(this).balance;
		for (uint index = 0; index < winners.length(); index++) {
			payable(winners.at(index)).transfer(balance.div(winners.length()));
		}
	}

	function _changeState(LotteryState _newState) private {
		state = _newState;
		emit LotteryStateChanged(state);
	}
}
view rawlottery.sol hosted with ❤ by GitHub

پرسش و پاسخ (FAQ)

پرسش و پاسخ میهن بلاکچین
  • چگونه با استفاده از قرارداد هوشمند اتریوم قرعه کشی انجام بدهیم؟

کد قرعه کشی در اتریوم را می‌توان با استفاده از توابع تصادفی قابل تایید (VRF) و زبان سالیدیتی ایجاد کرد. کد ایجاد لاتاری در اتریوم را در ادامه مطلب می‌توانید مشاهده کنید.

  • نحوه ایجاد قرار داد هوشمند در اتریوم چگونه است؟

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

جمع‌بندی

آنچه که دیدید یک پیاده‌سازی اولیه از قرارداد هوشمند قرعه کشی در اتریوم است. اما نشان می‌دهد که چگونه ظهور تصادفی بودن قابل تایید در بلاک چین، میزان پیچیدگی قرارداد‌هایی مانند قرارداد هوشمند قرعه‌کشی را در بستر اتریوم کاهش می‌دهد. در قرارداد‌های شرط‌بندی قبلی لازم بود که از مکانیسم‌های هشینگ، مکانیسم‌های زمانی، مکانیسم‌های مبتنی بر بلاک (Block) و غیره استفاده کنند که آسیب‌پذیری در همه آن‌ها به چشم می‌خورد.

آیا برای نوشتن قرارداد هوشمند قرعه کشی در اتریوم تلاش کرده‌اید؟ لطفا تجربیات و نظرات خود را با ما در میان بگذارید.

تگ: اتریومقرارداد هوشمند
اشتراک‌گذاریتوئیت

نوشته‌های مشابه

تحلیل تکنیکال

تحلیل تکنیکال قیمت بیت کوین (BTC) و اتریوم (ETH)؛ ۱۸ اردیبهشت ۱۴۰۴

18 اردیبهشت 1404 - 10:30
234
ورلد لیبرتی
اخبار آلتکوین

رای‌گیری برای پروپوزال ایردراپ USD1 به هولدرهای WLFI آغاز شد؛ نگرانی سناتورهای دموکرات!

17 اردیبهشت 1404 - 18:00
30
ارتقای تاریخی پکترا (Pectra) در مین نت اتریوم فعال شد؛ گامی بزرگ از ادغام تا مقیاس‌پذیری لایه ۲
اخبار اتریوم

ارتقای تاریخی پکترا (Pectra) در مین نت اتریوم فعال شد؛ گامی بزرگ از ادغام تا مقیاس‌پذیری لایه ۲

17 اردیبهشت 1404 - 16:30
118
تحلیل تکنیکال بیت کوین و اتریوم
تحلیل تکنیکال

تحلیل تکنیکال قیمت بیت کوین (BTC) و اتریوم (ETH)؛ ۱۶ اردیبهشت ۱۴۰۴

16 اردیبهشت 1404 - 09:00
119
فیچر رویدادهای کریپتویی هفته
تحلیل فاندامنتال

رویدادهای مهم کریپتویی در هفته آتی؛ از اصلاحات قانونی تا نوسانات بازار

14 اردیبهشت 1404 - 16:30
88
اخبار اتریوم

قیمت اتریوم در برابر بیت کوین نزدیک به سطوح کلیدی سال ۲۰۱۹؛ آیا ۴۵۰٪ رشد تکرار خواهد شد؟!

14 اردیبهشت 1404 - 15:00
527
اشتراک
اطلاع از
0 دیدگاه
جدید ترین
قدیمی ترین محبوب ترین
Inline Feedbacks
View all comments

آموزش

کرنل دائو kernel
کریپتو پدیا

کرنل دائو (KernelDAO) چیست؟ پیشگام نوآوری ری‌استیکینگ در دیفای چندزنجیره‌ای

19 اردیبهشت 1404 - 20:00
18
ترید کریپتو در رکود
ترید

ترید کریپتو در دوران رکود اقتصادی؛ هنر بقا در روزهای سخت

19 اردیبهشت 1404 - 16:00
94
نرخ بهره فدرال رزرو
کریپتو پدیا

نرخ بهره فدرال رزرو چیست؟

19 اردیبهشت 1404 - 12:00
105
صرافی یونی سواپ Uniswap
صرافی غیرمتمرکز

یونی‌ سواپ درگیر بحران حکمرانی؛ نماینده باسابقه DAO استعفا داد

18 اردیبهشت 1404 - 17:00
56
راه‌اندازی شبکه لایه دو توسط صرافی OKX با همکاری پالیگان؛ رشد OKB ادامه دارد؟
صرافی غیرمتمرکز

فعالیت مجدد تجمیع‌کننده DEX صرافی OKX؛ سیستم‌های امنیتی تقویت شدند

15 اردیبهشت 1404 - 17:00
71
گروک
آموزش

آموزش خودکارسازی معاملات ارز دیجیتال با هوش مصنوعی Grok 3

13 اردیبهشت 1404 - 08:09
3.4k

پیشنهاد سردبیر

میکروپرداخت‌ها

آینده میکروپرداخت‌ها (Micro Payments)؛ بررسی چالش‌های قدیمی و راه‌حل‌ها

13 اردیبهشت 1404 - 08:10
140

آموزش خودکارسازی معاملات ارز دیجیتال با هوش مصنوعی Grok 3

بهترین پروژه‌های اکوسیستم سویی (SUI) که ارزش توجه دارند

تعرفه چیست و چرا اهمیت دارد؟ راهنمای ساده و دقیق برای درک نقش تعرفه‌ها در تجارت جهانی

تحلیل تکنیکال یا پیش‌گویی؟ نگاهی صادقانه به دنیای تریدر

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

  • خانه
  • قیمت ارز
  • صرافی ها
  • ماشین حساب
No Result
مشاهده همه‌ی نتایج
  • اخبار
    • همه
    • رمزارز در ایران
    • اخبار بیت کوین
    • اخبار اتریوم
    • اخبار آلتکوین
    • اخبار بلاکچین
    • اخبار عمومی
    • اطلاعیه صرافی‌های داخلی
  • تحلیل
    • همه
    • تحلیل آنچین
    • تحلیل اقتصادی
    • تحلیل تکنیکال
    • تحلیل فاندامنتال
  • آموزش
    • همه
    • کریپتو پدیا
    • کریپتو کده
    • دیفای
    • سرمایه گذاری
    • آموزش همه صرافی های ارز دیجیتال
    • ترید
    • کیف پول
    • بازی
    • استخراج
    • NFT
    • مقالات عمومی
  • ایردراپ
  • هک و کلاهبرداری
  • قیمت ارزهای دیجیتال
  • ماشین حساب ارزهای دیجیتال
  • مقایسه قیمت در صرافی

© 2025 - تمامی حقوق مادی و معنوی این وبسایت نزد میهن بلاکچین محفوظ است