QX ERC20 Token Sains /** *Dikirim untuk verifikasi di Etherscan.io pada 2020-12-24 * /
soliditas pragma ^0.6.0;
/**
@dev pembungkus atas operasi aritmatika Soliditas dengan tambahan overflow
cek.
Operasi aritmatika dalam bungkus soliditas pada overflow. Ini bisa dengan mudah dihasilkan
dalam bug, karena programmer biasanya menganggap bahwa overflow meningkatkan
Kesalahan, yang merupakan perilaku standar dalam bahasa pemrograman tingkat tinggi.
SafeMath mengembalikan intuisi ini dengan mengembalikan transaksi saat
Operasi meluap.
Menggunakan perpustakaan ini alih -alih operasi yang tidak dicentang menghilangkan keseluruhan
Kelas bug, jadi disarankan untuk selalu menggunakannya. / pustaka safemath { / *
@Dev mengembalikan penambahan dua bilangan bulat yang tidak ditandatangani, kembali
meluap.
Mitra untuk operator + Soliditas.
Persyaratan:
kembali C; }
/**
- Solidity./**
@Dev mengembalikan pengurangan dua bilangan bulat yang tidak ditandatangani, kembali dengan pesan khusus
meluap (saat hasilnya negatif).
Mitra dengan - Solidity.
Persyaratan:
kembali C; }
/**
@Dev mengembalikan multiplikasi dua bilangan bulat yang tidak ditandatangani, kembali
meluap.
Mitra dengan operator Solidity * .
Persyaratan:
uint256 c = a * b; membutuhkan (c / a == b, "Safemath: Multiplication overflow");
kembali C; }
/**
/ Operator. Catatan: Fungsi ini menggunakan arevert opcode (yang meninggalkan gas yang tersisa tidak tersentuh) saat soliditas/**
@Dev mengembalikan divisi integer dari dua bilangan bulat yang tidak ditandatangani. Kembali dengan pesan khusus di
Divisi dengan nol. Hasilnya dibulatkan ke nol.
Mitra dengan Soliditas / Operator. Catatan: Fungsi ini menggunakan a
revert opcode (yang meninggalkan gas yang tersisa tidak tersentuh) saat soliditas
menggunakan opcode tidak valid untuk kembali (mengonsumsi semua gas yang tersisa).
Persyaratan:
kembali C; }
/**
% Solidity. Fungsi ini menggunakan revert/**
% Solidity. Fungsi ini menggunakan revert// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@dev utilitas matematika standar hilang dalam bahasa soliditas. / Library Math { / *
/**
/**
// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@Dev mencari array yang diurutkan dan mengembalikan indeks pertama yang berisi
nilai yang lebih besar atau sama dengan element . Jika tidak ada indeks seperti itu (yaitu semua
Nilai -nilai dalam array sangat kurang dari element ), panjang array adalah
dikembalikan. Kompleksitas waktu o (log n).
array diharapkan akan diurutkan dalam urutan naik, dan tidak mengandung
elemen berulang. */ function findUperbound (uint256 [] Storage array, uint256 elemen) tampilan internal return (uint256) {if (array.length == 0) {return 0; }
uint256 rendah = 0; uint256 tinggi = array.length;
while (rendah <tinggi) {uint256 mid = math.Argage (rendah, tinggi);
// 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;
}
}
// Pada titik ini low adalah batas atas eksklusif. Kami akan mengembalikan batas atas inklusif. if (rendah> 0 && array [rendah - 1] == elemen) {return rendah - 1; } else {return low; }}}
// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@Title counter
@Author Matt Condon (@shrugs)
@Dev menyediakan penghitung yang hanya bisa bertambah atau dikurangi satu. Ini dapat digunakan misalnya untuk melacak nomor
elemen dalam pemetaan, menerbitkan ID ERC721, atau menghitung ID permintaan.
Sertakan dengan using Counters for Counters.Counter;
Karena tidak mungkin untuk meluap bilangan bulat 256 bit dengan peningkatan satu, increment dapat melewati {safemath}
Periksa overflow, dengan demikian menghemat gas. Ini memang mengasumsikan penggunaan yang benar, karena _value yang mendasari tidak pernah
diakses secara langsung. */ Penghitung Perpustakaan {Menggunakan Safemath untuk UInt256;
Struct counter {// Variabel ini tidak boleh diakses secara langsung oleh pengguna perpustakaan: interaksi harus dibatasi untuk // fungsi perpustakaan. Pada soliditas v0.5.2, ini tidak dapat ditegakkan, meskipun ada proposal untuk menambah // fitur ini: lihat Ethereum/Solidity#4637 UInt256 _Value; // default: 0}
Function Current (Counter Storage Counter) Tampilan internal pengembalian (UInt256) {return counter._value; }
Function Increment (Counter Storage Counter) Internal {// Pemeriksaan overflow {SafeMath} dapat dilewati di sini, lihat komentar di counter._value teratas += 1; }
penurunan fungsi (penghitung penyimpanan penghitung) internal {counter._value = counter._value.sub (1); }}
// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/*
@Dev memberikan informasi tentang konteks eksekusi saat ini, termasuk
pengirim transaksi dan datanya. Sementara ini umumnya tersedia
melalui msg.sender dan msg.data, mereka tidak boleh diakses secara langsung
dengan cara, karena saat berhadapan dengan meta-transaksi GSN yang dikirimkan akun dan
Membayar untuk eksekusi mungkin bukan pengirim yang sebenarnya (sejauh aplikasi
prihatin).
Kontrak ini hanya diperlukan untuk kontrak menengah, seperti perpustakaan. */ Konteks Kontrak Abstrak {function _msgsender () tampilan internal pengembalian virtual (alamat dibayar) {return msg.sender; }
fungsi _msgdata () tampilan internal virtual returns (memori bytes) {this; // Silence State Mutability Warning tanpa menghasilkan bytecode - lihat Ethereum/Solidity#2691 Return msg.data; }}
// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@Dev Antarmuka standar ERC20 sebagaimana didefinisikan dalam EIP. / antarmuka ierc20 { / *
/**
account . */ Fungsi Saldo (Akun Alamat) Tampilan Eksternal Pengembalian (UInt256);/**
amount token dari akun penelepon ke recipient ./**
spenderowner melalui {transferFrom}. Ini/**
amount sebagai tunjangan spender di atas token penelepon./**
amount token dari sender ke recipient menggunakanamount kemudian dikurangkan dari penelepon/**
value dipindahkan dari satu akun ( from ) keto ).value mungkin nol. */ transfer acara (alamat diindeks dari, alamat diindeks ke, nilai UInt256);/**
spender untuk owner ditetapkan olehvalue adalah tunjangan baru. */ Persetujuan Acara (Alamat Pemilik yang Diindeks, Alamat Indeks Pemboros, Nilai UInt256); }// Lisensi Parsial: MIT
soliditas pragma ^0.6.2;
/**
@Dev koleksi fungsi yang terkait dengan jenis alamat / alamat pustaka { / *
@Dev mengembalikan true jika account adalah kontrak.
[PENTING]
====
Tidak aman untuk berasumsi bahwa alamat yang fungsi ini kembali
Salah adalah akun milik eksternal (EOA) dan bukan kontrak.
Antara lain, isContract akan mengembalikan false untuk yang berikut ini
Jenis Alamat:
==== */ Function ISContract (Akun Alamat) Tampilan internal Pengembalian (BOOL) {// Metode ini bergantung di ExtCodesize, yang mengembalikan 0 untuk kontrak dalam // konstruksi, karena kode hanya disimpan pada akhir eksekusi konstruktor.
Ukuran UInt256; // solhint-disable-next-line no-inline-assembly assembly {size: = extCodesize (akun)} ukuran pengembalian> 0; }
/**
@dev penggantian untuk transfer soliditas: mengirimkan amount wei ke
recipient , meneruskan semua gas yang tersedia dan kembali pada kesalahan.
https://eips.ethereum.org/eips/eip-1884hteip1884] meningkatkan biaya gas
dari opcodes tertentu, mungkin membuat kontrak melampaui batas gas 2300
dipaksakan dengan transfer , membuatnya tidak dapat menerima dana melalui
transfer . {SendValue} Menghapus batasan ini.
https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/htlearn More].
Penting: Karena kontrol ditransfer ke recipient , harus dirawat
Diambil untuk tidak menciptakan kerentanan reentrancy. Pertimbangkan untuk menggunakan
{Reentrancyguard} atau
https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-patternthewecks-effects-interteractions Pattern]. */ fungsi sendValue (penerima yang harus dibayar, jumlah UInt256) internal {membutuhkan (alamat (this) .salance> = jumlah, "Alamat: Saldo yang tidak memadai");
// solhint-disable-nex-line hindari-level-level-calls, hindari-call-value (keberhasilan bool,) = penerima.call {value: jumlah} (""); Membutuhkan (sukses, "Alamat: Tidak dapat mengirim nilai, penerima mungkin telah dikembalikan"); }
/**
call level rendah. Acall polos adalah pengganti yang tidak aman untuk panggilan fungsi: gunakan initarget kembali dengan alasan yang dikembalikan, itu digelembungkan oleh initarget harus menjadi kontrak.target dengan data tidak boleh kembali./**
functionCall ], tetapi denganerrorMessage sebagai alasan pengembalian mundur ketika target kembali./**
functionCall ],value Wei ke target .value .payable ./**
functionCallWithValue ], tetapierrorMessage sebagai alasan pengembalian mundur ketika target kembali.Fungsi _FunctionCallWithValue (Target Alamat, Bytes Memory Data, UInt256 Weivalue, String Memory ErrorMessage) Pengembalian Pribadi (memori byte) {membutuhkan (ISContract (target), "Alamat: Panggilan ke non-kontrak");
// 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);
}
}
}}
// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@Dev Implementasi antarmuka {IERC20}.
Implementasi ini agnostik ke cara token dibuat. Ini berarti
bahwa mekanisme pasokan harus ditambahkan dalam kontrak yang diturunkan menggunakan {_mint}.
Untuk mekanisme generik, lihat {ERC20PresetMInterPauser}.
Kiat: Untuk Tulisan Detail Lihat Panduan Kami
https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226 media bagaimana
untuk mengimplementasikan mekanisme pasokan].
Kami telah mengikuti Pedoman Openzeppelin Umum: Fungsi kembali sebagai gantinya
mengembalikan false pada kegagalan. Perilaku ini tetap konvensional
dan tidak bertentangan dengan harapan aplikasi ERC20.
Selain itu, acara {persetujuan} dipancarkan pada panggilan ke {transferFrom}.
Ini memungkinkan aplikasi untuk merekonstruksi tunjangan untuk semua akun saja
dengan mendengarkan acara tersebut. Implementasi EIP lainnya mungkin tidak memancarkan
Peristiwa ini, karena tidak diperlukan oleh spesifikasi.
Akhirnya, non-standar {DecreaseAllowance} dan {ExpilleAllowance}
Fungsi telah ditambahkan untuk mengurangi masalah-masalah terkenal di sekitar pengaturan
tunjangan. Lihat {ierc20-approve}. */ kontrak ERC20 adalah konteks, IERC20 {menggunakan Safemath untuk UInt256; menggunakan alamat untuk alamat;
Pemetaan (alamat => UInt256) Private _Balances;
pemetaan (alamat => pemetaan (alamat => uint256)) private _allowances;
uint256 private _totalsupply;
String private _name; String private _symbol; uint8 private _decimals;
/**
/**
/**
/**
decimals sama dengan 2 , keseimbangan 505 token harus5,05 ( 505 / 10 ** 2 )./**
/**
/**
recipient tidak bisa menjadi alamat nol.amount . */ Fungsi Transfer (Penerima Alamat, Jumlah UInt256) Pengembalian Override Virtual Publik (BOOL) {_Transfer (_msgsender (), penerima, jumlah); Kembali Benar; }/**
/**
spender tidak bisa menjadi alamat nol. */ fungsi menyetujui (alamat spender, uint256 jumlah) pengembalian override virtual publik (bool) {_approve (_msgsender (), spender, jumlah); Kembali Benar; }/**
sender dan recipient tidak bisa menjadi alamat nol.sender harus memiliki saldo setidaknya amount .sender setidaknyaamount . */ Fungsi TransferFrom (Pengirim Alamat, Penerima Alamat, Jumlah UInt256) Pengembalian Public Virtual Override (BOOL) {_Transfer (pengirim, penerima, jumlah); _approve (pengirim, _msgsender (), _allowances [pengirim] [_ msgsender ()]. Sub (jumlah, "ERC20: Jumlah transfer melebihi tunjangan")); Kembali Benar; }/**
spender oleh penelepon.spender tidak bisa menjadi alamat nol. */ function exilleAllowance (alamat spender, uint256 ditambahkan value) public virtual return (bool) {_approve (_msgsender (), spender, _allowances [_msgsender ()] [spender] .add (ditambahkanValue)); Kembali Benar; }/**
spender oleh penelepon.spender tidak bisa menjadi alamat nol.spender harus memiliki tunjangan untuk penelepon setidaknyasubtractedValue . */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); Kembali Benar; }/**
@Dev memindahkan amount token dari sender ke recipient .
Ini adalah fungsi internal setara dengan {transfer}, dan dapat digunakan untuk
Misalnya menerapkan biaya token otomatis, mekanisme pemotongan, dll.
Memancarkan acara {transfer}.
Persyaratan:
sender tidak bisa menjadi alamat nol.recipient tidak bisa menjadi alamat nol.sender harus memiliki saldo setidaknya amount . */ function _transfer (pengirim alamat, penerima alamat, jumlah UInt256) virtual internal {membutuhkan (pengirim! = Alamat (0), "ERC20: Transfer dari alamat nol"); membutuhkan (penerima! = alamat (0), "ERC20: Transfer ke alamat nol");_BeforeTokentRansfer (pengirim, penerima, jumlah);
_BALESA [pengirim] = _BALANCES [pengirim] .sub (jumlah, "ERC20: Jumlah transfer melebihi saldo"); _BALESA [penerima] = _BALANCES [penerima] .add (jumlah); memancarkan transfer (pengirim, penerima, jumlah); }
/** @Dev membuat amount token dan menugaskannya ke account , meningkat
total pasokan.
Memancarkan acara {transfer} dengan from set ke alamat nol.
Persyaratan
to bisa menjadi alamat nol. */ function _mint (Akun alamat, jumlah UInt256) virtual internal {membutuhkan (akun! = alamat (0), "ERC20: mint ke alamat nol");_BeforeTokentRansfer (alamat (0), akun, jumlah);
_totalsupply = _totalsupply.add (jumlah); _BALESA [Akun] = _BALANCES [akun] .add (jumlah); memancarkan transfer (alamat (0), akun, jumlah); }
/**
@Dev menghancurkan amount token dari account , mengurangi
Total Pasokan.
Memancarkan acara {transfer} dengan to mengatur ke alamat nol.
Persyaratan
account tidak bisa menjadi alamat nol.account harus memiliki setidaknya amount token. */ function _burn (Akun alamat, jumlah UInt256) virtual internal {membutuhkan (akun! = Alamat (0), "ERC20: Bakar dari alamat nol");_BeforeTokentRansfer (akun, alamat (0), jumlah);
_Balances [akun] = _BALIANS [Akun] .sub (jumlah, "ERC20: Jumlah terbakar melebihi saldo"); _totalsupply = _totalsupply.sub (jumlah); memancarkan transfer (akun, alamat (0), jumlah); }
/**
@Dev menetapkan amount sebagai tunjangan spender atas token owner .
Fungsi internal ini setara untuk approve , dan dapat digunakan
misalnya set tunjangan otomatis untuk subsistem tertentu, dll.
Memancarkan acara {persetujuan}.
Persyaratan:
owner tidak bisa menjadi alamat nol.spender tidak bisa menjadi alamat nol. */ function _approve (pemilik alamat, pemboros alamat, jumlah UInt256) virtual internal {membutuhkan (pemilik! = alamat (0), "ERC20: menyetujui dari alamat nol"); membutuhkan (spender! = alamat (0), "ERC20: menyetujui ke alamat nol");_allowances [pemilik] [spender] = jumlah; memancarkan persetujuan (pemilik, pemboros, jumlah); }
/**
/**
from dan to keduanya bukan nol, amount dari token fromto .from adalah nol, amount token akan to .to nol, amount token from akan dibakar.from dan to tidak pernah nol.// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@dev Kontrak ini memperluas token ERC20 dengan mekanisme snapshot. Saat snapshot dibuat, saldo dan
Total pasokan pada saat itu dicatat untuk akses selanjutnya.
Ini dapat digunakan untuk membuat mekanisme dengan aman berdasarkan saldo token seperti dividen tanpa kepercayaan atau pemungutan suara tertimbang.
Dalam implementasi naif, dimungkinkan untuk melakukan serangan "pengeluaran ganda" dengan menggunakan kembali keseimbangan yang sama dari yang berbeda
akun. Dengan menggunakan snapshot untuk menghitung dividen atau kekuatan suara, serangan itu tidak lagi berlaku. Itu juga bisa
Digunakan untuk membuat mekanisme forking ERC20 yang efisien.
Snapshot dibuat oleh fungsi internal {_snapshot}, yang akan memancarkan acara {snapshot} dan mengembalikan a
ID snapshot. Untuk mendapatkan persediaan total pada saat snapshot, panggil fungsi {totalsuppyat} dengan snapshot
pengenal. Untuk mendapatkan saldo akun pada saat snapshot, hubungi fungsi {balanceOfAT} dengan ID snapshot
dan alamat akun.
==== Biaya gas
Snapshot efisien. Penciptaan snapshot adalah O (1) . Pengambilan saldo atau persediaan total dari snapshot adalah _o (log
n) _ Dalam jumlah snapshot yang telah dibuat, meskipun n untuk akun tertentu umumnya akan banyak
Lebih kecil karena saldo identik dalam snapshot berikutnya disimpan sebagai entri tunggal.
Ada overhead konstan untuk transfer ERC20 normal karena pembukuan snapshot tambahan. Overhead ini
Hanya signifikan untuk transfer pertama yang segera mengikuti snapshot untuk akun tertentu. Setelah
Transfer akan memiliki biaya normal sampai snapshot berikutnya, dan seterusnya. */KONTRAK ABSTRAK ERC20SNAPSHOT adalah ERC20 {// terinspirasi oleh minimetoken Jordi Baylina untuk merekam saldo sejarah: // https://github.com/giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9d9d90konskon.minkonskon.minifa510b068b9d950
menggunakan Safemath untuk UInt256; menggunakan array untuk UInt256 []; menggunakan penghitung untuk counter.counter;
// Nilai Snapshotted memiliki array ID dan nilai yang sesuai dengan ID itu. Ini bisa berupa array dari // Snapshot Struct, tetapi itu akan menghalangi penggunaan fungsi yang bekerja pada array. Snapshots struct {uint256 [] id; nilai uint256 []; }
pemetaan (alamat => snapshot) private _AccountBalancesNapShots; Snapshots Private _totalsupplySnapshots;
// ID snapshot meningkat secara monoton, dengan nilai pertama adalah 1. ID 0 tidak valid. Counters.counter private _currentsnapshotid;
/**
id dibuat. */ Event Snapshot (ID UInt256);/**
@Dev membuat snapshot baru dan mengembalikan ID snapshot -nya.
Memancarkan peristiwa {snapshot} yang berisi ID yang sama.
{_snapshot} adalah internal dan Anda harus memutuskan bagaimana mengeksposnya secara eksternal. Penggunaannya mungkin terbatas pada a
Set akun, misalnya menggunakan {accessControl}, atau mungkin terbuka untuk umum.
[PERINGATAN]
====
Sementara cara terbuka untuk memanggil {_snapshot} diperlukan untuk mekanisme minimisasi kepercayaan tertentu seperti forking,
Anda harus mempertimbangkan bahwa itu berpotensi digunakan oleh penyerang dengan dua cara.
Pertama, dapat digunakan untuk meningkatkan biaya pengambilan nilai dari snapshot, meskipun akan tumbuh
Dengan demikian secara logaritmik membuat serangan ini tidak efektif dalam jangka panjang. Kedua, dapat digunakan untuk menargetkan
akun spesifik dan meningkatkan biaya transfer ERC20 untuk mereka, dengan cara yang ditentukan dalam biaya gas
bagian di atas.
Kami belum mengukur angka aktual; Jika ini adalah sesuatu yang Anda minati, hubungi kami.
==== */ function _snapshot () Pengembalian virtual internal (uint256) {_currentsnapshotid.increment ();
uint256 currentId = _currentsnapshotid.current (); memancarkan snapshot (currentId); mengembalikan CurrentID; }
/**
@Dev mengambil saldo account pada saat snapshotId dibuat. */ Fungsi BalanceOfAT (Akun Alamat, UInt256 Snapshotid) Tampilan Publik Pengembalian (UInt256) {(Bool Snapshotted, nilai UInt256) = _Valueat (SnapshotId, _AccountBalangesNapShots [akun]);
Return Snapshotted? Nilai: Saldo dari (akun); }
/**
@Dev mengambil total pasokan pada saat snapshotId dibuat. */ fungsi totalsuppmate (uint256 snapshotid) tampilan publik pengembalian (uint256) {(bool snapshotted, nilai uint256) = _valueat (snapshotid, _totalsupplysnapshots);
Return Snapshotted? nilai: totalsupply (); }
// Perbarui saldo dan/atau snapshot persediaan total sebelum nilai dimodifikasi. Ini diimplementasikan // dalam kait _beforeTokentransfer, yang dieksekusi untuk operasi _mint, _burn, dan _transfer. fungsi _beforetokentransfer (alamat dari, alamat ke, jumlah UInt256) override virtual internal {super._beforeTokentRansfer (dari, ke, jumlah);
if (from == address (0)) {// mint _upDateAccountSnapshot (to); _UpDateTotalSupplySnapshot (); } lain jika (ke == alamat (0)) {// bakar _upDateAccountSnapshot (dari); _UpDateTotalSupplySnapshot (); } else {// transfer _upDateAccountSnapshot (dari); _upDateAccountsNapshot (to); }}
Fungsi _Valueat (UInt256 Snapshotid, Snapshots Storage Snapshots) Tampilan Pribadi (Bool, UInt256) {membutuhkan (Snapshotid> 0, "ERC20SNAPSHOT: ID adalah 0"); // solhint-discable-next-line max-line-length membutuhkan (snapshotid <= _currentsnapshotid.current (), "ERC20SNAPShot: ID tidak ada");
// 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]);
}
}
fungsi _upDateAccountSnapshot (Akun alamat) private {_upDatesNapShot (_AccountBalangesNapShots [akun], saldo (akun)); }
Function _upDateToTalSupplySnapshot () private {_upDatesNapshot (_totalsupplySnapshots, totalsupply ()); }
fungsi _updatesNapshot (snapshots penyimpanan snapshot, uint256 currentValue) private {uint256 currentId = _currentsnapshotid.current (); if (_LastSnapShotId (snapshots.ids) <currentId) {snapshots.ids.push (currentId); snapshots.values.push (CurrentValue); }}
fungsi _LastSnapShotId (UInt256 [] ID penyimpanan) View Private Returns (UInt256) {if (ids.length == 0) {return 0; } else {return ids [ids.length - 1]; }}}
// Lisensi Parsial: MIT
soliditas pragma ^0.6.0;
/**
@Dev Library untuk mengelola
https://en.wikipedia.org/wiki/set_(abstract_data_type)anjang] dari primitif
tipe.
Set memiliki properti berikut:
(O (1)).
contoh kontrak {
// Add the library methods
using EnumerableSet for EnumerableSet.AddressSet;
// Declare a set state variable
EnumerableSet.AddressSet private mySet;
}
Pada v3.0.0, hanya set address Jenis ( AddressSet ) dan uint256
( UintSet ) didukung. */ Library EnumerableSet {// Untuk mengimplementasikan pustaka ini untuk beberapa jenis dengan kode sesedikit // pengulangan mungkin, kami menulisnya dalam hal jenis set generik dengan // nilai bytes32. // Implementasi yang ditetapkan menggunakan fungsi pribadi, dan implementasi yang menghadap ke pengguna // (seperti Alamat) hanyalah pembungkus di sekitar // set yang mendasarinya. // Ini berarti bahwa kita hanya dapat membuat enumerableSets baru untuk jenis yang sesuai // di bytes32.
Struktur set {// penyimpanan nilai 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 menghapus nilai dari satu set. O (1).
Mengembalikan benar jika nilainya dihapus dari set, yaitu jika itu
hadiah. */ function _remove (set penyimpanan set, value bytes32) pengembalian pribadi (bool) {// kita membaca dan menyimpan indeks nilai untuk mencegah beberapa bacaan dari slot penyimpanan yang sama uint256 valueIndex = set._indexes [nilai];
if (valueIndex! = 0) {// setara dengan berisi (set, value) // Untuk menghapus elemen dari array _values di O (1), kami menukar elemen untuk menghapus dengan yang terakhir di // array, dan kemudian menghapus elemen terakhir (kadang -kadang disebut 'swap dan pop'). // Ini memodifikasi urutan array, sebagaimana dicatat dalam {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 posisi di set. O (1).index must be strictly less than {length}. */ 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
peran. 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 . Dapat digunakan/**
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}
peristiwa.
Persyaratan:
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.
Persyaratan:
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}
peristiwa.
Persyaratan:
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();
}
}