SIP-77: Perbaikan bug StakingRewards dan stake() yang dapat dijeda

studiobet78 slot

anggur slot

ini77 slot

ugdewa slot

Ringkasan Singkat

stake() perlu dapat dijeda untuk insentif yang telah selesai dan dua perbaikan bug.

Abstrak

Peningkatan meliputi:

  • Mewarisi kontrak Pausable dan menambahkan pengubah notPaused ke stake() untuk mencegah staking ke pool yang sudah tidak digunakan.
  • Memperbaiki potensi bug overflow pada fungsi notifikasi reward.
  • Perbaikan pada setRewardsDuration untuk memungkinkan rewardsDuration diperbarui setelah pengaturan awal.

Motivasi

Menjeda stake saat reward selesai

Ketika kampanye StakingRewards telah selesai, kontrak perlu mencegah siapa pun melakukan staking. Staker tidak akan mendapatkan reward dan dapat menyebabkan masalah pemblokiran dengan inverse synthetic assets yang perlu dibersihkan agar bisa diluncurkan kembali. Menambahkan Pausable dan pengubah notPaused ke stake() akan memungkinkan admin mengatur paused menjadi true untuk mencegah staking. SelfDestructible belum diimplementasikan dan mengingat jumlah nilai dalam kontrak ini, sebaiknya tidak diimplementasikan.

Perbaikan potensi bug overflow

Ringkasan

Terdapat overflow perkalian yang dapat terjadi di dalam fungsi rewardPerToken, pada baris tertentu:

lastTimeRewardApplicable().sub(lastUpdateTime).mul(rewardRate).mul(1e18).div(_totalSupply)

Overflow terjadi setiap kali rewardRate >= 2^256 / (10^18 * (lastTimeRewardApplicable() - lastUpdateTime)).

Ini dapat terjadi ketika pengubah updateReward dipanggil, yang akan menyebabkan fungsi-fungsi berikut gagal (revert):

  • earned
  • stake
  • withdraw
  • getReward
  • exit
  • notifyRewardAmount

Tingkat reward diatur di dalam notifyRewardAmount, jika nilai yang terlalu besar diberikan ke fungsi tersebut. Perlu dicatat bahwa notifyRewardAmount sendiri terpengaruh oleh masalah ini, yang berarti jika reward yang diberikan salah, maka masalah tidak dapat dipulihkan.

Solusi

Transaksi notifyRewardAmount harus dibatalkan (revert) jika nilai yang diberikan lebih besar dari 2^256 / 10^18. Sebagai mekanisme keamanan tambahan, nilai ini akan diharuskan tidak lebih besar dari sisa saldo token reward dalam kontrak. Ini akan mencegah overflow dan juga memberikan pemeriksaan tambahan bahwa tingkat reward diatur ke nilai dalam rentang yang sesuai (misalnya, tidak ada angka nol tambahan atau hilang).

Detail

Secara spesifik, masalah ini terjadi ketika rewardRate terlalu tinggi; diatur di dalam fungsi notifyRewardAmount pada baris tertentu:

rewardRate = floor(reward / rewardsDuration) = (reward - k) / rewardsDuration

untuk beberapa 0 <= k < rewardsDuration.

Agar bug terjadi, kita memerlukan:

(reward - k) / rewardsDuration >= 2^256 / (10^18 * (lastTimeRewardApplicable - lastUpdateTime))
reward >= rewardsDuration * 2^256 / (10^18 * (lastTimeRewardApplicable - lastUpdateTime)) + k

Oleh karena itu, kita dapat memastikan bug tidak terjadi jika kita memaksa:

reward < rewardsDuration * 2^256 / (10^18 * (lastTimeRewardApplicable - lastUpdateTime))

Jadi kita harus membatasi reward agar lebih kecil dari nilai minimum RHS.

Nilai terkecil yang mungkin dari lastUpdateTime adalah timestamp blok ketika notifyRewardAmount terakhir dipanggil. Nilai terbesar yang mungkin dari lastTimeRewardApplicable adalah periodFinish, dan periodFinish = notificationBlockamp + rewardsDuration (baris tertentu). Menggabungkan ini kita memiliki:

(lastTimeRewardApplicable - lastUpdateTime) <= rewardsDuration

Ergo, kita memerlukan:

reward < rewardsDuration * 2^256 / (10^18 * rewardsDuration) = 2^256 / 10^18

Jadi masalah tidak akan muncul setiap kali kita memerlukan

reward < uint(-1) / UNIT

Perbaikan pada setRewardsDuration untuk memungkinkan pembaruan setelah pengaturan awal

setRewardsDuration dimaksudkan untuk memungkinkan rewardsDuration diatur setelah durasi selesai. Namun, cacat pada require memungkinkan perubahan setelah pengaturan awal.

Kode saat ini:

require(periodFinish == 0 || blockamp > periodFinish);

Perubahan yang diusulkan:

require(blockamp > periodFinish);

Spesifikasi Teknis

  • Mewarisi kontrak Pausable dan menambahkan pengubah notPaused ke stake().
  • Batalkan transaksi notifyRewardAmount jika tingkat reward yang dihitung akan membayar lebih dari saldo kontrak selama periode reward.
  • Ubah require di setRewardsDuration agar hanya memeriksa apakah periode telah selesai.

Kasus Uji

Pausable

  • Harus revert ketika stake dipanggil saat paused true.
  • Harus mengizinkan panggilan stake berhasil saat paused false.

Perbaikan bug overflow

  • Harus revert notifyRewardAmount jika reward lebih besar dari saldo kontrak.
  • Harus revert notifyRewardAmount jika reward ditambah sisa dari periode sebelumnya lebih besar dari saldo kontrak.
  • Harus tidak revert notifyRewardAmount jika reward sama dengan saldo kontrak.

Perbaikan bug setRewardsDuration

  • Harus revert ketika mengatur setRewardsDuration sebelum periode selesai.
  • Harus memperbarui rewardsDuration ketika memanggil setRewardsDuration setelah periode reward selesai.

Nilai yang Dapat Dikonfigurasi (Melalui SCCP)

Harap daftarkan semua nilai yang dapat dikonfigurasi melalui SCCP dalam implementasi ini.

sip 69 slot

▲ Kembali ke atas

Platform Lainnya

rocket 168 slot

bahagia 77 slot login

ricardo casino

SARANA88BET

Berita Piala Dunia

power stars slot

haha788 slot

zii bet

slot luar negeri rajadewa138

Jika Anda memiliki pertanyaan, silakan kirim email ke [email protected]

▲ Kembali ke atas