QX ERC20 Science Token /** *2020-12-24にEtherscan.ioで検証のために提出されました * /
プラグマの堅牢性 ^0.6.0;
/**
@devは、オーバーフローが追加されたSolidityの算術操作についてラッパーします
チェック。
堅牢性の算術操作オーバーフローのラップ。これは簡単に生じる可能性があります
バグでは、プログラマーは通常、オーバーフローが上昇すると想定しているため
エラー。これは、高レベルのプログラミング言語での標準動作です。
SafeMath 、次のとおりにトランザクションを戻すことにより、この直感を復元します
操作オーバーフロー。
未チェックの操作の代わりにこのライブラリを使用すると、全体が排除されます
バグのクラスなので、常に使用することをお勧めします。 /図書館Safemath { / *
@devは、2つの署名されていない整数の追加を返します。
オーバーフロー。
Solidity's + Operatorに対応します。
要件:
c; }
/**
-に対応しています。/**
@devは、2つの署名のない整数の減算を返し、カスタムメッセージで戻ります
オーバーフロー(結果が負の場合)。
Solidityの-に対応しています。
要件:
c; }
/**
@devは、2つの署名のない整数の乗算を返し、戻ります
オーバーフロー。
Solidityの*オペレーターに対応します。
要件:
uint256 c = a * b;要求(c / a == b、 "Safemath:乗算オーバーフロー");
c; }
/**
/ Operatorに対応します。注:この関数はaを使用しますrevert/**
@devは、2つの署名されていない整数の整数部門を返します。カスタムメッセージをオンに戻します
ゼロによる分割。結果はゼロに丸められます。
Solidity / Operatorに対応します。注:この関数はaを使用します
堅牢性中、オペコード(残りのガスが触れられないままになります)をrevert
無効なオペコードを使用して戻ります(残りのすべてのガスを消費します)。
要件:
c; }
/**
%オペレーターに対応します。この関数はrevertを使用します/**
%オペレーターに対応します。この関数はrevertを使用します//部分ライセンス:MIT
プラグマの堅牢性 ^0.6.0;
/**
@Dev Solidity Languageで欠落している標準の数学ユーティリティ。 /ライブラリ数学{ / *
/**
/**
//部分ライセンス:MIT
プラグマの堅牢性 ^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
プラグマの堅牢性 ^0.6.0;
/**
@titleカウンター
@author matt condon(@shrugs)
@Devは、1つによってのみ増加または減少できるカウンターを提供します。これは、たとえば数を追跡するために使用できます
マッピング、ERC721 IDの発行、またはリクエストIDのカウント内の要素の。
using Counters for Counters.Counter;
1つの増分で256ビットの整数をオーバーフローすることはできないため、 increment {Safemath}をスキップできます
オーバーフローチェック、それによりガスを節約します。根底にある_valueは決してないという点で、これは正しい使用法を想定しています
直接アクセス。 */ライブラリカウンター{UINT256にSafeMathを使用。
struct counter {//この変数は、ライブラリのユーザーが直接アクセスしてはなりません。 Solidity V0.5.2の時点で、これは強制できませんが、//この機能を追加する提案があります。 //デフォルト:0}
関数電流(カウンターストレージカウンター)内部ビューリターン(uint256){return counter._value; }
関数の増分(カウンターストレージカウンター)内部{// {safemath}オーバーフローチェックはここでスキップできます。上のカウンターでコメントを参照してください。_value += 1; }
関数Decroment(カウンターストレージカウンター)内部{counter._value = counter._value.sub(1); }}
//部分ライセンス:MIT
プラグマの堅牢性 ^0.6.0;
/*
@devは、現在の実行コンテキストに関する情報を提供します。
トランザクションとそのデータの送信者。これらは一般的に利用可能です
msg.senderとmsg.dataを介して、そのような直接でアクセスしないでください
マナー、GSNメタトランザクションを扱うとき、アカウントの送信と
実行のために支払うことは実際の送信者ではないかもしれません(アプリケーションに関しては
関係しています)。
この契約は、中間の図書館のような契約にのみ必要です。 */ abstract Contract Context {function _msgsender()内部ビュー仮想リターン(アドレス支払可能){return msg.sender; }
function _msgdata()内部ビュー仮想リターン(バイトメモリ){this; //バイトコードを生成せずに沈黙状態の可変性警告 - ethereum/solidity#2691を参照してくださいmsg.dataを返します。 }}
//部分ライセンス:MIT
プラグマの堅牢性 ^0.6.0;
/**
EIPで定義されているERC20標準の@DEVインターフェイス。 /インターフェイスierc20 { / *
/**
accountが所有するトークンの量を返します。 */ function balangeof(アドレスアカウント)外部ビューリターン(uint256);/**
amountをrecipientに移動します。/**
spenderがする残りのトークンの数を返しますownerに代わって支出することを許可されます。これはです/**
spenderの手当としてamountを設定します。/**
senderからrecipientへのトークンamountを使用して移動しますamountは発信者から差し引かれます/**
valueトークンが1つのアカウントから( from )に移動されたときに放出されますto )。valueゼロになる可能性があることに注意してください。 */イベント転送(アドレスインデックス付き、アドレスインデックス付き、uint256値からのアドレス);/**
ownerのspenderの手当がによって設定されたときに放出されましたvalueは新しい手当です。 */イベント承認(アドレスインデックスオーナー、アドレスインデックススペンダー、UINT256値); }//部分ライセンス:MIT
プラグマの堅牢性 ^0.6.2;
/**
アドレスタイプ/ライブラリアドレスに関連する関数の@devコレクション{ / *
@devは、 accountが契約の場合、trueを返します。
[重要]
====
この関数が戻ってくるアドレスが
Falseは、外部所有のアカウント(EOA)であり、契約ではありません。
とりわけ、 isContract以下の虚偽を返します
アドレスの種類:
===== */ function isContract(アドレスアカウント)内部ビューリターン(bool){//このメソッドは、//コンストラクターの実行の最後にのみ保存されるため、//構築の契約に0を返すextcodesizeに依存しています。
UINT256サイズ。 // solhint-disable-next-line no-inline-assemblyアセンブリ{size:= extcodesize(account)} return size> 0; }
/**
Solidityのtransferの@Dev交換: amountを送信しますwei
recipient 、利用可能なすべてのガスを転送し、エラーで戻る。
https://eips.ethereum.org/eips/eip-1884 [eip1884]ガスコストが増加します
特定のオプコードのうち、おそらく契約を締結して2300のガス制限を超えています
transferによって課され、彼らを経由して資金を受け取ることができなくなる
transfer 。 {SendValue}この制限を削除します。
https://diligence.consensys.net/posts/2019/09/stop-using-solidity-transfer-now/
重要:コントロールはrecipientに転送されるため、ケアは
再発の脆弱性を生み出さないと考えられています。使用を検討してください
{ReentrancyGuard}または
https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-cattern [checks-effects-interactions pattern]。 */ function sendvalue(アドレス支払可能な受信者、uint256額)内部{require(address(this).balance> = bolant、 "address:adress:不十分な残高");
// solhint-disable-next-line回避-low-level-calls、asmuse-call-value(bool success、)= reciontient.call {value:lument}( "");要求(成功、 "住所:価値を送信できません、受信者は戻った可能性があります"); }
/**
callを使用してSolidity関数コールを実行します。 acall 、関数呼び出しのための安全でない代替品です:これを使用してくださいtargetが戻る理由で戻る場合、それはこれによってバブルアップされますtarget契約でなければなりません。dataでtargetを呼び出すことは、戻ってはいけません。/**
functionCall ]、buterrorMessage 、 targetが戻るときに理由を戻します。/**
functionCall ]、value Weiをtargetに転送します。valueのETHバランスが必要です。payableばなりません。/**
functionCallWithValue ]、buttargetが戻るときに、フォールerrorMessageとしてのエラーズを逆転させます。function _FunctionCallWithValue(アドレスターゲット、バイトメモリデータ、UINT256 Weivalue、String Memory ErrorMessage)プライベートリターン(バイトメモリ){require(isContract(ターゲット)、 "アドレス:非契約の呼び出し");
// 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
プラグマの堅牢性 ^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のその他の実装は放出されない場合があります
これらのイベントは、仕様では要求されていないためです。
最後に、標準以外の{DecoseAllowance}と{suleseallowance}
設定に関するよく知られている問題を軽減するために機能が追加されました
手当。 {ierc20-approve}を参照してください。 */ contract ERC20はコンテキスト、ierc20 {uint256にsafemathを使用しています。アドレスのアドレスを使用します。
マッピング(address => uint256)private _balances;
マッピング(address =>マッピング(address => uint256))プライベート_allowances;
uint256 private _totalsupply;
文字列プライベート_name;文字列プライベート_symbol; uint8 private _decimals;
/**
/**
/**
/**
decimals 2等しい場合、 505トークンのバランスは5,05 ( 505 / 10 ** 2 )としてユーザーに表示されます。/**
/**
/**
recipientゼロアドレスにすることはできません。amountのバランスを持っている必要があります。 */関数転送(アドレス受信者、UINT256量)パブリック仮想オーバーライドリターン(bool){_transfer(_msgsender()、受信者、金額); trueを返します。 }/**
/**
spenderゼロアドレスになることはできません。 */ function承認(アドレスspender、uint256量)パブリック仮想オーバーライドリターン(bool){_approve(_msgsender()、spender、bomul); trueを返します。 }/**
senderとrecipientゼロアドレスになることはできません。senderには、少なくともamountの残高が必要です。senderのトークンを許可する必要がありますamount 。 */関数転送(アドレス送信者、アドレス受信者、UINT256額)パブリック仮想オーバーライドリターン(bool){_ transfer(送信者、受信者、金額); _Approve(sender、_msgsender()、_allowances [sender] [_ msgsender()]。 trueを返します。 }/**
spenderに付与された手当を原子的に増やします。spenderゼロアドレスになることはできません。 */ function suleseallowance(アドレスspender、uint256 addidvalue)public virtual returns(bool){_ approve(_msgsender()、spender、_allowances [_msgsender()] [spender] .add(add(add(add(value)); trueを返します。 }/**
spenderに付与された手当を原子的に減少させます。spenderゼロアドレスになることはできません。spender少なくともの発信者に手当を持っている必要がありますsubtractedValue 。 */ function decasteallowance(アドレスspender、uint256 suppstractedvalue)public virtual returns(bool){_ approve(_msgsender()、spender、_ allowances [_msgsender()] [spender]。 trueを返します。 }/**
@devは、 senderからrecipientにトークンのamountを移動します。
これは内部関数が{転送}と同等であり、
たとえば、自動トークン料金、スラッシングメカニズムなどを実装します。
{転送}イベントを発します。
要件:
senderゼロアドレスになることはできません。recipientゼロアドレスにすることはできません。senderには、少なくともamountの残高が必要です。 */ function _transfer(アドレス送信者、アドレス受信者、uint256額)内部仮想{require(sender!= address(0)、 "eRC20:ゼロアドレスからの転送");要求(受信者!= address(0)、 "ERC20:ゼロアドレスに転送");_beforetokentransfer(送信者、受信者、金額);
_balances [sender] = _balances [sender] .sub(bolent、 "ERC20:転送量が残高を超えます"); _Balances [Reciontient] = _Balances [Reciontient] .Add(額);エミット転送(送信者、受信者、金額); }
/** @devはamountトークンを作成し、それらをaccountに割り当て、増加します
総供給。
セットfromゼロアドレスまでの{転送}イベントを排出します。
要件
toできません。 */ function _mint(アドレスアカウント、uint256額)内部仮想{require(account!= address(0)、 "eRC20:ミントゼロアドレス");_beforetokentransfer(アドレス(0)、アカウント、金額);
_totalsupply = _totalsupply.add(額); _balances [account] = _balances [account] .add(antom);エミット転送(アドレス(0)、アカウント、金額); }
/**
@devはaccountからamountトークンを破壊し、を減らします
総供給。
{転送}イベントをゼロアドレスにtoします。
要件
accountゼロアドレスにすることはできません。accountには、少なくともamountトークンが必要です。 */ function _burn(アドレスアカウント、uint256額)内部仮想{require(account!= address(0)、 "eRC20:ゼロアドレスからの燃焼");_beforetokentransfer(アカウント、アドレス(0)、金額);
_balances [account] = _balances [account] .sub(bolent、 "ERC20:燃焼量が残高を超える"); _totalsupply = _totalsupply.sub(antom);エミット転送(アカウント、アドレス(0)、金額); }
/**
@devは、 ownerのトークンに対するspenderの手当としてamountを設定します。
この内部関数はapproveと同等であり、
たとえば、特定のサブシステムなどの自動手当を設定します。
{承認}イベントを排出します。
要件:
ownerゼロアドレスになることはできません。spenderゼロアドレスになることはできません。 */ function _approve(アドレス所有者、アドレススペンダー、uint256額)内部仮想{require(owner!= address(0)、 "eRC20:Zeroアドレスから承認"); require(spender!= address(0)、 "ERC20:ゼロアドレスを承認する");_Allowances [所有者] [spender] =金額;承認を発する(所有者、スペンダー、金額); }
/**
/**
fromゼロtoの場合は、 fromのトークンのamountto転送することになります。fromゼロの場合、 amountトークンは鋳造toれます。toゼロであるか、 fromのトークンのamount燃やされます。toゼロfromありません。//部分ライセンス:MIT
プラグマの堅牢性 ^0.6.0;
/**
@devこの契約は、スナップショットメカニズムを備えたERC20トークンを拡張します。スナップショットが作成されるとき、バランスと
当時の総供給は、後でアクセスするために記録されます。
これを使用して、信頼のない配当や加重投票などのトークンバランスに基づいてメカニズムを安全に作成できます。
素朴な実装では、異なるバランスを再利用することにより、「二重支出」攻撃を実行することが可能です
アカウント。スナップショットを使用して配当または投票力を計算することにより、これらの攻撃はもはや適用されません。それもそうかもしれません
効率的なERC20フォーキングメカニズムを作成するために使用されます。
スナップショットは{_snapshot}関数によって作成されます。これにより、{snapshot}イベントが発生し、
スナップショットID。スナップショット時に合計供給を取得するには、スナップショットで関数{totalSupplyat}を呼び出します
id。スナップショットの時点でアカウントのバランスを取得するには、スナップショットIDで{balangeoft}関数を呼び出します
およびアカウントアドレス。
====ガスコスト
スナップショットは効率的です。スナップショット作成はO(1)です。スナップショットからの残高または総供給の検索は_o(log
n)_作成されたスナップショットの数では、特定のアカウントのnは一般的に大きくなります
後続のスナップショットの同一のバランスは、単一のエントリとして保存されているためです。
追加のスナップショットブックキーピングにより、通常のERC20転送には一定のオーバーヘッドがあります。このオーバーヘッドはです
特定のアカウントのスナップショットの直後に最初の転送でのみ重要です。その後
転送は、次のスナップショットなどまで通常のコストになります。 */抽象契約ERC20SNAPSHOTはERC20 {// Jordi baylinaのミニマンに触発されて歴史的残高を記録するように触発されています:// https://github.com/giveth/minimd/blob/ea04d950eea153a04c51fa510b0688b9ded390cb/contract.ssmenticl.
UINT256にSafeMathを使用。 UINT256に配列を使用[]; counters.counterにカウンターを使用します。
// SnapShotted値には、IDの配列とそのIDに対応する値があります。これらは// snapshot structの配列である可能性がありますが、それは配列で動作する関数の使用を妨げるでしょう。 struct snapshots {uint256 [] ids; uint256 []値; }
マッピング(アドレス=>スナップショット)プライベート_AccountBalancesNapshots;スナップショットプライベート_totalsupplysnapshots;
//スナップショットIDは単調に増加し、最初の値は1です。0のIDは無効です。 counters.counter private _currentsnapshotid;
/**
idによって識別されたスナップショットが作成されたとき。 */イベントスナップショット(UINT256 ID);/**
@devは新しいスナップショットを作成し、スナップショットIDを返します。
同じIDを含む{snapshot}イベントを排出します。
{_snapshot}はinternalあり、外部から露出する方法を決定する必要があります。その使用はaに制限される場合があります
{AccessControl}を使用するなど、アカウントのセット、または一般に公開されている場合があります。
[警告]
====
フォーキングなどの特定の信頼最小化メカニズムには、{_snapshot}を呼び出すオープンな方法が必要ですが、
攻撃者が2つの方法で使用できる可能性があると考える必要があります。
まず、スナップショットから値の検索コストを増やすために使用できますが、成長します
したがって、この攻撃を長期的には効果的ではないように対数的に。第二に、ターゲットに使用できます
ガスコストで指定された方法で、特定のアカウントとERC20転送のコストを増やします
上記のセクション。
実際の数を測定していません。これがあなたが興味を持っているものなら、私たちに連絡してください。
==== */ function _snapshot()内部仮想リターン(uint256){_currentsnapshotid.increment();
uint256 currentId = _currentsnapshotid.current();エミットスナップショット(currentID); currentIDを返します。 }
/**
@devは、 snapshotIdが作成された時点でaccountの残高を取得します。 */ function balance of(addressアカウント、uint256 snapshotid)パブリックビューリターン(uint256){(bool snapshotted、uint256 value)= _valueat(snapshotid、_accountbalancesnapshots [account]);
スナップショットを返しますか?値:バランス(アカウント); }
/**
@devは、 snapshotIdが作成された時点で総供給を取得します。 */ function totalsupplyat(uint256 snapshotid)パブリックビューリターン(uint256){(bool snapshotted、uint256 value)= _valueat(snapshotid、_totalsupplysnapshots);
スナップショットを返しますか?値:totalSupply(); }
//値が変更される前に、バランスおよび/または合計供給スナップショットを更新します。これは、_mint、_burn、_ transfer操作のために実行される_beforetokentransferフックに//実装されます。 function _beforetokentransfer(アドレス、アドレス、uint256量)内部仮想オーバーライド{super._beforetokentransfer(from、to、anl of);
if(from == address(0)){// mint _updateaccountsnapshot(to); _UPDATETALSUPPLYSNAPSHOT(); } else if(to == address(0)){// burn _updatecountsnapshot(from); _UPDATETALSUPPLYSNAPSHOT(); } else {// _updateaccountsnapshot(from); _UPDATEACCOUNTSNAPSHOT(to); }}
function _valueat(uint256 snapshotid、snapshotsストレージスナップショット)プライベートビューリターン(bool、uint256){require(snapshotid> 0、 "erc20snapshot:id is 0"); // solhint-disable-next-line max-line-length require(snapshotid <= _currentsnapshotid.current()、 "erc20snapshot:negoxistent id");
// 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]、balangeof(account)); }
function _updatetalsupplysnapshot()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); }}
function _lastsnapshotid(uint256 []ストレージids)プライベートビューリターン(uint256){if(ids.length == 0){return 0; } else {return ids [ids.length -1]; }}}
//部分ライセンス:MIT
プラグマの堅牢性 ^0.6.0;
/**
@devライブラリ管理
https://en.wikipedia.org/wiki/set_(abstract_data_type) [sets]のプリミティブ
種類。
セットには次のプロパティがあります。
(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 )がサポートされています。 */ library enumerableset {//コード//繰り返しが少ない複数のタイプにこのライブラリを実装するには、// bytes32値を持つ一般的なセットタイプの観点から書きます。 //セット実装はプライベート機能を使用し、ユーザー向け//実装(アドレスセットなど)は//基礎となるセットの周りのラッパーのみです。 //これは、BYTES32で//フィットするタイプの新しいenumerablesセットのみを作成できることを意味します。
struct set {// 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(Set Storage Set、bytes32 value)private Returns(bool){//値のインデックスを読み取り、保存して、同じストレージスロットuint256 valueindex = set._indexes [value];
if(valueIndex!= 0){// contains(set、value)// o(1)の_values配列から要素を削除するには、[set、value)//は、[swap and 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 .使用できます/**
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();
}
}