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

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

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

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

ArzPlus Logo آلت‌سیزن شروع شده!🚀

همین حالا در ارزپلاس ثبت‌نام کن و به بیش از 900 آلت‌کوین پرسود بازار دسترسی داشته باش.

ثبت نام و خرید سریع
قرارداد هوشمند چیست ؟ با کاربردهای 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) و غیره استفاده کنند که آسیب‌پذیری در همه آن‌ها به چشم می‌خورد.

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

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

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

فیچر آلتکوین‌
تحلیل تکنیکال

تحلیل تکنیکال قیمت اتریوم (ETH)، سولانا (SOL) و ریپل (XRP)؛ ۲۹ مرداد ۱۴۰۴

29 مرداد 1404 - 10:00
86
فیچر کلی ای تی اف
اخبار آلتکوین

تاخیر دوباره SEC؛ تصمیم‌گیری درباره ETFهای کریپتویی به پاییز موکول شد!

28 مرداد 1404 - 13:00
48
فیچر اتریوم
اخبار اتریوم

نمودارهای اتر سیگنال می‌دهند: اصلاح به ۳.۹ هزار دلار، آغازی برای یک جهش ۱۰۰ درصدی

28 مرداد 1404 - 11:00
162
فیچر تحلیل آلت کوین اتوبوسی
تحلیل تکنیکال

تحلیل تکنیکال قیمت اتریوم (ETH)، سولانا (SOL) و بی ان بی (BNB)؛ ۲۸ مرداد ۱۴۰۴

28 مرداد 1404 - 09:30
161
فیچر اخبار اتریوم و تحلیل قیمت اتریوم
اخبار اتریوم

هجوم سرمایه به صندوق‌های ارز دیجیتال؛ اتریوم قهرمان هفته شد!

27 مرداد 1404 - 21:00
55
وضعیت کنونی توکن‌های NFT؛ آیا بازار توکن‌های بی‌همتا جان تازه‌ای خواهد گرفت؟
NFT

سقوط ۱.۲ میلیارد دلاری بازار NFT؛ پاجی پنگوئنز مجموعه بورد ایپ را کنار زد

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

آموزش

وضعیت کنونی توکن‌های NFT؛ آیا بازار توکن‌های بی‌همتا جان تازه‌ای خواهد گرفت؟
NFT

سقوط ۱.۲ میلیارد دلاری بازار NFT؛ پاجی پنگوئنز مجموعه بورد ایپ را کنار زد

27 مرداد 1404 - 19:00
56
moonbirds-nfts مجموعه انفتی مون بردز
NFT

بازگشت شگفت‌انگیز مون بردز؛ NFT شکست‌خورده‌ای که دوباره جان گرفت

26 مرداد 1404 - 19:00
41
فیچر مالیات بیت کوین
مقالات عمومی

۵ کشوری که در سال ۲۰۲۵ رمزارزها در آن‌ها معاف از مالیات هستند!

26 مرداد 1404 - 18:00
696
فیچر هیومنیتی پروتکل
کریپتو کده

هیومنیتی پروتکل (Humanity Protocol) چیست؟ تحولی در تایید هویت دیجیتال

24 مرداد 1404 - 22:00
113
رتبه بندی اعتباری آنچین
کریپتو پدیا

رتبه بندی اعتباری آنچین چیست؟ همکاری شرکت اعتبارسنجی مودیز با بلاکچین سولانا

24 مرداد 1404 - 20:00
64
فیچر بازیابی بیت کوین ها یگمشده با فناوری کوانتومی
مقالات عمومی

آیا بازیابی بیت کوین‌های گمشده با فناوری کوانتومی امکان‌پذیر است؟

24 مرداد 1404 - 16:00
119

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

تاخیر برداشت در اکسکوینو

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

5 مرداد 1404 - 17:00
3112

کلاهبرداری با کیف پول چند امضایی چیست و چگونه از آن در امان بمانیم؟

حمله انتقال صفر (Zero-Transfer)؛ راهنمای کامل شناسایی و مقابله با تهدید کیف پول‌های رمزارزی

تاثیر تصویب قانون GENIUS بر ریسک فریز و مسدود شدن دارایی‌های تتر ایرانی‌ها؛ چه باید کرد؟

اشتباه ۶۰ هزار دلاری کاربر بیت کوین در پرداخت کارمزد؛ مراقب باشید این اشتباه را تکرار نکنید!

تسلیم یا کاپیتولاسیون (Capitulation) در کریپتو چیست؟ نشانه ترس یا فرصتی برای ورود به بازار؟

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

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

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

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