QX ERC20科學代幣 /** *在2020-12-24上提交驗證以進行驗證 * /
PRAGMA固體 ^0.6.0;
/**
@Dev包裝器對Solidity的算術操作以及增加的溢出
檢查。
在溢出上固體包裝中的算術操作。這很容易導致
在錯誤中,因為程序員通常假定溢出會增加
錯誤,這是高級編程語言中的標準行為。
SafeMath通過在
操作溢出。
使用此庫代替未檢查的操作消除了整個
類別類別,因此建議始終使用它。 / Library Safemath { / *
@Dev返回兩個未簽名的整數,恢復
溢出。
與Solidity的+運算符相對。
要求:
返回c; }
/**
-員相對。/**
@Dev返回兩個未簽名整數的減法,並在自定義消息上恢復
溢出(結果為負)。
與堅固的-員相對。
要求:
返回c; }
/**
@Dev返回兩個未簽名整數的乘法,恢復
溢出。
與Solidity的*操作員相對。
要求:
uint256 c = a * b;需要(c / a == b,“ safemath:乘法溢出”);
返回c; }
/**
/操作員相對。注意:此功能使用revert OpCode(剩餘的氣體未觸及),而堅固/**
@Dev返回兩個未簽名整數的整數部門。帶有自定義消息的恢復
零。結果朝零舍入。
與固體/操作員相對。注意:此功能使用
revert OpCode(剩餘的氣體未觸及),而堅固
使用無效的操作碼還原(消耗所有剩餘氣體)。
要求:
返回c; }
/**
%操作員相對。此功能使用一個revert/**
%操作員相對。此功能使用一個revert//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
@DEV標準數學實用程序中缺少堅固性語言。 /庫數學{ / *
/**
/**
//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
@Dev搜索一個排序的array ,並返回包含的第一個索引
一個更大或等於element的值。如果沒有這樣的索引(即
數組中的值嚴格小於element ),數組長度為
返回。時間複雜性o(log n)。
預計array將按升序排序,並且不包含
重複元素。 */ function findupperbound(uint256 []存儲陣列,uint256元素)內部視圖返回(uint256){if(array.length == 0){return 0; }
UINT256低= 0; uint256高= array.length;
而(低<high){uint256 mid = math.averager(低,高);
// 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] ==元素){返回低-1; } else {return low; }}}}
//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
@Title計數器
@author Matt Condon(@shrugs)
@DEV提供只能由一個可以增加或減少的計數器。這可以用來跟踪數字
映射中的元素,發行ERC721 ID或計數請求ID。
包括using Counters for Counters.Counter;
由於無法以一個增量為單位的256位整數溢出,因此increment可以跳過{safemath}
溢出檢查,從而節省了氣體。這確實假定正確的用法,因為基礎_value永遠不會
直接訪問。 */庫計數器{使用safemath for uint256;
struct Counter {//該變量絕不應由庫的用戶直接訪問:交互必須僅限於// //庫的函數。從固體v0.5.2開始,儘管有一個提議添加此功能,但不能強制執行此功能:請參閱以太坊/固體#4637 uint256 _value; //默認值:0}
功能電流(計數器存儲計數器)內部視圖返回(UINT256){return Counter._value; }
函數增量(計數器存儲計數器)內部{// {safemath}溢出檢查可以在此處跳過,請參閱頂部計數器的註釋。 _value += 1; }
函數降低(計數器存儲計數器)內部{counter._value = counter._value.sub(1); }}}
//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/*
@DEV提供有關當前執行上下文的信息,包括
交易的發件人及其數據。雖然這些通常可用
通過msg.sender和msg.data,不應在這樣的直接中訪問它們
方式,因為在處理GSN元轉移時,帳戶發送和
支付執行可能不是實際發件人(就申請而言
關心)。
該合同僅是中間,類似圖書館的合同所必需的。 */抽象合同上下文{function _msgsender()內部視圖虛擬返回(應付付款){return msg.sender; }
函數_msgdata()內部視圖虛擬返回(bytes memory){this; //沉默狀態可突變性警告而無需產生字節碼 - 請參見以太坊/固體#2691返回msg.data; }}}
//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
EIP中定義的ERC20標準的@DEV接口。 /接口IERC20 { / *
/**
account擁有的令牌金額。 */ function Balanceof(地址帳戶)外部視圖返回(UINT256);/**
amount令牌從呼叫者的帳戶移至recipient 。/**
spender幣數量owner支出。這是/**
amount設置為在呼叫者令牌上的spender津貼。/**
amount令牌從sender移動到recipientamount/**
value代幣從一個帳戶從一個帳戶轉移fromto )。value可能為零。 */事件傳輸(地址索引,從地址索引為uint256值);/**
owner的spender的津貼由value是新的津貼。 */事件批准(地址索引所有者,地址索引索引,UINT256值); }//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.2;
/**
@DEV集合與地址類型/庫地址相關的功能{ / *
@Dev如果account是合同,則返回true。
[重要的]
====
假設此功能返回的地址是不安全的
false是一個外部賬戶(EOA),而不是合同。
除其他外, isContract將返回false以下
地址類型:
==== */ function isontract(地址帳戶)內部視圖返回(bool){//此方法依賴於extCodesize,該方法返回//構造中的合同為0,因為該代碼僅存儲在//構造器執行的末尾。
UINT256尺寸; // solhint-disable-next-line noinline-eSembly彙編{size:= extCodesize(account)}返回size> 0; }
/**
@Dev替換固體transfer :將amount發送給
recipient ,轉發所有可用的氣體並恢復錯誤。
https://eips.ethereum.org/eips/eip-1884 [eip1884]增加了氣體成本
在某些OPCODES中,可能會簽訂合同超過2300氣體限制
通過transfer施加,使他們無法通過
transfer 。 {sendValue}消除了此限制。
https://diligence.consensys.net/posts/2019/09/stop-using-solisitys-transfer-now/ [leym More]。
重要的是:因為控制被轉移到recipient ,所以護理必須是
不創造重新進入的漏洞。考慮使用
{retrancyguard}或
https://solity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-ecks-effects-interactions-pattern [checks-ecks-effects-effects-interactions模式]。 */ function sendValue(應付收款人,UINT256金額)內部{require(地址(this).balance> =金額,“地址:不足餘額”);
// solhint-disable-next-line避免避開低級別的呼叫,避免呼叫值(bool success)= conterient.call.call {value:nose}(量}(“”);要求(成功,“地址:無法發送價值,收件人可能已經恢復”); }
/**
call執行堅固的功能調用。一個call是功能呼叫的不安全替代:使用此target恢復為恢復原因,則它會被此彈起target必須是合同。data調用target不得恢復。/**
functionCall ],但使用target恢復時, errorMessage誤差為後備原因。/**
functionCall ],value轉移到target 。value的ETH餘額。payable 。/**
functionCallWithValue ]相同,但是target恢復時,以errorMessage作為後備原因恢復了原因。函數_functionCallWithValue(地址目標,BYTES內存數據,UINT256 Weivalue,String Memory Errormessage)私人返回(bytes memory){require(requart(isContract(isContract(isContract)),“地址:call to nontartract”);
// 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);
}
}
}}}
//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
{IERC20}接口的@DEV實現。
這種實現對代幣的創建方式不可知。這意味著
必須使用{_mint}中的派生合同中添加供應機制。
有關通用機制,請參見{erc20presetminterpauser}。
提示:有關詳細的寫作,請參閱我們的指南
https://forum.zeppelin.solutions/t/how-to-to-implement-erc20-supply-mechanisms/226 [how
實施供應機制]。
我們遵循了一般OpenZeppelin指南:功能恢復
失敗時返回false 。儘管如此,這種行為仍然是常規的
並且不會與ERC20應用程序的期望發生衝突。
此外,在{Transferfrom}的呼叫上發出了{批准}事件。
這允許應用程序重建所有帳戶的津貼
通過收聽所述事件。 EIP的其他實現可能不會發出
這些事件,因為規範不是必需的。
最後,非標準{depaneAseAllowance}和{highteAllowance}
已經添加了功能來減輕圍繞設置的知名問題
津貼。請參閱{ierc20-approve}。 */ Contract ERC20是上下文,IERC20 {使用SafeMath for Uint256;使用地址;
映射(地址=> uint256)私人_Balances;
映射(地址=>映射(address => uint256))私人_Allowances;
uint256私人_totalsupply;
字符串私有_name;字符串私有_symbol; uint8私有_decimals;
/**
/**
/**
/**
decimals等於2 ,則餘額為505代幣5,05 ( 505 / 10 ** 2 )。/**
/**
/**
recipient不能是零地址。amount 。 */函數傳輸(地址收件人,UINT256金額)公共虛擬覆蓋返回(bool){_transfer(_msgsender(),收件人,金額);返回true; }/**
/**
spender不能是零地址。 */函數批准(地址spender,uint256金額)公共虛擬替代返回(bool){_approve(_msgsender(),spender,金額);返回true; }/**
sender和recipient不能是零地址。sender必須具有至少amount 。sender的令牌津貼amount 。 */函數轉移From(地址發送者,地址收件人,UINT256金額)公共虛擬覆蓋返回(bool){_transfer(發送者,收件人,金額); _approve(sender,_msgsender(),_ allowances [sender] [_ msgsender()]。子(金額,“ erc20:轉移金額超過津貼”));返回true; }/**
spender的津貼。spender不能是零地址。 */函數highteAllowance(地址spender,uint256 addValue)public Virtual返回(bool){_approve(_MSGSENDER(),spender,_allowances [_MSGSENDER(_MSGSENDER()]返回true; }/**
spender的津貼。spender不能是零地址。spender必須至少有呼叫者的津貼subtractedValue 。 */函數降低(地址spender,uint256 suptractedValue)公共虛擬返回(bool){_approve(_MSGSENDER(),spender,_allowaness,_ spender,_msgsender(_msgsender()[_msgsender()]返回true; }/**
@Dev將令牌amount從sender移至recipient 。
這是內部功能等同於{transfer},可以使用
例如,實施自動令牌費用,削減機制等。
發出{傳輸}事件。
要求:
sender不能是零地址。recipient不能是零地址。sender必須具有至少amount 。 */ function _transfer(地址發送者,地址收件人,UINT256金額)內部虛擬{require(sender!=地址(0),“ erc20:從零地址轉移”); require(收件人!=地址(0),“ erc20:轉移到零地址”);_BEFORETOKENTRANSFER(發送者,收件人,金額);
_ balances [sender] = _ balances [sender] .sub(金額,“ erc20:轉移金額超過餘額”); _ balances [收件人] = _ balances [收件人] .add(量);發射轉移(發件人,收件人,金額); }
/** @dev創建amount令牌並將其分配給account ,增加
總供應。
發出一個from設置到零地址的事件。
要求
to是零地址。 */ function _mint(地址帳戶,uint256金額)內部虛擬{require(account!= address(0),“ erc20:mint至零地址”);_BEFORETOKENTRANSFER(地址(0),帳戶,金額);
_totalsupply = _totalsupply.add(量); _ balances [account] = _ balances [account] .add(量);發射轉移(地址(0),帳戶,金額); }
/**
@Dev從account中銷毀amount令牌,減少
總供應。
發出{Transfer}事件, to為零地址。
要求
account不能是零地址。account必須至少具有amount幣。 */ function _burn(地址帳戶,UINT256金額)內部虛擬{require(account!=地址(0),“ erc20:從零地址刻錄”);_BEFORETOKENTRANSFER(帳戶,地址(0),金額);
_balances [account] = _ balances [account] .sub(金額,“ erc20:燒傷金額超過餘額”); _totalsupply = _totalsupply.sub(量);發射轉移(帳戶,地址(0),金額); }
/**
@Dev將amount設置為對owner的代幣的spender津貼。
此內部功能等同於approve ,可以用來
例如,設置某些子系統的自動津貼,等等。
發出{批准}事件。
要求:
owner不能是零地址。spender不能是零地址。 */ function _approve(地址所有者,地址spender,uint256金額)內部虛擬{require(lands!=地址(0),“ erc20:從零地址批准”); require(spender!=地址(0),“ erc20:批准零地址”);_Allowances [所有者] [Spender] =金額;發射批准(所有者,支出者,金額); }
/**
/**
from from amount toto 。from零零時,將to amount令牌。to ,將燃燒from S標記的amount 。from和to永遠都不是零。//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
@Dev此合同使用快照機制擴展了ERC20令牌。創建快照時,平衡和
記錄當時的總供應,以供以後訪問。
這可以用來根據令牌餘額(例如無信任的股息或加權投票)安全創建機制。
在天真的實現中,可以通過重複不同的平衡來執行“雙重支出”攻擊
帳戶。通過使用快照來計算股息或投票權,這些攻擊不再適用。也可以
用於創建有效的ERC20分叉機制。
快照是由內部{_snapshot}函數創建的,它將發射{snapshot}事件並返回
快照ID。要在快照時獲取總電源,請使用快照調用函數{
ID。要在快照時獲得帳戶的餘額,請使用快照ID調用{Balanceofat}函數
和帳戶地址。
====氣體成本
快照是有效的。快照創建是O(1) 。從快照中檢索餘額或總供水為_o(log
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 []的數組;使用計數器進行計數器。
//快照值具有ID數組和與該ID相對應的值。這些可能是A //快照結構的數組,但這會阻礙在數組上起作用的功能。 struct快照{uint256 [] ids; uint256 []值; }
映射(地址=>快照)私有_accountbalancesnapshots;快照私有_totalsupplysnapshots;
//快照ID單調增加,第一個值為1。 ID為0是無效的。 counter.counter private _currentsNapShotid;
/**
id標識的快照時,{_snapshot}發射的@Dev。 */事件快照(UINT256 ID);/**
@Dev創建了一個新的快照並返回其快照ID。
發出包含相同ID的事件{快照}事件。
{_snapshot}是internal ,您必須決定如何外部暴露它。它的使用可能僅限於
一組帳戶,例如使用{AccessControl},或者可以向公眾開放。
[警告]
====
雖然需要一種開放的調用{_snapshot}的方式,而某些信任最小化機制(例如分叉)需要
您必須認為攻擊者可以通過兩種方式使用它。
首先,它可以用來增加快照中值的收回成本,儘管它將增長
從而使對數從長遠來看使這種攻擊無效。其次,它可以用於靶向
特定帳戶並增加了ERC20轉移的成本,以汽油成本指定的方式
上面的部分。
我們尚未測量實際數字;如果這是您感興趣的事情,請與我們聯繫。
==== */ function _snapShot()內部虛擬返回(uint256){_currentsnapshotid.increment();
uint256 currentId = _currentsNapShotid.current();發射快照(CurrentId);返回CurrentID; }
/**
@Dev檢索snapshotId時的account餘額。 */ function BalanceOfat(地址帳戶,UINT256快照)公共視圖返回(UINT256){(bool snapshotted,uint256 value)= _VALUEAT(snapshotid,_accountbalancesnapsnapshots [account]);
返回快照?價值:BalanceOf(帳戶); }
/**
@Dev檢索創建snapshotId時的總電源。 */ function tostalsupplyat(uint256 snapshotid)public view返回(uint256){(bool snapshotted,uint256 value)= _valueat(snapshotid,_totalSupplysnapsnapshots);
返回快照?價值:tostalsupply(); }
//在修改值之前,更新余額和/或總電源快照。這是在_beforetokentransfer Hook中實現的,該掛鉤是為_mint,_burn和_transfer操作執行的。函數_beforetOkentRansfer(地址,地址到,UINT256量)內部虛擬覆蓋{super._beforetokentransfer(從,到量);
if(來自==地址(0)){// mint _updateaccountsnapshot(to); _updateTotalSupplySnapShot(); } else if(to ==地址(0)){// burn _updateaccountsnapshot(from); _updateTotalSupplySnapShot(); } else {//傳輸_updateaccountsnapshot(來自); _updateaccountsnapshot(to); }}}
函數_valueat(uint256快照,快照存儲快照)私人視圖返回(bool,uint256){require(snapshotid> 0,“ erc20snapshot:id is id is id is id is d is 0”); // solhint-disable-next-line max-line長度require(snapshotid <= _currentsnapshotid.current(),“ erc20snapshot:nonexistent 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]);
}
}
函數_updateaccountsnapshot(地址帳戶)private {_updatesNapShot(_accountbalancesnapshots [account],ballackof(account)); }
函數_updateTotalSupplySnapShot()private {_updatesNapShot(_totalsupplysnapshots,ptalsupply()); }
函數_updatesNapShot(快照存儲快照,uint256 CurrentValue)private {uint256 CurrentId = _CurrentsNapShotId.current(); if(_lastSnapShotId(snapshots.ids)<currentid){snapshots.ids.push(currentId); snapshots.values.push(CurrentValue); }}}
函數_lastSnapShotID(uint256 []存儲IDS)私有視圖返回(uint256){if(ids.length == 0){返回0; } else {返回IDS [ids.length -1]; }}}}
//部分許可證:麻省理工學院
PRAGMA固體 ^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值的通用集類型。 // SET實現使用私有功能,而面向用戶//實現(例如地址集)只是圍繞//基礎設置的包裝器。 //這意味著我們只能為適合bytes32中的類型創建新的Enumerableset。
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值)私人返回(bool){//我們讀取和存儲值的索引,以防止從同一存儲插槽uint256 uint256 valueindex = set._indexes [value];
if(valueIndex!= 0){//等效於包含(set,value)//要從o(1)中的_values數組刪除元素,我們將元素交換以用//陣列中的最後一個元素刪除,然後刪除最後一個元素(有時稱為“ 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(設置存儲集,UINT256索引)私有視圖返回(bytes32){requike(set._values.length> index,“ enumerableset:in yumerableset:in bounds of Bounds”);返回set._values [index]; }//地址集
struct addressset {set _inner; }
/**
/**
/**
/**
/**
index中存儲的值。 o(1)。index必須嚴格小於{長度}。 */ at(addressset存儲集,uint256索引)內部視圖返回(地址){返回地址(uint256(_at(set._inner,index)))); }// uintset
struct uintset {set _inner; }
/**
/**
/**
/**
/**
index中存儲的值。 o(1)。index必須嚴格小於{長度}。 */函數在(Uintset存儲集,UINT256索引)內部視圖返回(UINT256){return uint256(_at(set._inner,index)); }}}//部分許可證:麻省理工學院
PRAGMA固體 ^0.6.0;
/**
@DEV合同模塊,允許兒童實施基於角色的訪問
控制機制。
角色由其bytes32標識符提及。這些應該暴露
在外部API中,是唯一的。實現這一目標的最好方法是
使用public constant哈希摘要:
bytes32公共常數my_role = keccak256(“ my_role”);
角色可用於表示一組權限。限制訪問
函數調用,使用{hasrole}:
函數foo()public {
require(hasRole(MY_ROLE, msg.sender));
...
}
可以通過{grantrole}動態授予和撤銷角色,並且
{revokerole}函數。每個角色都具有關聯的管理角色,只有
具有角色的管理角色的帳戶可以調用{grantrole}和{revokerole}。
默認情況下,所有角色的管理員角色均為DEFAULT_ADMIN_ROLE ,這意味著
只有擔任此角色的說明才能授予或撤銷其他
角色。可以通過使用更複雜的角色關係
{_setroleadmin}。
警告: DEFAULT_ADMIN_ROLE也是其自己的管理員:它有權
授予並撤銷這一角色。應採取額外的預防措施以確保
已授予它的帳戶。 */抽象合同AccessControl是上下文{使用Enumerableset for Enumerableset.addressset;使用地址;
struct roledata {enumerableset.addressset成員; bytes32 adminrole; }
映射(bytes32 => roledata)私有_roles;
bytes32公共常數default_admin_role = 0x00;
/**
newAdminRole作為role的管理角色時,替換了previousAdminRoleDEFAULT_ADMIN_ROLE是所有角色的起始管理員,儘管/**
account role時發出。sender是發起合同電話的帳戶,管理員角色/**
account被吊銷role時,@Dev發出。sender是發起合同電話的帳戶:revokeRole ,則是管理員角色承載者renounceRole ,則是角色承載者(IE account ) */事件rolerevoked(bytes32索引角色,地址索引帳戶,地址索引索引發送者);/**
true如果account已獲得role 。 */函數HASROLE(BYTES32角色,地址帳戶)public View Reports(bool){return _roles [real] .members.contains(account); }/**
role的帳戶數量。可以使用/**
role的帳戶之一。 index必須是/**
role的管理角色。請參閱{grantrole}和/**
@Dev account role 。
如果account尚未授予role ,則會發出{colemgranted}
事件。
要求:
role的角色。 */函數grantrole(bytes32角色,地址帳戶)public virtual {require(hasrole(_roles [cool] .adminrole,_msgsender()),“ accessControl:sender:sender必須是admin to grant to Grant”);_grantrole(角色,帳戶); }
/**
@DEV從account中撤銷role 。
如果account被授予role ,則會發出{Rolerevoked}事件。
要求:
role的角色。 */函數revokerole(bytes32角色,地址帳戶)public virtual {require(hasrole(_roles [cole] .adminrole,_msgsender()),“ accessControl:sender:sender必須是admin to dismand devoke'');_revokerole(角色,帳戶); }
/**
@DEV從呼叫帳戶中撤銷role 。
角色通常通過{grantrole}和{revokerole}進行管理:此函數的
目的是為帳戶提供失去特權的機制
如果它們被妥協(例如,當信任的設備放錯了位置時)。
如果召集了呼叫帳戶的role ,則會發出{rolerevoked}
事件。
要求:
account 。 */函數renouncerole(bytes32角色,地址帳戶)public virtual {require(account == _msgsender(),“ accessControl:只能放棄自我的角色”);_revokerole(角色,帳戶); }
/**
account role 。account尚未授予role ,則會發出{colemgranted}/**
adminRole設置為role的管理角色。函數_grantrole(bytes32角色,地址帳戶)private {if(_Roles [cole] .members.add(account)){emit colemgranted(cole,account,account,_msgsender()); }}}
函數_revokerole(bytes32角色,地址帳戶)private {if(_Roles [real] .members.remove(account)){emit rolerevoked(cole,account,account,_msgsender(_msgsender()); }}}}
巴格馬堅固0.6.8;
合同QxToken是上下文,AccessControl,ERC20SnapShot {Bytes32公共常數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();
}
}