QX ERC20 Science Token /** *Представлено для проверки на etherscan.io на 2020-12-24 * /
Pragma Solidy ^0,6,0;
/**
@dev Обертки над арифметическими операциями Solidity с добавленным переполнением
чеки
Арифметические операции в солидности обертывают переполнение. Это может легко привести
в ошибках, потому что программисты обычно предполагают, что переполнение повышает
Ошибка, которая является стандартным поведением в языках программирования высокого уровня.
SafeMath восстанавливает эту интуицию, возвращая транзакцию, когда
операция переполнения.
Использование этой библиотеки вместо неконтролируемых операций устраняет целый
Класс ошибок, поэтому рекомендуется использовать его всегда. / библиотека Safemath { / *
@dev возвращает добавление двух неподписанных целых чисел, возвращаясь
переполнение.
Аналог оператора Solidity + .
Требования:
возврат C; }
/**
- Solidity./**
@dev возвращает вычитание двух беспингевых целых чисел, возвращаясь на пользовательское сообщение на
переполнение (когда результат отрицательный).
Аналогичный - Solidity.
Требования:
возврат C; }
/**
@dev возвращает умножение двух беззнатных целых чисел, возвращаясь
переполнение.
Аналогичный оператор солидности * .
Требования:
uint256 c = a * b; требуется (c / a == b, "safemath: ulliplow overflow");
возврат C; }
/**
/ оператора. Примечание: эта функция используетrevert код OpCod/**
@dev возвращает целочисленное подразделение двух беспингевых целых чисел. Возвращается с пользовательским сообщением на
разделение по ноль. Результат округлен к нулю.
Аналог для солидности / оператора. Примечание: эта функция использует
revert код OpCod
использует неверный оплот для возврата (потребление всего оставшегося газа).
Требования:
возврат C; }
/**
% . Эта функция использует revert/**
% . Эта функция использует revert// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
@DEV Стандартные математические утилиты отсутствуют на языке солидности. / библиотека математика { / *
/**
/**
// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
@dev ищет отсортированный array и возвращает первый индекс, который содержит
значение больше или равное element . Если такой индекс не существует (т.е.
значения в массиве строго меньше, чем element ), длина массива
вернулся. Временная сложность o (log n).
Ожидается, что array будет отсортирован в порядке возрастания и не содержать
Повторные элементы. */ function findupperbound (uint256 [] Массив хранения, элемент UINT256) Внутреннее представление возвращает (uint256) {if (array.length == 0) {return 0; }
uint256 low = 0; uint256 High = array.length;
while (low <high) {uint256 mid = math.average (low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds down (it does integer division with truncation).
if (array[mid] > element) {
high = mid;
} else {
low = mid + 1;
}
}
// На данный момент low - исключительная верхняя граница. Мы вернем инклюзивную верхнюю границу. if (low> 0 && array [low - 1] == element) {return low - 1; } else {return low; }}}
// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
@title счетчики
@author Мэтт Кондон (@shrugs)
@DEV предоставляет счетчики, которые могут быть увеличены или уменьшены только одним. Это можно использовать, например, для отслеживания числа
элементов в картировании, выдачи ERC721 IDS или подсчета идентификаторов запросов.
Включите с using Counters for Counters.Counter;
Поскольку невозможно переполнить 256 -битное целое число с приращением одного, increment может пропустить {safemath}
Проверка переполнения, тем самым экономя газ. Это действительно предполагает правильное использование в том смысле, что базовая _value никогда не будет
непосредственно доступен. */ Библиотечные счетчики {используя SafeMath для Uint256;
struct counter {// Эта переменная никогда не должна быть доступна непосредственно пользователями библиотеки: взаимодействия должны быть ограничены // функции библиотеки. Начиная с Solidity v0.5.2, это не может быть применено, хотя существует предложение добавить // Эта функция: см. Ethereum/Solidity#4637 Uint256 _value; // по умолчанию: 0}
Функция тока (счетчик счетчика счетчика) Внутреннее представление возврата (Uint256) {return counter._value; }
Приращение функции (счетчик счетчиков) внутренний {// {safemath} Проверка переполнения может быть пропущена здесь, см. Комментарий на верхнем счетчике ._value += 1; }
Уменьшение функции (счетчик счетчиков) внутренний {counter._value = counter._value.sub (1); }}
// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/*
@dev предоставляет информацию о текущем контексте выполнения, включая
отправитель транзакции и ее данные. Хотя они обычно доступны
через msg.sender и msg.data, к ним не следует получить доступ к такому прямому
способ, когда при работе с мета-транзакциями GSN отправляют аккаунт и
Оплата выполнения может не быть фактическим отправителем (в отношении заявки
обеспокоен).
Этот контракт требуется только для промежуточных, библиотечных контрактов. */ Аннотация Контекст контракта {function _msgsender () Внутреннее представление виртуальные возвраты (адрес оплачивается) {return msg.sender; }
function _msgdata () Внутреннее представление виртуальное возврат (байтс -память) {this; // Silence State Mintability Предупреждение без генерирования Bytecode - см. Ethereum/Solidity#2691 return msg.data; }}
// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
@dev интерфейс стандарта ERC20, как определено в EIP. / интерфейс ierc20 { / *
/**
account . */ Function Balanceof (адресная учетная запись) Внешнее представление возврата (Uint256);/**
amount токенов из учетной записи вызывающего в recipient ./**
spenderowner через {Transferfrom}. Это/**
amount как пособие spender на токены вызывающего абонента./**
amount tokens от sender к recipient , используяamount вычитается из вызывающего абонента/**
value перемещаются из одной учетной записи ( from ) вto ).value может быть нулю. */ Передача событий (адрес индексируется с адреса, индексированного до, uint256 значение);/**
spender для owner установленаvalue - это новое пособие. */ Утверждение события (указанный на адрес владелец, указанный адрес, индексированный Spender, значение UINT256); }// частичная лицензия: MIT
Pragma Solidy ^0,6,2;
/**
@dev Коллекция функций, связанных с типом адреса / Библиотека Адрес { / *
@dev возвращает True, если account является контрактом.
[ВАЖНЫЙ]
====
Небезопасно предполагать, что адрес, для которого эта функция возвращает
Неверно-это аккаунт извне (EOA), а не договор.
Среди прочего, isContract вернет ложь для следующего
Типы адресов:
==== */ function isContract (адресная учетная запись) Внутреннее представление возврата (bool) {// Этот метод зависит от ExtCodeSize, который возвращает 0 для контрактов в // конструкции, поскольку код хранится только в конце выполнения // конструктора.
uint256 размер; // solhint-disable-next-line no-inline-assembly сборка {size: = extcodesize (учетная запись)} return размер> 0; }
/**
@dev замена для transfer Solidity: отправляет amount в Wei на
recipient , пересылка всего доступного газа и возвращение ошибок.
https://eips.ethereum.org/eips/eip-1884* eip1884] увеличивает стоимость газа
определенных опкомпонов, возможно, заключение контрактов превышает лимит газа 2300
навязывается transfer , что делает их неспособными получать средства через
transfer . {SendValue} Удаляет это ограничение.
https://diligence.consensys.net/posts/2019/09/stop-using-solitys-transfer-now/tlearn больше].
ВАЖНО: Поскольку контроль передается recipient , должна быть осторожность
Взятые, чтобы не создавать уязвимостей повторной деятельности. Подумайте об использовании
{Reentrancyguard} или
https://solidity.readthedocs.io/en/v0.5.11/security-conderations.html#use-the-checks-effects-interctions-pattern® Паттерн-интеллектуальность]. */ function sendValue (адрес, подлежащий уплате, получатель, UINT256 Сумма) Внутренняя {require (Addrance (this) .balance> = сумма, «Адрес: недостаточный баланс»);
// solhint-disable-next-line vense-low-сигналы, избегание V-Value (Bool Success,) = получатель. Требование (успех », адрес: невозможно отправить значение, получатель мог бы отказаться»); }
/**
call . Аcall - это небезопасная замена для вызова функции: используйте этоtarget возвращается с возвратной причиной, она пузырится этимtarget должна быть договором.target с data не должен возвращаться./**
functionCall ], но сerrorMessage как запасная причина вернуть причину, когда target возвращается./**
functionCall ],value вей на target .value .payable ./**
functionCallWithValue ], ноerrorMessage в качестве запасной причины вернуть причину, когда target возвращается.function _functionCallWithValue (Целевая цель адреса, данные памяти байтов, UINT256 WEIVEIVEUE, Строковая память ErrorMessage) Private Returns (Bytes Memory) {require (iscontract (target), «Адрес: вызов в неконтракту»);
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}}
// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
@dev Реализация интерфейса {ierc20}.
Эта реализация является агностикой для создания токенов. Это означает
что механизм поставки должен быть добавлен в полученный контракт с использованием {_mint}.
Для общего механизма см. {ERC20PRESETMInterPauser}.
Совет: подробная запись см. Наше руководство
https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226* How
для реализации механизмов снабжения].
Мы следовали общедоступным рекомендациям Openzeppelin: функции возвращаются вместо этого
возврата false при неудаче. Такое поведение, тем не менее, обычное
и не конфликтует с ожиданиями приложений ERC20.
Кроме того, событие {утверждение} испускается при вызовах {TransferFrom}.
Это позволяет приложениям реконструировать пособие для всех учетных записей.
Слушая упомянутые события. Другие реализации EIP могут не излучать
Эти события, как это не требуется для спецификации.
Наконец, нестандартный {DecielseAllowance} и {увеличивание}
Функции были добавлены для смягчения хорошо известных проблем, связанных с настройкой
пособия. Смотрите {ierc20-approve}. */ Контракт ERC20 - это контекст, IERC20 {Использование SAFEMATH для UINT256; Использование адреса для адреса;
Картирование (адрес => uint256) private _balances;
Картирование (Address => mapping (Address => Uint256)) private _Allainces;
uint256 private _totalsupply;
String private _name; строка частной _symbol; uint8 private _decimals;
/**
/**
/**
/**
decimals равенства 2 , баланс 505 токенов должен5,05 ( 505 / 10 ** 2 )./**
/**
/**
recipient не может быть нулевым адресом.amount . */ Передача функции (получатель адреса, UINT256 сумма) Общественное виртуальное переопределение возврата (bool) {_transfer (_msgsender (), получатель, сумма); вернуть истину; }/**
/**
spender не может быть нулевым адресом. */ Функция утверждения (адрес Spender, UINT256 SUTP) Общественное виртуальное переопределение возврата (BOOL) {_Approve (_MSGSENDER (), SPENDER, SUMP); вернуть истину; }/**
sender и recipient не могут быть нулевым адресом.sender должен иметь баланс не менее amount .sender , по крайней мере,amount . */ function transferfrom (отправитель адреса, получатель адреса, UINT256 сумма) Общественный виртуальный переопределение возврата (bool) {_transfer (отправитель, получатель, сумма); _prope (отправитель, _msgsender (), _allowances [отправитель] [_ msgsender ()]. sub (сумма, "ERC20: сумма передачи превышает пособие")); вернуть истину; }/**
spender Caller.spender не может быть нулевым адресом. */ function увеличивание (Address Spender, Uint256 AddValue) Публичные виртуальные возвраты (BOOL) {_PARPOVE (_MSGSENDER (), SPENDER, _Allowances [_MSGSENDER ()] [SPENDER] .ADD (ADDVALUE)); вернуть истину; }/**
spender Caller.spender не может быть нулевым адресом.spender должен иметь пособие для абонента, по крайней мере,subtractedValue . */ Функция DEMEASEALLOWANCE (ADDREAD SPENDER, UINT256 SUPTRACTEDVALUE) Общественные виртуальные возвраты (BOOL) {_PARPOVE (_MSGSENDER (), SPENDER, _Allowances [_MSGSENDER ()] [SPENDER] .SUB (SUBTRACTEDVALUE, «ERC20: снижение разрешения ниже Zero»); вернуть истину; }/**
@dev перемещает amount токенов от sender к recipient .
Это внутренняя функция эквивалентна {Transfer} и может использоваться для
Например, реализовать автоматические платы за токен, механизмы сокращения и т. Д.
Излучает событие {Transfer}.
Требования:
sender не может быть нулевым адресом.recipient не может быть нулевым адресом.sender должен иметь баланс не менее amount . */ function _transfer (отправитель адреса, получатель адреса, Uint256 Summ). требуется (получатель! = Адрес (0), "ERC20: передача на нулевой адрес");_beforeTokentRansfer (отправитель, получатель, сумма);
_balances [Sender] = _Balances [Sender] .sub (сумма, "ERC20: Сумма передачи превышает баланс"); _balances [получатель] = _balances [получатель] .Add (сумма); EdiT Transfer (отправитель, получатель, сумма); }
/** @dev создает токены amount и назначает их account , увеличиваясь
Общее предложение.
Излучает событие {Transfer} from Set до нулевого адреса.
Требования
to может быть нулевым адресом. */ function _mint (адресная учетная запись, сумма Uint256) Внутренний виртуальный {require (account! = Адрес (0), "ERC20: Mint на нулевой адрес");_beforeTokentRansfer (адрес (0), учетная запись, сумма);
_totalsupply = _totalsupply.add (сумма); _balances [account] = _balances [account] .Add (сумма); EdiT Transfer (адрес (0), учетная запись, сумма); }
/**
@dev разрушает токены amount с account , уменьшая
общее количество запасов.
Излучает событие {Transfer}, to установить на нулевой адрес.
Требования
account не может быть нулевым адресом.account должна иметь как amount токены. */ function _burn (Адресная учетная запись, UINT256 SUTP) Внутренняя виртуальная {require (account! = Адрес (0), "ERC20: сжигать с нулевого адреса");_beforeTokEntransfer (учетная запись, адрес (0), сумма);
_balances [account] = _balances [account] .sub (сумма, "ERC20: Сумма сжигания превышает баланс"); _totalsupply = _totalsupply.sub (сумма); EDIM -передача (учетная запись, адрес (0), сумма); }
/**
@DEV устанавливает amount как spender по токенам owner .
Эта внутренняя функция эквивалентна для approve и может использоваться для
Например, установить автоматические пособия для определенных подсистем и т. Д.
Излучает событие {утверждение}.
Требования:
owner не может быть нулевым адресом.spender не может быть нулевым адресом. */ function _pprove (Владелец адреса, адрес Address Spender, Uint256 сумма) Внутренний виртуальный {require (владелец! = Адрес (0), "ERC20: утвердить из нулевого адреса"); Требуется (Spender! = Адрес (0), "ERC20: одобрить нулевой адрес");_allowances [владелец] [spender] = сумма; излучать одобрение (владелец, Spender, сумма); }
/**
/**
from to , что оба ненулевые, amount токенов fromto .from нуля нуль, amount будут отчитаны to .to ноль, amount токенов from токенов будет сожжено.from и to не ноль.// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
@dev Этот контракт расширяет токен ERC20 с механизмом снимка. Когда создается снимок, баланс и
Общее количество поставки в то время записывается для последующего доступа.
Это может быть использовано для безопасного создания механизмов, основанных на балансах токенов, таких как достоверные дивиденды или взвешенное голосование.
В наивных реализациях можно выполнить атаку «двойные расходы», повторно используя один и тот же баланс из разных
счета. Используя снимки для вычисления дивидендов или голосования, эти атаки больше не применяются. Это также может быть
Используется для создания эффективного механизма развязки ERC20.
Снимки создаются функцией внутренней {_SNAPSHOT}, которая излучит событие {Snapshot} и вернет
идентификатор снимка. Чтобы получить общий предложение во время снижения, вызовите функцию {totalSupplyat} с помощью снижения.
идентификатор. Чтобы получить баланс учетной записи во время снижения, вызовите функцию {balanceofat} с идентификатором снимка
и адрес счета.
==== Затраты на газ
Снимки эффективны. Создание снимка - O (1) . Поиск остатков или полного снабжения с моментального снимка - _O (журнал
n) _ В количестве созданных снимков, хотя n для конкретной учетной записи, как правило, будет много
Меньше, так как идентичные балансы в последующих снимках хранятся в виде единой записи.
Существует постоянная накладная расходы для обычных трансфертов ERC20 из -за дополнительной бухгалтерской работы. Это накладное расходы есть
Только значимый для первой передачи, который немедленно следует за снижением для конкретной учетной записи. Последующий
Переводы будут иметь нормальную стоимость до следующего снимка и так далее. */ abstract contract ERC20Snapshot is ERC20 { // Inspired by Jordi Baylina's MiniMeToken to record historical balances: // https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol
Использование SafeMath для Uint256; Использование массивов для Uint256 []; Использование счетчиков для счетчиков.counter;
// Снимок значений имеют массивы идентификаторов и значение, соответствующее этому идентификатору. Это может быть массив структуры снимка //, но это препятствует использованию функций, которые работают на массиве. struct Snapshots {uint256 [] ids; uint256 [] значения; }
Картирование (адрес => снимки) private _accountbalancesnapshots; Снимки частные _totalsupplysnapshots;
// идентификаторы снимков монотонно увеличиваются, причем первое значение является 1. Идентификатор 0 является недействительным. Counters.counter private _currentsnapshotid;
/**
id . */ Снимок события (UINT256 ID);/**
@dev создает новый снимок и возвращает свой идентификатор снимка.
Излучает событие {Snapshot}, которое содержит тот же идентификатор.
{_SNAPSHOT} является internal , и вы должны решить, как это выставить внешнее. Его использование может быть ограничено
Набор учетных записей, например, с использованием {AccessControl}, или он может быть открыт для общественности.
[ПРЕДУПРЕЖДЕНИЕ]
====
В то время как открытый способ вызова {_SNAPSHOT} требуется для определенных механизмов минимизации доверия, таких как разбрызгивание,
Вы должны учитывать, что он может быть потенциально использовать злоумышленники двумя способами.
Во -первых, его можно использовать для увеличения стоимости извлечения значений из снимков, хотя он будет расти
Логарифмично таким образом делает эту атаку неэффективной в долгосрочной перспективе. Во -вторых, его можно использовать для нацеливания
Конкретные счета и увеличить стоимость переводов ERC20 для них, как указано в затратах на газ
Раздел выше.
Мы не измерили фактические числа; Если это то, что вас интересует, обратитесь к нам.
==== */ function _snapshot () внутренние виртуальные возвраты (uint256) {_currentsnapshotid.increment ();
uint256 currentid = _currentsnapshotid.current (); EdiT Snapshot (CurrentID); вернуть CurrentId; }
/**
@dev получает баланс account в то время, когда был создан snapshotId . */ function balanceofat (адресная учетная запись, Uint256 Snapshotid) Общественное представление возврата (Uint256) {(Bool Snapshotted, uint256 значение) = _valueat (Snapshotid, _AccountBalanceSnapshots [account]);
Вернуть снимки? значение: баланс (счет); }
/**
@dev извлекает общий предложение в то время, когда был создан snapshotId . */ function totalsupplyat (uint256 Snapshotid) Общественное представление возвращает (uint256) {(Bool Snapshotted, uint256 значение) = _valueat (Snapshotid, _totalsupplysnapshots);
Вернуть снимки? значение: totalSupply (); }
// Обновление баланса и/или общих снимков питания до того, как значения будут изменены. Это реализовано // в крючке _beforetokentransfer, который выполняется для операций _mint, _burn и _transfer. Функция _beforetokentransfer (адрес от, адрес to, uint256 сумма) Внутреннее виртуальное переопределение {super._beforetokentransfer (от, до, сумма);
if (from == address (0)) {// mint _updateaccountsnapshot (to); _UpDateTotalSupplySnapShot (); } else if (to == Address (0)) {// Burn _updateaccountsnapshot (from); _UpDateTotalSupplySnapShot (); } else {// Transfer _updateAccountsnapshot (from); _updateaccountsnapshot (to); }}
Функция _valueat (Uint256 Snapshotid, Snapshots StorageShots) Частный вид return (bool, uint256) {require (snapshotid> 0, "erc20snapshot: id 0"); // solhint-disable-next-line максимальная линейная длина (Snapshotid <= _currentsnapshotid.current (), "ERC20SNAPSHOT: не существующий идентификатор");
// When a valid snapshot is queried, there are three possibilities:
// a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
// created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
// to this id is the current one.
// b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
// requested id, and its value is the one to return.
// c) More snapshots were created after the requested one, and the queried value was later modified. There will be
// no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
// larger than the requested one.
//
// In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
// it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
// exactly this.
uint256 index = snapshots.ids.findUpperBound(snapshotId);
if (index == snapshots.ids.length) {
return (false, 0);
} else {
return (true, snapshots.values[index]);
}
}
function _updateaccountsnapshot (адресная учетная запись) private {_updatesnapshot (_accountbalancesnapshots [account], balance (account)); }
function _updateTotalSupplySnapShot () private {_UpdatesNapShot (_totalSupplySnapShots, totalSupply ()); }
function _updatesnapshot (снимки снимков хранения, uint256 currentValue) private {uint256 currentId = _currentsnapshotid.current (); if (_lastsnapshotid (snapshots.ids) <currentId) {snapshots.ids.push (currentId); Snapshots.values.push (CurrentValue); }}
функция _lastsnapshotid (uint256 [] идентификаторы хранения) частное представление возвращает (uint256) {if (ids.length == 0) {return 0; } else {return ids [ids.length - 1]; }}}
// частичная лицензия: MIT
Pragma Solidy ^0,6,0;
/**
Библиотека @dev для управления
https://en.wikipedia.org/wiki/set_(abstract_data_type)® Примитива
типы
Наборы имеют следующие свойства:
(O (1)).
Пример контракта {
// Add the library methods
using EnumerableSet for EnumerableSet.AddressSet;
// Declare a set state variable
EnumerableSet.AddressSet private mySet;
}
По состоянию на v3.0.0, только наборы типового address ( AddressSet ) и uint256
( UintSet ) поддерживаются. */ библиотека перечисленных по счетам {// Для реализации этой библиотеки для нескольких типов с максимально небольшим кодом // повторения, мы записываем ее в терминах общего типа набора со значениями // bytes32. // Реализация SET использует частные функции, а пользовательские // реализации (например, AddressSet)-это просто обертки вокруг // базового набора. // Это означает, что мы можем создавать только новые перечисления для типов, которые подходят // в Bytes32.
struct set {// хранилище установленных значений bytes32 [] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
/**
@dev удаляет значение из набора. O (1).
Возвращает true, если значение было удалено из набора, то есть если оно было
подарок. */ function _remove (установить набор хранилища, значение Bytes32) Private Returns (bool) {// Мы читаем и сохраняем индекс значения, чтобы предотвратить несколько чтений из того же слота хранения uint256 vildex = set._indexes [value];
if (valueIndex! = 0) {// эквивалентно содержимому (установить, значение) // Чтобы удалить элемент из массива _values в o (1), мы обмениваемся элементом, чтобы удалить с последним в // массив, а затем удалять последний элемент (иногда называемый как 'SWAP и POP'). // Это изменяет порядок массива, как отмечено в {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {return false; }}
/**
/**
/**
index позиции в наборе. O (1).index должен быть строго меньше, чем {длина}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { require(set._values.length > index, "EnumerableSet: index out of bounds"); return set._values[index]; }// AddressSet
struct AddressSet { Set _inner; }
/**
/**
/**
/**
/**
index in the set. O(1).index must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint256(_at(set._inner, index))); }// UintSet
struct UintSet { Set _inner; }
/**
/**
/**
/**
/**
index in the set. O(1).index must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); }}// Partial License: MIT
pragma solidity ^0.6.0;
/**
@dev Contract module that allows children to implement role-based access
control mechanisms.
Roles are referred to by their bytes32 identifier. These should be exposed
in the external API and be unique. The best way to achieve this is by
using public constant hash digests:
bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
Roles can be used to represent a set of permissions. To restrict access to a
function call, use {hasRole}:
function foo() public {
require(hasRole(MY_ROLE, msg.sender));
...
}
Roles can be granted and revoked dynamically via the {grantRole} and
{revokeRole} functions. Each role has an associated admin role, and only
accounts that have a role's admin role can call {grantRole} and {revokeRole}.
By default, the admin role for all roles is DEFAULT_ADMIN_ROLE , which means
that only accounts with this role will be able to grant or revoke other
roles. More complex role relationships can be created by using
{_setRoleAdmin}.
WARNING: The DEFAULT_ADMIN_ROLE is also its own admin: it has permission to
grant and revoke this role. Extra precautions should be taken to secure
accounts that have been granted it. */ abstract contract AccessControl is Context { using EnumerableSet for EnumerableSet.AddressSet; using Address for address;
struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; }
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
newAdminRole is set as role 's admin role, replacing previousAdminRoleDEFAULT_ADMIN_ROLE is the starting admin for all roles, despite/**
account is granted role .sender is the account that originated the contract call, an admin role/**
account is revoked role .sender is the account that originated the contract call:revokeRole , it is the admin role bearerrenounceRole , it is the role bearer (ie account ) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);/**
true if account has been granted role . */ function hasRole(bytes32 role, address account) public view returns (bool) { return _roles[role].members.contains(account); }/**
role . Can be used/**
role . index must be a/**
role . See {grantRole} and/**
@dev Grants role to account .
If account had not been already granted role , emits a {RoleGranted}
событие.
Требования:
role 's admin role. */ function grantRole(bytes32 role, address account) public virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");_grantRole(role, account); }
/**
@dev Revokes role from account .
If account had been granted role , emits a {RoleRevoked} event.
Требования:
role 's admin role. */ function revokeRole(bytes32 role, address account) public virtual { require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");_revokeRole(role, account); }
/**
@dev Revokes role from the calling account.
Roles are often managed via {grantRole} and {revokeRole}: this function's
purpose is to provide a mechanism for accounts to lose their privileges
if they are compromised (such as when a trusted device is misplaced).
If the calling account had been granted role , emits a {RoleRevoked}
событие.
Требования:
account . */ function renounceRole(bytes32 role, address account) public virtual { require(account == _msgSender(), "AccessControl: can only renounce roles for self");_revokeRole(role, account); }
/**
role to account .account had not been already granted role , emits a {RoleGranted}/**
adminRole as role 's admin role.function _grantRole(bytes32 role, address account) private { if (_roles[role].members.add(account)) { emit RoleGranted(role, account, _msgSender()); }}
function _revokeRole(bytes32 role, address account) private { if (_roles[role].members.remove(account)) { emit RoleRevoked(role, account, _msgSender()); } } }
pragma solidity 0.6.8;
contract QXToken is Context, AccessControl, ERC20Snapshot { bytes32 public constant SNAPSHOT_ROLE = keccak256("SNAPSHOT_ROLE");
constructor(uint256 amount, uint8 decimals) ERC20("QX ERC20", "QX") public {
_setupDecimals(decimals);
_mint(msg.sender, amount);
// set up required roles
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(SNAPSHOT_ROLE, _msgSender());
}
/**
* @dev Creates a new snapshot and returns its snapshot id.
* Emits a {Snapshot} event that contains the same id.
*/
function snapshot() public {
require(hasRole(SNAPSHOT_ROLE, _msgSender()), "Must have snapshot role to create a snapshot");
_snapshot();
}
}